¿Cuál es la forma más fácil de obtener el nombre completo de un usuario en un sistema Linux / POSIX?

StackOverflow https://stackoverflow.com/questions/833227

Pregunta

Podría pasar a través de / etc / passwd pero eso parece oneroso. 'finger' no está instalado y me gustaría evitar esa dependencia. Esto es para un programa, por lo que sería bueno si hubiera algún comando que le permitiera acceder a la información del usuario.

¿Fue útil?

Solución

No especificas un lenguaje de programación, así que supondré que quieres usar el shell; Aquí hay una respuesta para los shells de Posix .

Dos pasos para esto: obtenga el registro apropiado, luego obtenga el campo que desea de ese registro.

Primero, el registro de la cuenta se realiza consultando la tabla passwd :

$ user_name=foo
$ user_record="$(getent passwd $user_name)"
$ echo "$user_record"
foo:x:1023:1025:Fred Nurk,,,:/home/foo:/bin/bash

Para las pasas histéricas, el nombre completo del usuario se registra en un campo llamado " Campo "GECOS" ; Para complicar las cosas, este campo a menudo tiene su propia estructura con el nombre completo como uno de los varios subcampos opcionales . Por lo tanto, cualquier cosa que desee obtener el nombre completo del registro de la cuenta debe analizar ambos niveles.

$ user_record="$(getent passwd $user_name)"
$ user_gecos_field="$(echo "$user_record" | cut -d ':' -f 5)"
$ user_full_name="$(echo "$user_gecos_field" | cut -d ',' -f 1)"
$ echo "$user_full_name"
Fred Nurk

Su lenguaje de programación probablemente tenga una función de biblioteca para hacer esto en menos pasos. En C, usaría la función "getpwnam" y luego analizaría el campo GECOS.

Otros consejos

En un sistema glibc moderno, use este comando:

getent passwd "username" | cut -d ':' -f 5

Eso le proporcionará la entrada passwd del usuario especificado, independientemente del módulo NSS subyacente.

Lea la página de manual de getent .


Si ya está programando, puede usar la función C getpwnam () :

struct passwd *getpwnam(const char *name);

La estructura passwd tiene un miembro pw_gecos que debe contener el nombre completo del usuario.

Lea la página de manual de getpwnam () .


Tenga en cuenta que muchos sistemas usan este campo para más que el nombre completo del usuario. La convención más común es usar una coma (, ) como separador dentro del campo y colocar el nombre real de los usuarios primero.

En caso de que quiera hacer esto desde C, intente algo como esto:

#include <sys/types.h>
#include <pwd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

/* Get full name of a user, given their username. Return 0 for not found,
   -1 for error, or 1 for success. Copy name to `fullname`, but only up
   to max-1 chars (max includes trailing '\0'). Note that if the GECOS
   field contains commas, only up to to (but not including) the first comma
   is copied, since the commas are a convention to add more than just the
   name into the field, e.g., room number, phone number, etc. */
static int getfullname(const char *username, char *fullname, size_t max)
{
    struct passwd *p;
    size_t n;

    errno = 0;
    p = getpwnam(username);
    if (p == NULL && errno == 0)
        return 0;
    if (p == NULL)
        return -1;
    if (max == 0)
        return 1;
    n = strcspn(p->pw_gecos, ",");
    if (n > max - 1)
        n = max - 1;
    memcpy(fullname, p->pw_gecos, n);
    fullname[n] = '\0';
    return 1;
}

int main(int argc, char **argv)
{
    int i;
    int ret;
    char fullname[1024];

    for (i = 1; i < argc; ++i) {
        ret = getfullname(argv[i], fullname, sizeof fullname);
        if (ret == -1)
            printf("ERROR: %s: %s\n", argv[i], strerror(errno));
        else if (ret == 0)
            printf("UNKONWN: %s\n", argv[i]);
        else
            printf("%s: %s\n", argv[i], fullname);
    }
    return 0;
}

Combinación de otras respuestas, probadas en instalaciones mínimas de Debian / Ubuntu:

getent passwd `whoami` | cut -d ':' -f 5 | cut -d ',' -f 1

Prueba esto:

getent passwd eutl420 | awk -F':' '{gsub(",", "",$5); print $5}'

Las dos respuestas principales se pueden combinar en una línea:

getent passwd <username> | cut -d ':' -f 5 | cut -d ',' -f 1

Mi código funciona en bash y ksh, pero no en el tablero o en el viejo shell Bourne. También lee los otros campos, en caso de que los desee.

IFS=: read user x uid gid gecos hm sh < <( getent passwd $USER )
name=${gecos%%,*}
echo "$name"

También puede escanear todo el archivo / etc / passwd. Esto funciona en shell Bourne simple, en 1 proceso, pero no tanto con LDAP o qué.

while IFS=: read user x uid gid gecos hm sh; do
  name=${gecos%%,*}
  [ $uid -ge 1000 -a $uid -lt 60000 ] && echo "$name"
done < /etc/passwd

Por otro lado, usar herramientas es bueno. Y C también es bueno.

La forma en que lo imaginé en Linux para obtener el nombre completo en una variable fue:

u_id=`id -u`
uname=`awk -F: -vid=$u_id '{if ($3 == id) print $5}' /etc/passwd`

Luego, simplemente use la variable, por ejemplo: $ echo $ uname

Toma 1:

$ user_name=sshd
$ awk -F: "\$1 == \"$user_name\" { print \$5 }" /etc/passwd
Secure Shell Daemon

Sin embargo, la base de datos passwd admite caracteres especiales '& amp;' en gecos, que debe reemplazarse con el valor en mayúscula del nombre de usuario:

$ user_name=operator
$ awk -F: "\$1 == \"$user_name\" { print \$5 }" /etc/passwd
System &

La mayoría de las respuestas aquí (excepto la solución de dedo) no respetan & amp ;. Si desea apoyar este caso, necesitará un script más complicado.

Toma 2:

$ user_name=operator
$ awk -F: "\$1 == \"$user_name\" { u=\$1; sub(/./, toupper(substr(u,1,1)), u);
    gsub(/&/, u, \$5); print \$5 }" /etc/passwd
System Operator

El viejo y bueno dedo también puede ayudar :-)

finger $USER |head -n1 |cut -d : -f3
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top