Lister tous les utilisateurs humains

19

Comment répertorier tous les utilisateurs humains que j'ai créés? J'ai essayé cat /etc/passwdet il énumère juste beaucoup de choses.

anatoly techtonik
la source

Réponses:

18

Les utilisateurs humains ont des UID commençant à 1000, vous pouvez donc utiliser ce fait pour filtrer les non-humains:

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

Cela coupe le premier (nom d'utilisateur) et le troisième (UID) champs délimités par les deux-points de /etc/passwd, puis filtre les lignes résultantes qui se terminent par deux-points et quatre chiffres, puis coupe le premier champ (nom d'utilisateur) de cela, vous laissant avec une liste de utilisateurs avec des UID compris entre 1000 et 9999.

Si vous avez plus de neuf mille utilisateurs sur votre système, cela échouera - mais il est nécessaire de limiter le résultat à des UID à 4 chiffres afin de ne pas intercepter nobody(UID 65534).


la source
15

Cela fait à peu près ce que fait la réponse acceptée , juste dans une commande au lieu de trois:

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

Et grâce à Karel dans les commentaires, l' nobodyutilisateur est également filtré.

Oli
la source
@karel Ouais, peut-être. Au lieu de filtrer par UID, je filtre explicitement ce nom d'utilisateur. Il peut y avoir une raison pour avoir un utilisateur légitime avec un UID aussi élevé ... Qui sait;)
Oli
9

Personnellement, j'aime utiliser seulement:

ls /home

Certes, ce n'est pas une liste d'utilisateurs mais plutôt une liste de leurs répertoires personnels. Les utilisateurs humains existants sur le système auront des répertoires personnels dans /home, mais vous pouvez également voir les répertoires personnels des anciens utilisateurs qui ont été supprimés.

Cela fonctionne pour mes besoins et peut également fonctionner pour le vôtre. Par exemple, si vous cherchez à supprimer un compte d'utilisateur qui s'avère ne plus exister ( nonexistent-user) et exécutez la commande

sudo deluser nonexistent-user

il vous dira simplement que cet utilisateur n'existe pas.

