Quem define as variáveis ​​de ambiente $ USER e $ USERNAME?

34

Além disso, essas variáveis ​​sempre correspondem ao nome de usuário atualmente conectado (no meu sistema Debian)? Posso assumir a disponibilidade deles em outros sistemas Unix (como)?

Também estou curioso por que alguém usaria, em whoamivez de apenas ler qualquer uma dessas variáveis.

tshepang
fonte
2
Olhando para a manpágina, whoamirelata o nome associado ao seu ID de usuário efetivo. O que significa que ele retornará algo diferente se você estiver usando sudoou executando um executável setuid. Se você sudoconfigurou, tente sudo whoamipor exemplo.
Joseph R.
4
USERe USERNAMEsão variáveis ​​de ambiente comuns, o que significa que, se desejar, você pode configurá-las para valores arbitrários. Apenas digite USER=xyz. Em outras palavras, mesmo se essas variáveis ​​existirem, não há garantia de que seus valores correspondam ao nome de usuário atualmente conectado.
Uwe
@ Uwe By guarantee, eu quis dizer por padrão (ou seja, assumindo que o usuário não os alterou).
Tshepang
2
@Tshepang Como seguimento ao meu primeiro comentário: comparar os resultados de sudo whoamiesudo echo $USER
Joseph R.
2
@JosephR. Pois sudo echo $USER, o shell se expande $USERe depois chama sudo. Então é claro que não produz a mesma saída que whoami. Como sudo whoami, sudo sh -c 'echo $USER'normalmente produz root. Em relação ao seu comentário sobre o whoamiuso do EUID , observe que ele sudo whoamisairia rootmesmo se whoamiusado o UID. sudoconjuntos tanto EUID e UID para o comando é executado (exceto na situação muito incomum que você configurá-lo explicitamente para se comportar de outra forma). Compare sudo id -ucom sudo id -ru.
Eliah Kagan

Respostas:

29

É login .

A página do manual de login do Linux (1) diz:

O valor para $ HOME , $ USER , $ SHELL , $ PATH , $ LOGNAME e $ MAIL são definidos de acordo com os campos apropriados na entrada da senha.

A página de manual de login do FreeBSD (1) diz:

O utilitário de login insere informações no ambiente (consulte o ambiente (7) ) especificando o diretório inicial do usuário (HOME), o interpretador de comandos (SHELL), o caminho de pesquisa (PATH), o tipo de terminal (TERM) e o nome do usuário (LOGNAME e USER) .

As páginas de manual do NetBSD , OpenBSD e OS X dizem a mesma coisa.

Aqui está o código fonte do login do util-linux:

setenv("HOME", pwd->pw_dir, 0); /* legal to override */
setenv("USER", pwd->pw_name, 1);
setenv("SHELL", pwd->pw_shell, 1);
/* ... */
setenv("LOGNAME", pwd->pw_name, 1);

Aqui está o código fonte do login do FreeBSD:

(void)setenv("LOGNAME", username, 1);
(void)setenv("USER", username, 1);
(void)setenv("PATH", rootlogin ? _PATH_STDPATH : _PATH_DEFPATH, 0);
poige
fonte
2
Na minha caixa do Fedora 16, eu tenho ambos USERe USERNAMEset e seu comando apenas retorna LOGNAME.
Joseph R.
11
. @JosephR, infelizmente, eu não tenho Fedora nas mãos, mas eu olhei para fontes do FreeBSD, bem como, ver UPD ..
poige
Mas este obviamente não é o caso do Fedora. Tudo o que estou dizendo é loginque não parece ser a única coisa que define essas variáveis.
Joseph R.
11
Note que o Linux é apenas um kernel, não possui um logincomando. Os sistemas operacionais que usam Linux como seu kernel são livres para usar qualquer implementação que desejarem. Por exemplo, sistemas baseados no Debian tendem a usar o sistema shadow-utils, não o util-linux.
Stéphane Chazelas
11
Observe que loginmuitas vezes não é invocado ao efetuar login na sshmaioria dos gerenciadores de login gráficos.
Stéphane Chazelas
11

Não há regra. Algumas conchas gostam tcshou zshcolocam $LOGNAME. zshconjuntos $USER.

Pode ser definido por algumas coisas que você fazer login como login(como invocado por gettyquando o login em um terminal e às vezes por outras coisas como in.rlogind), cron, su, sudo, sshd, rshd, gerenciadores de login gráfica ou não.

No entanto, se houver um login, na minha experiência, $USERgeralmente é definido (mas pode não ser atualizado após uma alteração na identificação do usuário (através de comandos setuid) nessa sessão de login.O POSIX exige que $LOGNAMEseja definido no login (e cron).

Para obter o nome de login de forma portável, o melhor é usar o lognamecomando (se não houver nenhum login, ele poderá retornar nada). Para obter o ID do usuário, use id -u. Para obter um nome de usuário correspondente à corrente id efetivo de usuário: id -un. Para obter todos eles (na maioria das vezes, há apenas um nome de usuário por ID de usuário, mas isso não é garantido):

perl -le 'while ($n = getpwent()) {print $n if getpwnam($n) == $>}'

Embora isso possa não funcionar em sistemas onde o banco de dados do usuário não pode ser enumerado (como acontece às vezes com os bancos de dados do usuário em rede, por exemplo).

Stéphane Chazelas
fonte
3

Você provavelmente deseja confiar no padrão POSIX aqui, pois em algum momento você provavelmente se preocupará não apenas com o login do usuário (gerenciado pelo loginprograma), mas também com crontrabalhos e afins.

Portanto, você deve saber que o POSIX exige, $LOGNAMEmas não $USER. Por exemplo, $USERpode não ser definido pelo cron, como indicado em uma resposta de Keith Thompson , que também faz referência a um histórico de como isso se relaciona ao histórico do System-V vs BSD:

... pelo menos no meu sistema (Ubuntu 14.04), a variável de ambiente $ USER não está definida para trabalhos cron. Em vez disso, você pode usar $ LOGNAME, que faz parte do ambiente para tarefas cron.

De acordo com a página do manual environ (7) (digite man environ para lê-lo), $ USER é usado por programas derivados do BSD e $ LOGNAME é usado pelos programas derivados do System V.

nealmcb
fonte
1

Se você deseja usar as variáveis ​​de ambiente (em vez de whoamiou getpwente getpwnam) e não tem certeza se elas sempre são definidas da mesma maneira em todos os sistemas * NIX, tente isso no bash:

THIS_USER=${USER:-${USERNAME:-${LOGNAME}}}
echo ${THIS_USER}

Se ainda estiver vazio depois de tudo isso, você estará em um sistema bastante esotérico. ;)

Jesse Chisholm
fonte