Làm thế nào để một vỏ biết nhà (s)?


25

Mỗi shell có một biến môi trường $ HOME được đặt (ví dụ /Users/lotolo:). Nếu tôi ở dưới csh tôi có thể unsetenv HOMEvà vẫn nếu tôi làm thì cdtôi sẽ ở nhà. Tôi cũng đã thử nghiệm điều này trên bash ( unset HOME) và đó là hành vi tương tự. Vậy làm thế nào để shell biết nhà của tôi / other_user ở đâu? Nó đọc những giá trị đó ở đâu?

Đây không phải là một bản sao vì câu hỏi của tôi không phải là làm sao tôi biết, nhưng làm thế nào để cái vỏ biết HOME. Và hành vi này được mở rộng cho người dùng khác là tốt.


1
@StephenKitt, không không trùng lặp. Ở đây chúng ta đang nói về hành vi shell cho thư mục chính của người dùng hiện tại.
Stéphane Chazelas

Trong trường hợp đơn giản từ /etc/passwd. Một số hệ thống có thể lưu trữ thông tin đó trong LDAP, máy chủ NIS, v.v.
Satō Katsura

1
Các chương trình (bao gồm cả shell) chỉ cần gọi getpwuid(3)hoặc tương tự. Một số hệ thống có thể được định cấu hình để "định tuyến lại" getpwuid(3)để truy xuất thông tin từ /etc/passwd, LDAP, NIS, NIS +, v.v.
Satō Katsura

@StephenKitt, xem câu trả lời của tôi
Stéphane Chazelas

1
@ GAD3R, xem thảo luận ở trên, StephenKitt đã chỉ ra cùng một bản sao đó (mà anh ta đã rút lại), nhưng tôi tranh luận ở trên (và cũng xem câu trả lời của tôi) rằng đó không phải là một bản sao.
Stéphane Chazelas

Câu trả lời:


33

Trong trường hợp cshtcsh, nó ghi lại giá trị của $HOMEbiến tại thời điểm shell được khởi động ( trong $homebiến của nó như được ghi chú bởi @JdeBP ).

Nếu bạn bỏ đặt nó trước khi bắt đầu csh, bạn sẽ thấy một cái gì đó như:

$ (unset HOME; csh -c cd)
cd: No home directory.

Đối với bash(và hầu hết các vỏ giống như Bourne khác), tôi thấy một hành vi khác với vỏ của bạn.

bash-4.4$ unset HOME; cd
bash: cd: HOME not set

Nội dung của $HOMEbiến được khởi tạo bởi quá trình đăng nhập dựa trên thông tin được lưu trữ trong cơ sở dữ liệu người dùng so với tên người dùng của bạn .

Thông tin về tên người dùng không phải lúc nào cũng có sẵn. Tất cả các shell có thể biết chắc chắn là userid của quá trình đang thực thi nó và một số người dùng (với các thư mục nhà khác nhau) có thể chia sẻ cùng một userid.

Vì vậy, một khi $HOMEđã biến mất, không có cách nào đáng tin cậy để lấy lại.

Truy vấn cơ sở dữ liệu người dùng (với getpwxxx()API tiêu chuẩn) cho thư mục chính của người dùng đầu tiên có cùng uid với người chạy shell sẽ chỉ là một xấp xỉ (không đề cập đến thực tế là cơ sở dữ liệu người dùng có thể đã thay đổi (hoặc nhà thư mục được xác định là giá trị một lần) kể từ khi phiên đăng nhập bắt đầu).

zsh là cái vỏ duy nhất mà tôi biết làm điều đó:

$ env -u HOME ltrace -e getpw\* zsh -c 'cd && pwd'
zsh->getpwuid(1000, 0x496feb, 114, 0x7f9599004697)      = 0x7f95992fddc0
/home/chazelas
+++ exited (status 0) +++

Tất cả các shell khác tôi đã thử hoặc phàn nàn về việc hủy đặt HOME đó hoặc sử dụng /làm giá trị nhà mặc định.

Tuy nhiên, một hành vi khác là fish, dường như truy vấn cơ sở dữ liệu về tên người dùng được lưu trữ $USERnếu có hoặc thực hiện getpwuid()nếu không:

