每个 shell 都有一个环境变量 $HOME 设置(例如:/Users/lotolo
)。如果我在 csh 之下,我可以unsetenv HOME
,而且如果我这样做,cd
我也会呆在家里。我也在 bash ( ) 上对此进行了测试,unset HOME
并且行为相同。那么 shell 如何知道 my/other_user 的家在哪里呢?它在哪里读取这些值?
这不是重复的,因为我的问题不是如何做我知道,但是怎么办贝壳知道HOME
。这种行为也扩展到其他用户。
答案1
csh
在和的情况下,它记录shell 启动时变量tcsh
的值($HOME
$home
在@JdeBP 指出的变量中)。
如果您在开始之前取消设置csh
,您会看到类似以下内容:
$ (unset HOME; csh -c cd)
cd: No home directory.
对于bash
(以及大多数其他类似 Bourne 的 shell),我看到的行为与您的行为不同。
bash-4.4$ unset HOME; cd
bash: cd: HOME not set
变量的内容$HOME
由登录过程根据用户数据库中存储的针对您的用户的信息进行初始化姓名。
有关用户名本身的信息并不总是可用。 shell 所能确定的只是正在执行它的进程的用户 ID,并且多个用户(具有不同的主目录)可以共享相同的用户 ID。
因此,一旦$HOME
消失,就没有可靠的方法可以将其找回来。
查询用户数据库(使用getpwxxx()
标准 API)查找与运行 shell 的用户具有相同 uid 的第一个用户的主目录只是一个近似值(更不用说用户数据库可能已更改(或主目录)目录被定义为一次性值)(自登录会话开始以来)。
zsh
是我所知道的唯一可以做到这一点的 shell:
$ env -u HOME ltrace -e getpw\* zsh -c 'cd && pwd'
zsh->getpwuid(1000, 0x496feb, 114, 0x7f9599004697) = 0x7f95992fddc0
/home/chazelas
+++ exited (status 0) +++
我尝试过的所有其他 shell 要么抱怨未设置 HOME,要么用作/
默认 home 值。
然而,不同的行为是fish
s,它似乎会查询数据库以获取存储在$USER
if any 中的用户名,或者执行getpwuid()
if not:
$ 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(https://github.com/fish-shell/fish-shell/issues/3599):
$ env -u HOME USER=foo fish -c ''
zsh: segmentation fault env -u HOME USER=foo fish -c ''
答案2
那么 shell 如何知道 my/other_user 的家在哪里呢?
事实并非如此。你只是没有正确地进行实验。正如您从 C shell 手册中看到的,如果不提供任何参数,该cd
命令将更改为变量的值。home
如果未设置此变量,它不知道将目录更改到哪里并打印错误:
机器:~> 设置主页=/ 机器:/home/用户> cd 机器:~> 取消设置主页 机器:/> cd cd: 无主目录 机器:/>
您取消设置了错误的变量。它不是HOME
环境变量,而是home
C shell 的内部变量(在 shell 启动时从前者的值初始化,但在其他情况下它本身就是一个独立变量)。
答案3
系统在登录时将 HOME 变量设置为用户主目录的路径名。它是由
- 用于图形会话的 gdm、kdm 或 xdm。
- 登录控制台、telnet 和 rlogin 会话
- sshd 用于 SSH 连接
您可以更改其值,但要注意,因为 .bashrc、.profile、.xinitrc 等文件如果不在主目录中,则不会被读取。