A menudo quiero obtener el nombre de inicio de sesión asociado con una ID de usuario y, debido a que se ha demostrado que es un caso de uso común, decidí escribir una función de shell para hacer esto. Si bien uso principalmente distribuciones GNU / Linux, trato de escribir mis scripts para que sean lo más portátiles posible y verificar que lo que estoy haciendo sea compatible con POSIX.
Analizar gramaticalmente /etc/passwd
El primer enfoque que intenté fue analizar /etc/passwd(usando awk).
awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
Sin embargo, el problema con este enfoque es que los inicios de sesión pueden no ser locales, por ejemplo, la autenticación del usuario podría ser a través de NIS o LDAP.
Usa el getentcomando
El uso getent passwdes más portátil que el análisis, /etc/passwdya que también consulta bases de datos NIS o LDAP no locales.
getent passwd "$uid" | cut -d: -f1
Desafortunadamente, la getentutilidad no parece estar especificada por POSIX.
Usa el idcomando
id es la utilidad estandarizada POSIX para obtener datos sobre la identidad de un usuario.
Las implementaciones BSD y GNU aceptan una ID de usuario como un operando:
- id (1) - páginas del manual de OpenBSD
- id (1) - Página del manual de FreeBSD
- GNU Coreutils: invocación de id
Esto significa que se puede usar para imprimir el nombre de inicio de sesión asociado con una ID de usuario:
id -nu "$uid"
Sin embargo, proporcionar ID de usuario como el operando no se especifica en POSIX; solo describe el uso de un nombre de inicio de sesión como operando.
Combinando todo lo anterior
Pensé en combinar los tres enfoques anteriores en algo como lo siguiente:
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
}
Sin embargo, esto es torpe, poco elegante y, lo que es más importante, no es robusto; sale con un estado distinto de cero si la ID de usuario no es válida o no existe. Antes de escribir un script de shell más largo y más grueso que analiza y almacena el estado de salida de cada invocación de comando, pensé en preguntar aquí:
¿Existe una forma más elegante y portátil (compatible con POSIX) de obtener el nombre de inicio de sesión asociado con una ID de usuario?
getentni iddevolverá nada después de la primera coincidencia; la única forma de encontrarlos todos es enumerar a todos los usuarios, si la base de datos de usuarios lo permite. (Buscando /etc/passwdobras para usuarios definidos allí, obviamente.)
/etc/passwd y /etc/shadowpara probar este escenario y verifiqué ambas cosas idygetent passwd como usted describe. Si, en algún momento, termino usando un sistema en el que un usuario tiene varios nombres, haré lo mismo que estas utilidades del sistema y simplemente trataré la primera aparición como el nombre canónico para ese usuario.
setuid(some_id), y no hay ningún requisito que some_idpueda ser parte de una base de datos de usuarios. Con cosas como los espacios de nombres de usuario en Linux, esto puede convertirse en una suposición paralizante para sus scripts.
getpwuid()función que se lsutiliza para traducir UID a nombres de inicio de sesión. La respuesta de Gilles es una forma más directa y eficiente de lograr esto.