外壳如何知道房屋?


25

每个外壳程序都有一个环境变量$ HOME设置(例如:)/Users/lotolo。如果我在csh之下,我可以unsetenv HOME并且仍然可以,如果我这样做,cd我将在家里。我也在bash(unset HOME)上进行了测试,这是相同的行为。那么外壳如何知道我/ other_user的家在哪里?它在哪里读取这些值?

这不是重复的,因为我的问题不是怎么知道,而是shell如何知道HOME。并且此行为也扩展到其他用户。


1
@StephenKitt,不是重复的。这里我们谈论的是当前用户主目录的外壳行为。
斯特凡Chazelas

在的简单情况下/etc/passwd。某些系统可以将该信息存储在LDAP,NIS服务器等中。
SatōKatsura

1
程序(包括shell)只是调用getpwuid(3)或类似。某些系统可以配置为“重新路由” getpwuid(3)以从/etc/passwd,LDAP,NIS,NIS +等检索信息。
SatōKatsura 2016年

@StephenKitt,看到我的答案
斯特凡Chazelas

1
@ GAD3R,请参见上面的讨论,StephenKitt已经指出了相同的副本(他已撤回该副本),但是我在上面(也请参阅我的回答)指出,它不是副本。
斯特凡Chazelas

Answers:


33

在的情况下cshtcsh,它记录的值$HOME在壳开始(时间变量在其$home可变由@JdeBP指出)。

如果您在启动之前取消设置csh,则会看到类似以下内容的内容:

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

对于bash(以及大多数其他类似Bourne的贝壳),我看到的行为与您的行为不同。

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

$HOME变量的内容由登录过程根据用户数据库中存储的用户信息初始化。

有关用户名本身的信息并非始终可用。Shell只能确定正在执行它的进程的用户ID,并且几个用户(具有不同的主目录)可以共享同一用户ID。

因此,一旦$HOME消失了,就没有可靠的方法来取回它。

在用户数据库(使用getpwxxx()标准API)中查询第一个具有与运行Shell的用户具有相同uid的uid的用户的主目录,这只是一个近似值(更不用说用户数据库可能已更改(或主目录)自登录会话开始以来,目录被定义为一个时间值)。

zsh 我知道的唯一的壳就是这样做的:

$ 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,它似乎是在数据库中查询存储在其中的用户名($USER如果有的话),或者getpwuid()如果不是:

$ 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
我想我们可以报告此问题!顺便说一句很好的答案,谢谢!
LotoLo

1
@LotoLo,是的,我正忙于使用fishdev git head进行构建,以查看该错误是否也存在。编辑。是的。
斯特凡Chazelas

现在我很好奇:如果未设置,哪个环境变量会使外壳对用户最大程度的不友好? PATHTERMUSER
user1024 2016年

这里有一条奇数行:“只会是一个近似值……”该段中的括号也没有对齐。那应该是什么?
muru

1
@muru Querying the user database... would only be...确实不太清楚
edc65 '16

6

那么外壳如何知道我/ other_user的家在哪里?

没有。您只是没有正确执行实验。从C Shell手册中可以看到,如果不提供参数,该cd命令将更改为home变量的值。如果未设置此变量,则它不知道将目录更改到何处并显示错误:

机器:〜>设为首页= /
机器:/ home / user> cd
机器:〜>未设置首页
机器:/> cd
cd:没有主目录
机器:/> 

您未设置错误的变量。它不是HOME环境变量,而是homeC外壳程序的内部变量(在外壳程序启动时从前者的值初始化,否则单独使用自变量)。


在csh上不存在(至少在我的版本中:“ tcsh 6.18.01(Astron)2012-02-14(x86_64-apple-darwin)”),它是带有home值的HOME变量。但是正如@Stephane Chazelas所说,我必须在启动外壳之前取消设置变量,因为它将在启动时设置HOME值。
LotoLo

上面 C外壳程序,我在方便的OpenBSD机器上运行它,并演示了其行为。它甚至不是TENEX C shell(尽管其行为相同)。
JdeBP '16

是的,我看到了...我打了,csh但显然是别名tcsh
LotoLo '16

0

系统在登录时将HOME变量设置为用户主目录的路径名。它是由

  • gdm,kdm或xdm用于图形会话。
  • 在控制台,telnet和rlogin会话上登录
  • SSH连接的sshd

您可以更改其值,但要注意,因为如果.bashrc,.profile,.xinitrc等不在主目录中,则它们不会被读取。


但是我可以取消设置($ HOME)...对吗?怎样知道另一个用户的家?
LotoLo

1
usermod -d HOME_DIR创建新地址后,您可以使用命令进行更新。默认的主目录是/ home / $ username,它由登录程序确定。
达巴比
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.