Comment un obus connaît-il sa (ses) maison (s)?

25

Chaque shell a une variable d'environnement $ HOME définie (ex:) /Users/lotolo. Si je suis sous csh, je peux unsetenv HOMEet encore si je le fais, cdje serai chez moi. J'ai également testé cela sur bash ( unset HOME) et c'est le même comportement. Alors, comment le shell sait-il où se trouve mon / autre_utilisateur? Où lit-il ces valeurs?

Ce n'est pas un doublon car ma question n'est pas de savoir comment je sais, mais comment le shell sait-il HOME. Et ce comportement est également étendu aux autres utilisateurs.

LotoLo
la source
1
@StephenKitt, non pas un doublon. Ici, nous parlons du comportement du shell pour le répertoire personnel de l'utilisateur actuel.
Stéphane Chazelas
Dans le cas simple de /etc/passwd. Certains systèmes peuvent stocker ces informations dans LDAP, des serveurs NIS, etc.
Satō Katsura
1
Les programmes (y compris les coquilles) appellent simplement getpwuid(3)ou similaires. Certains systèmes peuvent être configurés pour "réacheminer" getpwuid(3)pour récupérer des informations à partir de /etc/passwdLDAP, NIS, NIS + etc.
Satō Katsura
@StephenKitt, voir ma réponse
Stéphane Chazelas
1
@ GAD3R, voir la discussion ci-dessus, StephenKitt avait déjà indiqué ce même doublon (qu'il a depuis rétracté), mais je soutiens ci-dessus (et voir également ma réponse) qu'il ne s'agit pas d'un doublon.
Stéphane Chazelas

Réponses:

33

Dans le cas de cshet tcsh, il enregistre la valeur de la $HOMEvariable au moment du démarrage du shell ( dans sa $homevariable comme noté par @JdeBP ).

Si vous le désactivez avant de commencer csh, vous verrez quelque chose comme:

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

Pour bash(et la plupart des autres obus de type Bourne), je vois un comportement différent du vôtre.

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

Le contenu de la $HOMEvariable est initialisé par le processus de connexion sur la base des informations stockées dans la base de données utilisateur par rapport à votre nom d' utilisateur .

Les informations sur le nom d'utilisateur lui-même ne sont pas toujours disponibles. Tout ce qu'un shell peut savoir avec certitude, c'est l'ID utilisateur du processus qui l'exécute et plusieurs utilisateurs (avec des répertoires personnels différents) peuvent partager le même ID utilisateur.

Donc, une fois $HOMEparti, il n'y a aucun moyen fiable de le récupérer.

L'interrogation de la base de données utilisateur (avec getpwxxx()l'API standard) pour le répertoire personnel du premier utilisateur qui a le même uid que celui qui exécute le shell ne serait qu'une approximation (sans parler du fait que la base de données utilisateur aurait pu changer (ou le répertoire principal) répertoire étant défini comme une valeur unique) depuis le début de la session de connexion).

zsh est le seul shell que je connaisse qui fait ça:

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

Tous les autres shells que j'ai essayés se plaignent de ce HOME non défini ou utilisent /comme valeur par défaut.

Pourtant, un comportement différent est celui fishde, qui semble interroger la base de données pour le nom d'utilisateur stocké dans le $USERcas échéant ou faire un getpwuid()sinon:

$ 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 lorsque l'utilisateur n'existe pas ( 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 ''
Stéphane Chazelas
la source
2
Je suppose que nous pouvons signaler ce problème! Très belle réponse btw, merci!
LotoLo
1
@LotoLo, oui, je suis en train de construire avec fishla tête de développement de git pour voir si le bug est là aussi. Modifier. Oui, ça l'est.
Stéphane Chazelas
Maintenant, je suis curieux: quelle variable d'environnement rend le shell inutilisable au maximum s'il n'est pas défini? PATH? TERM? USER?
user1024
Il y a une ligne étrange ici: "ne serait qu'une approximation ..." Les parenthèses ne s'alignent pas dans ce paragraphe aussi. Qu'est-ce que c'était censé être?
muru
1
@muru Querying the user database... would only be...pas si clair en effet
edc65
6

Alors, comment le shell sait-il où se trouve mon / autre_utilisateur?

Ce n'est pas le cas. Vous ne faites tout simplement pas l'expérience correctement. Comme vous pouvez le voir dans le manuel du shell C, la cdcommande change la valeur de la homevariable si elle est fournie sans argument. Si cette variable n'est pas définie, elle ne sait pas où changer de répertoire et affiche une erreur:

machine: ~> définir la maison = /
machine: / home / utilisateur> cd
machine: ~> maison non réglée
machine: /> cd
cd: pas de répertoire personnel
machine: /> 

Vous annulez la mauvaise variable. Ce n'est pas HOMEla variable d'environnement, c'est homela variable interne du shell C (initialisée à partir de la valeur de la première au démarrage du shell, mais sinon une variable indépendante à part entière).

JdeBP
la source
non sur csh (au moins sur ma version: "tcsh 6.18.01 (Astron) 14/02/2012 (x86_64-apple-darwin)")) c'est la variable HOME portant la valeur de home. Mais comme @Stephane Chazelas l'a dit, je dois annuler la variable avant de lancer le shell car il définira la valeur HOME au démarrage.
LotoLo
Ce qui précède est le shell C, que j'ai exécuté sur une machine OpenBSD pratique, et montre son comportement. Ce n'est même pas le shell TENEX C (bien que cela se comporte de la même manière).
JdeBP
Oui, je l'ai vu ... J'ai tapé cshmais apparemment, il a un aliastcsh
LotoLo
0

Le système a défini la variable HOME au moment de la connexion comme étant un chemin d'accès au répertoire personnel de l'utilisateur. Il est défini par

  • gdm, kdm ou xdm pour les sessions graphiques.
  • connectez-vous aux sessions console, telnet et rlogin
  • sshd pour les connexions SSH

Vous pouvez changer sa valeur mais faites attention car .bashrc, .profile, .xinitrc, etc. ne seront pas lus s'ils ne sont pas dans le répertoire personnel.

Dababi
la source
Mais je peux le désactiver ($ HOME) ... non? Et comment sait-il où est la maison d'un autre utilisateur?
LotoLo
1
vous pouvez le mettre à jour à l'aide de la usermod -d HOME_DIRcommande, lorsqu'un nouvel usre est créé. le répertoire par défaut est / home / $ username et il est déterminé par le programme de connexion.
Dababi