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.


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 ''

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ó).


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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.