Как оболочка знает дом (ы)?

25

Каждая оболочка имеет переменную окружения $ HOME set (ex:) /Users/lotolo. Если я нахожусь под csh, я могу unsetenv HOMEи все еще, если я делаю, cdя буду в моем доме. Я проверял это также на bash ( unset HOME), и это то же самое поведение. Так как же оболочка узнает, где находится мой / other_user дом? Где он читает эти значения?

Это не дубликат, так как мой вопрос не в том, откуда я знаю, а в том, как оболочка узнает HOME. И это поведение распространяется и на других пользователей.

LotoLo
источник
1
@ StefhenKitt, нет, не дубликат. Здесь мы говорим о поведении оболочки для домашнего каталога текущего пользователя.
Стефан Шазелас
В простом случае из /etc/passwd. Некоторые системы могут хранить эту информацию на серверах LDAP, NIS и т. Д.
Satō Katsura
1
Программы (в том числе оболочки) просто звонят getpwuid(3)или аналогичны. Некоторые системы могут быть настроены на «перенаправление» getpwuid(3)для получения информации из /etc/passwdLDAP, NIS, NIS + и т. Д.
Satō Katsura
@StephenKitt, посмотри мой ответ
Стефан Шазелас
1
@ GAD3R, см. Обсуждение выше, СтивенКитт уже указал на тот же самый дубликат (который он с тех пор отозвал), но я утверждаю выше (и вижу также мой ответ), что это не дубликат.
Стефан Шазелас

Ответы:

33

В случае cshи tcshон записывает значение $HOMEпеременной во время запуска оболочки ( в ее $homeпеременной, как отмечено @JdeBP ).

Если вы отключите его перед запуском csh, вы увидите что-то вроде:

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

Для bash(и большинства других подобных Борну оболочек) я вижу поведение, отличное от вашего.

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

Содержимое $HOMEпеременной инициализируется процессом входа в систему на основе информации, хранящейся в базе данных пользователей, относительно вашего имени пользователя .

Информация о самом имени пользователя не всегда доступна. Оболочка может знать наверняка только идентификатор пользователя процесса, который ее выполняет, и несколько пользователей (с разными домашними каталогами) могут использовать один и тот же идентификатор пользователя.

Таким образом, после того, $HOMEкак ушел, нет надежного способа вернуть его.

Запрос к базе данных пользователей (со getpwxxx()стандартным API) для домашнего каталога первого пользователя, который имеет тот же uid, что и тот, в котором запущена оболочка, будет лишь приблизительным (не говоря уже о том, что база данных пользователей могла измениться (или домашний каталог). каталог определяется как одноразовое значение) с момента начала сеанса входа в систему).

zsh единственная известная мне оболочка, которая делает это:

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

Все остальные оболочки, которые я пробовал, либо жалуются на этот неустановленный HOME, либо используют /в качестве домашнего значения по умолчанию.

И все же другое поведение - это fish's', который, кажется, запрашивает в базе данных имя пользователя, сохраненное, $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, да, я занят fishразработкой с разработчиком, чтобы увидеть, есть ли ошибка. Редактировать. Да, это.
Стефан Шазелас
Теперь мне любопытно: какая переменная окружения делает оболочку максимально дружественной к пользователю, если не установлена? PATH? TERM? USER?
user1024
Здесь есть странная строка: «будет только приблизительным ...» Скобки в этом абзаце тоже не совпадают. Что это должно было быть?
Муру
1
@muru Querying the user database... would only be...не совсем понятно
edc65
6

Так как же оболочка узнает, где находится мой / other_user дом?

Это не так. Вы просто не проводите эксперимент должным образом. Как видно из руководства по оболочке C, cdкоманда меняется на значение homeпеременной, если она указана без аргументов. Если эта переменная не установлена, она не знает, где изменить каталог и выводит ошибку:

машина: ~> установить домой = /
машина: / home / user> cd
машина: ~> сброшенный дом
машина: /> CD
CD: Нет домашнего каталога
Машина: /> 

Вы сбросили неправильную переменную. Это не HOMEпеременная окружения, это homeвнутренняя переменная оболочки C (инициализируется из значения первого при запуске оболочки, но в остальном независимая переменная сама по себе).

JdeBP
источник
нет на csh (по крайней мере, в моей версии: "tcsh 6.18.01 (Astron) 2012-02-14 (x86_64-apple-darwin)") это переменная HOME, содержащая значение home. Но, как сказал @Stephane Chazelas, я должен сбросить переменную перед запуском оболочки, так как она установит значение HOME при запуске.
LotoLo
Выше является Си - оболочка, которую я провел на удобной OpenBSD машине, и демонстрирует свое поведение. Это даже не оболочка TENEX C (хотя она ведет себя одинаково).
JdeBP
Да, я видел это ... Я напечатал, cshно, по-видимому, это псевдонимtcsh
LotoLo
0

Система установила переменную HOME во время входа в систему в качестве пути к домашнему каталогу пользователя. Это установлено

  • gdm, kdm или xdm для графических сессий.
  • войти в систему на консольных, telnet и rlogin
  • sshd для соединений SSH

Вы можете изменить его значение, но обратите внимание, потому что .bashrc, .profile, .xinitrc и т. Д. Не будут прочитаны, если они не находятся в домашнем каталоге.

Dababi
источник
Но я могу сбросить его ($ HOME) ... верно? И как он узнает, где находится дом другого пользователя?
LotoLo
1
Вы можете обновить его с помощью usermod -d HOME_DIRкоманды, когда создается новый пользователь. по умолчанию home - это / home / $ username и определяется программой входа в систему.
Дабаби