Sam Hamblin
la source
+1 De cette façon, c'est simple, c'est ce que la plupart des utilisateurs expérimentés feraient réellement, et je pense que ce n'est pas moins robuste que les méthodes qui vérifient une gamme d'UID. Il semble moins probable qu'un utilisateur humain ait un répertoire personnel à l'extérieur /home(qui n'est pas lié à un lien symbolique /home) qu'un utilisateur humain aurait un UID inférieur à 1000 (après tout, c'est la méthode la plus courante pour empêcher un gestionnaire d'affichage de répertorier un utilisateur sur l'écran de connexion, ce qui peut parfois être fait pour un utilisateur humain). Le seul inconvénient relativement mineur ici est celui lost+foundqui sera répertorié sur les systèmes avec des /homepartitions séparées .
Eliah Kagan
Petit problème, cependant: que se passe-t-il si l'utilisateur a été créé avec useradd --no-create-home username?
Sergiy Kolodyazhnyy
@Serg Je pense que cela revient à l'ambiguïté inhérente à la description du problème. Un compte sans répertoire personnel représente-t-il vraiment un utilisateur humain? Dans la pratique, de tels comptes sont généralement - mais certes pas toujours - utilisés pour des tâches hautement spécialisées (généralement par des personnes ayant leurs propres comptes séparés) ou pour des utilisateurs destinés à accéder au système uniquement via des services spécifiques et restreints. Bien sûr, il existe un autre cas d'utilisation pour useradd --no-create-home- le répertoire personnel pourrait déjà exister ou pourrait être créé peu de temps après - mais la ls /homeméthode fonctionne bien pour ces cas.
Eliah Kagan
4

Bien que cela puisse sembler une idée claire, il y a en fait une ambiguïté dans le sens de l'utilisateur humain . Un compte d'utilisateur est-il délibérément caché de l'écran de connexion car il est utilisé uniquement à des fins spécialisées (mais par des humains) par un utilisateur humain? Qu'en est-il de l' ubuntuutilisateur (UID 999) sur le CD live? Et les comptes invités dans Ubuntu sont créés à la volée et détruits après la déconnexion; sont-ils des utilisateurs humains? D'autres exemples pourraient être imaginés.

Par conséquent, il convient que plusieurs réponses non équivalentes aient été données. La solution de Saige Hamblin pour exécuter ls /homeest ce que les gens font réellement , et à moins que vous n'écriviez un script, vous devriez probablement simplement l'utiliser.

Rendre ls /homeplus robuste

Mais vous avez peut-être des utilisateurs qui ont été supprimés, mais dont les répertoires personnels existent toujours /home, et vous devez éviter de les répertorier. Ou peut-être pour une autre raison, vous devez vous assurer que seules les entrées /homequi correspondent à des comptes réels sont répertoriées.

Dans ce cas, je vous suggère de passer les noms de tout /homeà getent(pour récupérer les passwdentrées des utilisateurs avec ces noms), puis isoler et d' afficher tout le champ nom d' utilisateur (avec grep, sedou awk, selon votre préférence). N'importe lequel d'entre eux fera:

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

Cela devrait bien fonctionner, car vous ne devriez pas avoir de comptes utilisateur avec des espaces ou des caractères de contrôle dans leurs noms; ne peut pas, sans reconfigurer Ubuntu pour le permettre ; et si vous le faites, vous avez de plus gros problèmes. Ainsi, les problèmes habituels avec l'analyse lssont inapplicables. Mais même si c'est vraiment bien ici, si vous considérez les substitutions de commandes avec lsun déplaisir esthétique ou simplement une mauvaise habitude, vous pouvez préférer:

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

Ceux-ci ne prennent pas non plus en compte les espaces ou les caractères de contrôle. Je ne les fournis que parce que $(ls /home)ça ne va pas, même quand c'est bien, et frotte ainsi de nombreux utilisateurs dans le mauvais sens. Dans la plupart des situations, il existe de vraies bonnes raisons pour éviter l'analysels , et dans ces situations, l'analyse basename -an'est généralement que très légèrement moins mauvaise. Dans cette situation, cependant, en raison de la limitation du nombre de caractères pouvant apparaître dans les noms d'utilisateur , ils conviennent tous les deux.

Explication, avantages et inconvénients

J'utilise getentprincipalement parce qu'il accepte les noms d'utilisateur comme arguments pour restreindre sa sortie, mais aussi parce qu'il est légèrement plus universel que d'examiner /etc/passwddirectement, dans le cas où les fonctionnalités d'authentification et la base de données de mots de passe sont fournies par les services réseau.

Cette méthode présente l'avantage supplémentaire par rapport à ce ls /homeque, sur les systèmes avec une /homepartition séparée , lost+foundapparaît généralement dans la sortie de ls /home.

  • Avec la méthode plus robuste présentée ci-dessus, lost+foundn'apparaîtra que s'il se trouve qu'un utilisateur (humain ou non) est appelé lost+found, ce qui est peu probable.
  • Mais si vous saisissez des commandes de manière interactive plutôt que d'écrire un script, ls /homec'est bien - vous savez que vous n'avez pas d'utilisateur humain appelé lost+found.

Rarement, cette méthode (dans l'une des variantes ci-dessus) produira une sortie insatisfaisante:

  • Si le répertoire personnel d'un utilisateur existe à l'extérieur /home, ou pas du tout, cela suggère mais n'implique pas que le compte ne doit pas être considéré comme représentant un utilisateur humain. Cette méthode répertorie uniquement les utilisateurs lorsqu'il existe un répertoire du même nom dans /home.
  • Si vous avez créé des répertoires supplémentaires /homequi ne sont en fait le répertoire personnel de personne et qu'ils ont le même nom qu'un utilisateur non humain existant - ou se composent de mots séparés par des espaces, dont un ou plusieurs portent le même nom en tant qu'utilisateur non humain existant - certains utilisateurs non humains peuvent alors être inclus dans la sortie.
    (Cette méthode peut être implémentée avec une boucle et des getentinvocations séparées , donc le fractionnement de mots ne produit pas de sortie parasite. Mais la complexité n'est pas garantie; fondamentalement, si vous utilisez /homeautre chose qu'un endroit pour les répertoires personnels des utilisateurs, cette méthode ne produit pas de sortie fiable.)

Simplification de la vérification UID

Si vous décidez d'utiliser une méthode qui vérifie les ID utilisateur pour vous assurer qu'ils sont dans la plage probable pour les comptes représentant des êtres humains, comme dans la réponse acceptée ou la réponse d'Oli , alors je suggère ceci pour plus de brièveté:

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

Cela utilise une expression régulière Perl ( -P) pour montrer:

  • texte au début d'une ligne ( ^) ne contenant pas de :s ( [^:]+) - c'est le premier champ, tout comme :le séparateur de champ danspasswd
  • qui précède mais n'inclut pas ( (?= )) le champ de mot de passe x- il devrait toujours l'être x, car dans Ubuntu, les hachages de mot de passe sont stockés dans la shadowbase de données, pas dans la base de passwddonnées lisible par le monde
  • et un champ UID composé exactement de 4 chiffres ( :\d{4}:).

Il s'agit donc d'une variante beaucoup plus courte et quelque peu plus simple de la technique dans la réponse acceptée . (La technique décrite ici fonctionne également très bien, et elle a l'avantage d'être portable sur des systèmes non GNU / Linux qui grepne prennent pas en charge -P.)

Reconsidérer la gamme UID «humaine»

Si vous souhaitez accepter des UID très élevés et vérifier nobodyexplicitement, vous pouvez utiliser la méthode dans la réponse d'Oli . Cependant, vous voudrez peut-être déterminer si les utilisateurs avec des UID très élevés doivent vraiment être considérés comme humains, ou s'ils sont plus susceptibles d'être un autre utilisateur non humain à des fins spéciales (comme nobody). Dans la pratique, ces utilisateurs - en plus - ne sont nobodypas courants, il s'agit donc vraiment d'un jugement de votre part.

Un compromis possible consiste à répertorier les utilisateurs dans la plage des UID qui sont réellement attribués aux utilisateurs nouvellement créés, non "système". Vous pouvez vérifier cela dansadduser.conf :

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

Voici deux façons de répertorier les utilisateurs dont les UID vont de 1000 à 29999:

getent passwd | grep -oP '^[^:]+(?=:x:[12]?\d{4}:)'
getent passwd | awk -F: '999<$3 && $3<30000 {print $1}'
Eliah Kagan
la source
Si vous vouliez être stylistique, basenamec'est moche. Ce n'est pas mieux que ls. La principale raison pour laquelle nous n'analysons pas ls est que c'est un travail qui peut être effectué par d'autres outils de manière beaucoup plus sûre et propre, et non par le style. Dans ce cas, la coque: cd /home; getent passwd *.
muru
Je suis d'accord avec vous sur / la maison étant peu fiable (c'est inutile pour moi, voir ma réponse). Je dis juste que si vous voulez prêcher sur le style, attendez-vous à une piqûre.
muru
@muru Je vois comment mon phrasé original pourrait induire les gens en erreur en pensant qu'éviter l'analyse lsest généralement une question de style. Le deuxième point sur les "résultats insatisfaisants" a couvert le problème, mais il apparaît dans une section ultérieure. J'ai reformulé pour clarifier pourquoi l'analyse lsest appropriée dans cette situation . Bien que cd /home; getent passwd *prenant une forme souvent indicative d'une approche plus rationnelle, je l'ai évitée afin de ne pas amener les lecteurs à croire que le contenu des /homerépertoires, avec des entrées ajoutées étranges ne correspondant pas à de vrais utilisateurs, pourrait toujours être invoqué comme un guide les utilisateurs existent.
Eliah Kagan
1

TL; DR : seuls les utilisateurs humains ont SystemAccount = false

Une autre façon consiste à répertorier la sortie de tout en ignorant root ls /var/lib/AccountsService/users/ | grep -v root. Maintenant, il y a une bizarrerie - gdm, un écran d'accueil / de connexion (ou plus officiellement un gestionnaire de bureau) est également répertorié en tant qu'utilisateur. Donc, juste en énumérant, nous ne pouvons pas dire si gdm est humain ou non.

Une approche plus efficace et correcte consiste à parcourir les fichiers de ce dossier et à identifier les utilisateurs répertoriés comme ayant SystemAccount=false. Le soufflet à une doublure atteint ce

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

Sergiy Kolodyazhnyy
la source
1
Bien que parfois pratique, cela échoue dans certains scénarios relativement courants. Par exemple, sur mon système minimal Ubuntu 15.04 (installé à partir de mini.isoet sans gestionnaire d'affichage ou X11 installé), j'ai un compte d'utilisateur humain - mais /var/lib/AccountsService/usersc'est un répertoire vide. Je m'attends à ce que cela ne fonctionne pas non plus sur une installation d'Ubuntu Server prête à l'emploi. De plus, lorsque cela fonctionne, cela se fait sous une notion quelque peu restrictive de ce qui rend un compte utilisateur "humain": rendre un utilisateur avec useradd, même sans --system , ne crée pas de fichier dans AccountsService/users.
Eliah Kagan
1

En rejoignant le parti, je supervise un système de réseau utilisant LDAP, ayant des répertoires personnels à l'extérieur /homeet des UID (en raison d'un problème de script) par millions. Aucune des réponses actuelles ne fonctionne donc. Le test qui fonctionne pour moi consiste à vérifier si l'utilisateur a un shell de connexion valide. Un shell valide est celui qui est répertorié dans /etc/shells. La forme la plus simple:

getent passwd | grep -wFf /etc/shells

Le fichier peut contenir des commentaires (ou des lignes vides), il peut donc être nécessaire de les filtrer:

getent passwd | grep -wFf <(grep '^/' /etc/shells)
muru
la source
+1 Il s'agit peut-être de l'approche la plus robuste suggérée jusqu'à présent. Bien qu'il présente l'inconvénient de montrer root(qui ne devrait probablement pas être considéré comme un utilisateur humain, car les humains deviennent généralement root temporairement et à des fins spécifiques, plutôt que de l'utiliser pour leur travail régulier), il semble que ce soit le moins susceptible d'échouer dans tout moyen majeur. Les méthodes dans d'autres réponses (y compris la mienne) peuvent échouer, selon la méthode, si les répertoires personnels ne sont pas dans /home, d'autres ordures sont dans /home, les UID sont bizarres ou le système n'utilise pas de DM. Cette réponse fonctionne assez bien dans tous ces scénarios.
Eliah Kagan
1

Sur les systèmes buntu, les utilisateurs réguliers (utilisateurs humains, c'est-à-dire) ont des UID commençant par 1000 qui leur sont attribués de manière séquentielle lors de la première création de leurs comptes. Tout cela revient à dire que le premier compte créé sur un système buntu a un UID de 1000. Le suivant créé a un UID de 1001. Et ainsi de suite et ainsi de suite.

Donc, à mon avis, la façon la plus simple de répertorier tous les comptes d'utilisateurs humains présents sur le système est de vérifier si la troisième colonne du /etc/passwdfichier qui contient l'UID de l'utilisateur est supérieure ou égale à 1000 et inférieure à, disons, 2000 (il est très peu probable qu'un PC de bureau typique ait plus d'un millier de comptes d'utilisateurs, ne pensez-vous pas?):

$ awk -F$':' '{ if ($3 >= 1000 && $3 < 2000) print $1; }' /etc/passwd
misha
la source
Merci d'avoir expliqué la réponse d'Oli avec des détails. Vous devez également filtrer nobody. =)
anatoly techtonik
1
Vous n'avez pas à le faire car personne n'a un UID de 65534 et est donc automatiquement filtré comme tous les autres comptes d'utilisateurs non humains.
misha