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 getent
comando
El uso getent passwd
es más portátil que el análisis, /etc/passwd
ya que también consulta bases de datos NIS o LDAP no locales.
getent passwd "$uid" | cut -d: -f1
Desafortunadamente, la getent
utilidad no parece estar especificada por POSIX.
Usa el id
comando
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?
getent
ni id
devolverá 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/passwd
obras para usuarios definidos allí, obviamente.)
/etc/passwd
y /etc/shadow
para probar este escenario y verifiqué ambas cosas id
ygetent 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_id
pueda 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 ls
utiliza 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.