$ env -u HOME USER=bin ltrace -e getpw\* fish -c 'cd;pwd'
fish->getpwnam("bin")  = 0x7fd2beba3d80
fish: Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory
where the current user has write access.
fish: Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory
where the current user has write access.
--- SIGCHLD (Child exited) ---
/bin
+++ exited (status 0) +++


$ env -u HOME -u USER ltrace -e getpw\* fish -c 'cd;pwd'
fish->getpwuid(1000, 0x7f529eb4fb28, 0x12d8790, 0x7f529e858697) = 0x7f529eb51dc0
fish->getpwnam("chazelas")                                      = 0x7f529eb51d80
--- SIGCHLD (Child exited) ---
--- SIGCHLD (Child exited) ---
/home/chazelas
+++ exited (status 0) +++

SEGV khi người dùng không tồn tại ( https://github.com/fish-shell/fish-shell/issues35399 ):

$ env -u HOME USER=foo fish -c ''
zsh: segmentation fault  env -u HOME USER=foo fish -c ''

2
Tôi cho rằng chúng ta có thể báo cáo vấn đề này! Rất tốt đẹp trả lời btw, cảm ơn!
LotoLo

1
@LotoLo, vâng, tôi đang bận xây dựng với fishđầu phát triển để xem lỗi có ở đó không. Chỉnh sửa. Đúng vậy
Stéphane Chazelas

Bây giờ tôi tò mò: Biến môi trường nào làm cho vỏ tối đa không thân thiện với người dùng nếu không được đặt? PATH? TERM? USER?
dùng1024

Có một dòng lẻ ở đây: "sẽ chỉ là một xấp xỉ ..." Các dấu ngoặc đơn cũng không xếp hàng trong đoạn đó. Nó được cho là gì?
muru

1
@muru Querying the user database... would only be...thực sự không rõ ràng lắm
edc65

6

Vậy làm thế nào để shell biết nhà của tôi / other_user ở đâu?

Nó không. Bạn chỉ không thực hiện thí nghiệm đúng cách. Như bạn có thể thấy từ sổ tay shell C, cdlệnh sẽ thay đổi thành giá trị của homebiến nếu được cung cấp không có đối số. Nếu biến này không được đặt, nó không biết thay đổi thư mục ở đâu và in lỗi:

máy: ~> đặt nhà = /
máy: / nhà / người dùng> cd
máy: ~> bỏ đặt nhà
máy: /> cd
cd: Không có thư mục nhà
máy: /> 

Bạn bỏ đặt biến sai. Không phải HOMElà biến môi trường, nó là homebiến nội bộ của vỏ C (được khởi tạo từ giá trị của cái trước khi vỏ khởi động, nhưng nếu không thì là biến độc lập theo đúng nghĩa của nó).


không có trên csh (ít nhất là trên phiên bản của tôi: "tcsh 6.18.01 (Astron) 2012/02/14 (x86_64-apple-darwin)") đó là biến HOME mang giá trị gia đình. Nhưng như @Stephane Chazelas nói rằng tôi phải bỏ đặt biến trước khi khởi chạy shell vì nó sẽ đặt giá trị HOME khi bắt đầu.
LotoLo

Trên đây trình bao C, mà tôi đã chạy trên một máy OpenBSD tiện dụng và thể hiện hành vi của nó. Nó thậm chí không phải là vỏ TENEX C (mặc dù nó hoạt động giống nhau).
JdeBP

Vâng, tôi đã thấy nó ... Tôi đã gõ cshnhưng dường như nó được đặt bí danhtcsh
LotoLo

0

Hệ thống đặt biến HOME tại thời điểm đăng nhập là tên đường dẫn của thư mục chính của người dùng. Nó được thiết lập bởi

  • gdm, kdm hoặc xdm cho các phiên đồ họa.
  • đăng nhập vào phiên console, telnet và rlogin
  • sshd cho các kết nối SSH

Bạn có thể thay đổi giá trị của nó nhưng chú ý vì .bashrc, .profile, .xinitrc, v.v. sẽ không được đọc nếu chúng không có trong thư mục chính.


Nhưng tôi có thể bỏ đặt nó ($ HOME) ... phải không? Và làm thế nào để biết nhà của người dùng khác ở đâu?
LotoLo

1
bạn có thể cập nhật nó bằng usermod -d HOME_DIRlệnh, khi một usre mới được tạo. nhà mặc định là / home / $ tên người dùng và nó được xác định bởi chương trình đăng nhập.
Dababi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.