Muitas vezes, quero obter o nome de login associado a um ID de usuário e, como é um caso de uso comum, decidi escrever uma função de shell para fazer isso. Enquanto eu uso principalmente distribuições GNU / Linux, tento escrever meus scripts para serem o mais portáveis possível e verificar se o que estou fazendo é compatível com POSIX.
Analisar /etc/passwd
A primeira abordagem que tentei foi analisar /etc/passwd
(usando awk
).
awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
No entanto, o problema dessa abordagem é que os logins podem não ser locais, por exemplo, a autenticação do usuário pode ser via NIS ou LDAP.
Use o getent
comando
O uso getent passwd
é mais portátil do que a análise, /etc/passwd
pois também consulta bancos de dados NIS ou LDAP não locais.
getent passwd "$uid" | cut -d: -f1
Infelizmente, o getent
utilitário não parece ser especificado pelo POSIX.
Use o id
comando
id
é o utilitário padronizado do POSIX para obter dados sobre a identidade de um usuário.
As implementações BSD e GNU aceitam um ID do usuário como um operando:
- id (1) - páginas de manual do OpenBSD
- id (1) - Página de manual do FreeBSD
- GNU Coreutils: chamada de identificação
Isso significa que ele pode ser usado para imprimir o nome de login associado a um ID do usuário:
id -nu "$uid"
No entanto, fornecer IDs do usuário como operando não é especificado no POSIX; descreve apenas o uso de um nome de login como o operando.
Combinando todas as opções acima
Eu considerei combinar as três abordagens acima em algo como o seguinte:
get_username(){
uid="$1"
# First try using getent
getent passwd "$uid" | cut -d: -f1 ||
# Next try using the UID as an operand to id.
id -nu "$uid" ||
# As a last resort, parse `/etc/passwd`.
awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
}
No entanto, isso é desajeitado, deselegante e - mais importante - não robusto; sai com um status diferente de zero se o ID do usuário for inválido ou não existir. Antes de escrever um script de shell mais longo e desajeitado que analise e armazene o status de saída de cada chamada de comando, pensei em perguntar aqui:
Existe uma maneira mais elegante e portátil (compatível com POSIX) de obter o nome de login associado a um ID do usuário?
getent
nem id
vai retornar nada passado o primeiro jogo; a única maneira de encontrar todos eles é enumerar todos os usuários, se o banco de dados do usuário permitir. (Procurando /etc/passwd
trabalhos para usuários definidos lá, obviamente).
/etc/passwd
e /etc/shadow
para testar esse cenário e verifiquei que ambos id
e getent passwd
se comportam como você descreve. Se, em algum momento, eu acabar usando um sistema em que um usuário tem vários nomes, farei o mesmo que esses utilitários de sistema e simplesmente tratarei a primeira ocorrência como o nome canônico desse usuário.
setuid(some_id)
, e não há requisitos que some_id
possam fazer parte de qualquer banco de dados do usuário. Com coisas como namespaces de usuário no Linux, isso pode se tornar uma suposição incapacitante para seus scripts.
getpwuid()
função que ls
usa para converter UIDs em nomes de login. A resposta de Gilles é uma maneira mais direta e eficiente de conseguir isso.