Listar todos los usuarios humanos

19

¿Cómo puedo enumerar todos los usuarios humanos que he creado? Lo he intentado cat /etc/passwdy solo enumera muchas cosas.

anatoly techtonik
fuente

Respuestas:

18

Los usuarios humanos tienen UID que comienzan en 1000, por lo que puede usar ese hecho para filtrar a los no humanos:

cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1

Esto corta los campos delimitados por dos puntos primero (nombre de usuario) y tercero (UID) /etc/passwd, luego filtra las líneas resultantes que terminan con dos puntos y cuatro dígitos, luego corta el primer campo (nombre de usuario) de ese, dejándolo con una lista de usuarios con UID entre 1000 y 9999.

Si tiene más de nueve mil usuarios en su sistema, esto fallará, pero es necesario restringir el resultado a UID de 4 dígitos para no detectarlo nobody(UID 65534).


fuente
15

Esto hace más o menos lo que hace la respuesta aceptada , solo en un comando en lugar de tres:

awk -F: '$3 >= 1000 && $1 != "nobody" {print $1}' /etc/passwd

Y gracias a Karel en los comentarios, el nobodyusuario también se filtra.

Oli
fuente
@karel Sí, tal vez. En lugar de filtrar por UID, estoy filtrando ese nombre de usuario explícitamente. Puede haber una razón para tener un usuario legítimo con un UID tan alto ... Quién sabe;)
Oli
9

Personalmente me gusta usar solo:

ls /home

Es cierto que esta no es una lista de usuarios, sino una lista de sus directorios de inicio. Los usuarios humanos actualmente existentes en el sistema tendrán directorios de inicio /home, pero también puede ver los directorios de inicio de los usuarios anteriores que fueron eliminados.

Esto funciona para mis propósitos y puede funcionar para los suyos también. Por ejemplo, si está buscando eliminar una cuenta de usuario que ya no existe ( nonexistent-user) y ejecutar el comando

sudo deluser nonexistent-user

solo le dirá que este usuario no existe.

Sam Hamblin
fuente
+1 De esta manera es simple, es lo que los usuarios más experimentados harían realmente, y creo que no es menos robusto que los métodos que verifican un rango de UID. Parece menos probable que un usuario humano tenga un directorio de inicio externo /home(que no esté vinculado a un enlace simbólico /home) que un usuario humano que tenga un UID de menos de 1000 (después de todo, este es el método más común para evitar que un administrador de visualización aparezca en la lista un usuario en la pantalla de inicio de sesión, que a veces puede hacerse para un usuario humano). La única desventaja relativamente menor aquí es que lost+foundse enumerará en sistemas con /homeparticiones separadas .
Eliah Kagan
Pequeño problema, sin embargo: ¿qué sucede si el usuario fue creado con useradd --no-create-home username?
Sergiy Kolodyazhnyy
@Serg Creo que todo se reduce a la ambigüedad inherente en la descripción del problema. ¿Una cuenta sin directorio de inicio representa realmente un usuario humano? En la práctica, tales cuentas generalmente se usan, aunque no siempre es cierto, para tareas altamente especializadas (generalmente por personas con sus propias cuentas separadas) o para usuarios destinados a acceder al sistema solo a través de servicios específicos y restringidos. Por supuesto, hay otro caso de uso para: el useradd --no-create-homedirectorio de inicio podría ya existir o podría crearse poco después, pero el ls /homemétodo funciona bien para esos casos.
Eliah Kagan
4

Si bien puede parecer una idea clara, en realidad existe una ambigüedad en el significado del usuario humano . ¿Se oculta deliberadamente una cuenta de usuario de la pantalla de inicio de sesión porque solo se usa para fines especializados (pero por humanos) un usuario humano? ¿Qué tal el ubuntuusuario (UID 999) en el CD en vivo? Y las cuentas de invitado en Ubuntu se crean sobre la marcha y se destruyen después de cerrar sesión; son usuarios humanos? Se podrían idear más ejemplos.

Por lo tanto, es apropiado que se hayan dado múltiples respuestas no equivalentes. La solución de ejecución de Saige Hamblinls /home es lo que la gente realmente hace, y a menos que esté escribiendo un script, probablemente debería usar eso.

Haciendo ls /homemás robusto

Pero quizás tenga usuarios que han sido eliminados, pero cuyos directorios principales todavía existen /home, y debe evitar enumerarlos. O tal vez por alguna otra razón, debe asegurarse de que solo /homese enumeren las entradas que corresponden a cuentas reales.

En ese caso, sugiero pasar los nombres de todo lo /homeque getent(para recuperar las passwdentradas de los usuarios con los nombres), sólo el campo nombre de usuario a continuación, aislar y visualizar (con grep, sedo awk, según su preferencia). Cualquiera de estos hará:

getent passwd $(ls /home) | grep -o '^[^:]*'
getent passwd $(ls /home) | sed 's/:.*//'
getent passwd $(ls /home) | awk -F: '{print $1}'

