Como um shell conhece o (s) lar (es)?

25

Cada shell possui uma variável de ambiente $ HOME definida (ex:) /Users/lotolo. Se eu estiver no csh, eu posso unsetenv HOMEe ainda assim cd, estarei em minha casa. Eu testei isso também no bash ( unset HOME) e é o mesmo comportamento. Então, como o shell sabe onde está o meu / other_user? Onde ele lê esses valores?

Isso não é uma duplicata, pois minha pergunta não é como eu sei, mas como o shell sabe HOME. E esse comportamento também é estendido a outros usuários.

LotoLo
fonte
11
@StephenKitt, não, não uma duplicata. Aqui estamos falando do comportamento do shell para o diretório inicial do usuário atual.
Stéphane Chazelas
No caso simples de /etc/passwd. Alguns sistemas podem armazenar essa informação em LDAP, servidores NIS, etc.
Satō Katsura
11
Programas (incluindo conchas) apenas ligam getpwuid(3)ou similares. Alguns sistemas podem ser configurados para "re-route" getpwuid(3)para obter informações de /etc/passwd, LDAP, NIS, NIS + etc.
Satō Katsura
@StephenKitt, veja a minha resposta
Stéphane Chazelas
11
@ GAD3R, veja a discussão acima, StephenKitt já havia apontado para a mesma duplicata (que ele retirou desde então), mas eu argumento acima (e veja também a minha resposta) que não é uma duplicata.
Stéphane Chazelas 28/11

Respostas:

33

No caso de cshe tcsh, ele registra o valor da $HOMEvariável no momento em que o shell foi iniciado ( em sua $homevariável conforme observado por @JdeBP ).

Se você desmarcá-lo antes de começar csh, verá algo como:

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

Para bash(e para a maioria das outras conchas tipo Bourne), vejo um comportamento diferente do seu.

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

O conteúdo da $HOMEvariável é inicializado pelo processo de login com base nas informações armazenadas no banco de dados do usuário com relação ao seu nome de usuário .

As informações sobre o próprio nome do usuário nem sempre estão disponíveis. Tudo que um shell pode ter certeza é o ID do usuário do processo que está sendo executado e vários usuários (com diretórios pessoais diferentes) podem compartilhar o mesmo ID do usuário.

Assim, uma vez $HOMEterminado, não há maneira confiável de recuperá-lo.

Consultar o banco de dados do usuário (com getpwxxx()API padrão) para o diretório inicial do primeiro usuário que possui o mesmo uid que o que executa o shell seria apenas uma aproximação (sem mencionar o fato de que o banco de dados do usuário poderia ter sido alterado (ou o endereço inicial) diretório definido como um valor único) desde que a sessão de login foi iniciada).

zsh é o único shell que eu sei que faz isso:

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

Todas as outras conchas que tentei queixam-se da HOME não configurada ou usam /como valor inicial padrão.

No entanto, é um comportamento diferente fish, que parece consultar o banco de dados pelo nome de usuário armazenado, $USERse houver, ou fazer um getpwuid()se não:

$ 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 quando o usuário não existe ( 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
fonte
2
Suponho que possamos relatar esse problema! Resposta muito boa btw, obrigado!
LotoLo 28/11
11
@LotoLo, sim, estou ocupado construindo com fisha cabeça dev git para ver se o bug está lá também. Editar. Sim.
Stéphane Chazelas 28/11
Agora estou curioso: qual variável de ambiente torna o shell hostil ao usuário se não estiver definido? PATH? TERM? USER?
user1024
Há uma linha ímpar aqui: "seria apenas uma aproximação ..." Os parênteses também não se alinham nesse parágrafo. O que deveria ser?
Muru
11
@muru Querying the user database... would only be...não é tão claro, de fato #
edc65 29/11
6

Então, como o shell sabe onde está o meu / other_user?

Não faz. Você não está realizando o experimento corretamente. Como você pode ver no manual do shell C, o cdcomando muda para o valor da homevariável, se fornecido sem argumentos. Se essa variável não estiver definida, ela não saberá para onde alterar o diretório e imprimirá um erro:

máquina: ~> definir casa = /
máquina: / home / user> cd
máquina: ~> casa não configurada
máquina: /> cd
cd: nenhum diretório inicial
máquina: /> 

Você desabilitou a variável errada. Não é HOME, a variável de ambiente, é homea variável interna do shell C (inicializada a partir do valor do primeiro quando o shell é inicializado, mas, caso contrário, é uma variável independente por si só).

JdeBP
fonte
não no csh (pelo menos na minha versão: "tcsh 6.18.01 (Astron) 14/02/2012 (x86_64-apple-darwin)") é a variável HOME que carrega o valor de casa. Mas, como @Stephane Chazelas disse, devo desmarcar a variável antes de iniciar o shell, pois ele definirá o valor HOME no início.
LotoLo 28/11
O exemplo acima é o shell C, que eu executei em uma máquina OpenBSD, e demonstra seu comportamento. Não é nem o shell TENEX C (embora isso se comporte da mesma forma).
JdeBP #
Sim, eu vi ... Eu digitei, cshmas aparentemente é um alias paratcsh
LotoLo 28/11
0

O sistema configurou a variável HOME no momento do login como um nome de caminho do diretório inicial do usuário. É definido por

  • gdm, kdm ou xdm para sessões gráficas.
  • login nas sessões do console, telnet e rlogin
  • sshd para conexões SSH

Você pode alterar seu valor, mas preste atenção, pois .bashrc, .profile, .xinitrc, etc. não serão lidos se não estiverem no diretório inicial.

Dababi
fonte
Mas posso desmarcá-lo ($ HOME) ... certo? E como ele sabe onde fica a casa de outro usuário?
LotoLo
11
você pode atualizá-lo usando o usermod -d HOME_DIRcomando, quando um novo usuário é criado. a página inicial padrão é / home / $ nome de usuário e é determinada pelo programa de login.
dabâbi