Esto debería funcionar bien, ya que no debería tener cuentas de usuario con espacios en blanco o caracteres de control en sus nombres; no puede, sin reconfigurar Ubuntu para permitirlo ; y si lo haces, tienes mayores problemas. Por lols tanto, los problemas habituales con el análisis no son aplicables. Pero a pesar de que está realmente bien aquí, si considera las sustituciones de comandos con lsdesagrado estético o simplemente un mal hábito, puede preferir:

getent passwd $(basename -a /home/*) | grep -o '^[^:]*'
getent passwd $(basename -a /home/*) | sed 's/:.*//'
getent passwd $(basename -a /home/*) | awk -F: '{print $1}'

Estos tampoco admiten espacios en blanco ni caracteres de control. Los proporciono solo porque se $(ls /home)ve mal incluso cuando es correcto y, por lo tanto, afecta a muchos usuarios de la manera incorrecta. En la mayoría de las situaciones, existen buenas razones reales para evitar el análisisls , y en esas situaciones, el análisis basename -asuele ser solo un poco menos malo. En esta situación, sin embargo, debido a la limitación sobre qué caracteres pueden aparecer prácticamente en los nombres de usuario , ambos están bien.

Explicación, beneficios y desventajas

Lo uso getentprincipalmente porque acepta nombres de usuario como argumentos para restringir su salida, pero también porque es un poco más universal que examinar /etc/passwddirectamente, en caso de que los servicios de red proporcionen servicios de autenticación y la base de datos de contraseñas.

Este método tiene la ventaja adicional de ls /homeque, en sistemas con una /homepartición separada , lost+foundgeneralmente aparece en la salida de ls /home.

  • Con el método más robusto presentado anteriormente, lost+foundsolo aparecerá si se llama a un usuario (humano o no) lost+found, lo cual es poco probable.
  • Pero si está ingresando comandos de manera interactiva en lugar de escribir un script, ls /homeestá bien , sabe que no tiene un usuario humano llamado lost+found.

Con poca frecuencia, este método (en cualquiera de las variaciones anteriores) producirá resultados insatisfactorios:

  • Si el directorio de inicio de un usuario existe fuera /home, o no existe , esto sugiere, pero no implica, que la cuenta no debe considerarse como un usuario humano. Este método solo enumera los usuarios cuando hay un directorio con el mismo nombre /home.
  • Si ha creado directorios adicionales en /home que no son en realidad el directorio de inicio de nadie, y tienen el mismo nombre que un usuario no humano existente, o consisten en palabras separadas por espacios en blanco, uno o más de los cuales tienen el mismo nombre como un usuario no humano existente, entonces algunos usuarios no humanos pueden incluirse en la salida.
    (Este método se puede implementar con un bucle e getentinvocaciones separadas , por lo que la división de palabras no produce resultados espurios. Pero la complejidad no está garantizada; fundamentalmente, si utiliza /homealgo más que un lugar para los directorios de inicio de los usuarios, este método será no produce resultados confiables)

Hacer más simple la comprobación de UID

Si decide utilizar un método que verifica las ID de los usuarios para asegurarse de que estén en el rango probable de cuentas que representan seres humanos, como en la respuesta aceptada o la respuesta de Oli , sugiero esto por brevedad:

getent passwd | grep -oP '^[^:]+(?=:x:\d{4}:)'

Esto usa una expresión regular Perl ( -P) para mostrar:

  • texto al comienzo de una línea ( ^) que no contiene :s ( [^:]+): este es el primer campo, al igual :que el separador de campo enpasswd
  • que precede pero no incluye ((?= ) ) el campo de contraseña x: siempre debe serlo x, ya que en Ubuntu los hashes de contraseña se almacenan en la shadowbase de datos, no en la base de passwddatos legible en todo el mundo
  • y un campo UID que consta de exactamente 4 dígitos ( :\d{4}:).

Por lo tanto, esta es una variante significativamente más corta y algo más simple de la técnica en el respuesta aceptada . (La técnica descrita allí también funciona bien, y tiene la ventaja de ser portátil para sistemas que grepno son GNU / Linux y que no son compatibles -P).

Reconsiderando el rango de UID "humano"

Si desea acomodar UID muy altos y verificar nobodyexplícitamente, puede usar el método en la respuesta de Oli . Sin embargo, es posible que desee considerar si los usuarios con UID muy altos realmente deberían considerarse humanos, o si es más probable que sean otros usuarios no humanos con fines especiales (como nobody). En la práctica, tales usuarios, además, nobodyson poco comunes, por lo que realmente es una decisión de tu parte.

Un posible compromiso es enumerar a los usuarios en el rango de UID que en realidad se están asignando a usuarios recién creados que no son del "sistema". Puedes verificar esto enadduser.conf :

$ grep -E '^(FIRST|LAST)_UID' /etc/adduser.conf
FIRST_UID=1000
LAST_UID=29999

Aquí hay dos formas de enumerar los usuarios cuyos UID varían de 1000 a 29999:

getent passwd | grep -oP '^[^:]+(?=:x:[12]?\d{4}:)'
getent passwd | awk -F: '999<$3 && $3<30000 {print $1}'
Eliah Kagan
fuente
Si querías ser estilísticamente agradable, basenamees feo. No es mejor que ls. La razón principal por la que no analizamos ls es que es un trabajo que pueden realizar otras herramientas de manera mucho más segura y limpia, no con estilo. En este caso, el Shell: cd /home; getent passwd *.
Muru
Estoy de acuerdo con que usted / home no sea confiable (es inútil para mí, vea mi respuesta). Solo digo que si va a predicar sobre el estilo, espere bromas.
Muru
@muru Veo cómo mi fraseo original podría inducir a error a la gente a pensar que evitar el análisis lsgeneralmente se trata de estilo. El segundo punto sobre "resultados insatisfactorios" cubrió el problema, pero aparece en una sección posterior. Volví a redactar para aclarar por qué el análisis lses apropiado en esta situación . Aunque cd /home; getent passwd *adopte una forma a menudo indicativa de un enfoque más sólido, lo he evitado para no llevar a los lectores a creer que el contenido de los /homedirectorios, con entradas añadidas extrañas que no corresponden a usuarios reales, podría de alguna manera ser considerado como una guía de lo que los usuarios existen
Eliah Kagan
1

TL; DR : solo usuarios humanos tienen SystemAccount = false

Otra forma es enumerar la salida de mientras se ignora la raíz ls /var/lib/AccountsService/users/ | grep -v root. Ahora, hay una peculiaridad: gdm, una pantalla de bienvenida / inicio de sesión (o más formalmente un administrador de escritorio) también aparece como usuario. Entonces, solo de la lista no podemos decir si gdm es humano o no.

Un enfoque más eficiente y correcto es revisar los archivos en esa carpeta y descubrir qué usuarios están en la lista SystemAccount=false. El bramido de una línea logra que

grep SystemAccount=false /var/lib/AccountsService/users/* | awk -F '/' '{gsub(":","/");print $6}'

Sergiy Kolodyazhnyy
fuente
1
Aunque a veces es útil, esto falla en algunos escenarios relativamente comunes. Por ejemplo, en mi sistema mínimo Ubuntu 15.04 (instalado desde mini.isoy sin administradores de pantalla o X11 instalado), tengo una cuenta de usuario humano, pero /var/lib/AccountsService/userses un directorio vacío. Espero que esto no funcione de manera similar en una instalación de Ubuntu Server lista para usar. Además, cuando esto funciona, lo hace bajo una noción algo restrictiva de lo que hace que una cuenta de usuario sea "humana": hacer que un usuario con useradd, incluso sin --system , no cree un archivo AccountsService/users.
Eliah Kagan
1

Al unirme a la fiesta, superviso los sistemas de red que utilizan LDAP, que tienen /homemillones de directorios externos y UID (debido a una falla en las secuencias de comandos). Ninguna de las respuestas actuales, por lo tanto, funciona. La prueba que funciona para mí es verificar si el usuario tiene un shell de inicio de sesión válido. Un shell válido es uno que se enumera en /etc/shells. La forma más simple:

getent passwd | grep -wFf /etc/shells

El archivo puede contener comentarios (o líneas vacías), por lo que es posible que tenga que filtrarlos:

getent passwd | grep -wFf <(grep '^/' /etc/shells)
muru
fuente
+1 Este puede ser el enfoque más sólido sugerido hasta ahora. Aunque tiene la desventaja de mostrarse root(que probablemente no debería considerarse un usuario humano, ya que los humanos generalmente se convierten en root temporalmente y para fines específicos, en lugar de usarlo para su trabajo regular), parece que es menos probable que falle Cualquier forma importante. Los métodos en otras respuestas (incluida la mía) pueden fallar, dependiendo del método, si no son los directorios de inicio en /home, otro tipo de basura es en /home, UID son extraños, o el sistema no utiliza un DM. Esta respuesta funciona bastante bien en todos esos escenarios.
Eliah Kagan
1

En los sistemas buntu, los usuarios habituales (es decir, usuarios humanos) tienen UID que comienzan con 1000 que se les asignan secuencialmente cuando se crean sus cuentas por primera vez. Todo esto se reduce a que la primera cuenta creada en un sistema buntu tiene un UID de 1000. La siguiente cuenta creada tiene un UID de 1001. Y así sucesivamente.

Entonces, la forma más simple de enumerar todas las cuentas de usuarios humanos presentes en el sistema, en mi opinión, es verificar si la tercera columna en el /etc/passwdarchivo que contiene el UID del usuario es mayor o igual a 1000 y menor que, digamos, 2000 (es muy poco probable que una PC de escritorio típica tenga más de mil cuentas de usuario, ¿no cree?):

$ awk -F$':' '{ if ($3 >= 1000 && $3 < 2000) print $1; }' /etc/passwd
misha
fuente
Gracias por explicar la respuesta de Oli con detalles. También necesitas filtrar nobody. =)
anatoly techtonik
1
No es necesario porque nadie tiene un UID de 65534 y, por lo tanto, se filtra automáticamente como todas las demás cuentas de usuarios no humanos.
misha