Je souhaite souvent obtenir le nom de connexion associé à un ID utilisateur et comme il s'est avéré qu'il s'agit d'un cas d'utilisation courant, j'ai décidé d'écrire une fonction shell pour ce faire. Bien que j'utilise principalement des distributions GNU / Linux, j'essaie d'écrire mes scripts pour être aussi portables que possible et de vérifier que ce que je fais est compatible POSIX.
Analyser /etc/passwd
La première approche que j'ai essayée a été d'analyser /etc/passwd(en utilisant awk).
awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
Cependant, le problème avec cette approche est que les connexions peuvent ne pas être locales, par exemple, l'authentification des utilisateurs pourrait être via NIS ou LDAP.
Utilisez la getentcommande
L'utilisation getent passwdest plus portable que l'analyse /etc/passwdcar elle interroge également les bases de données NIS ou LDAP non locales.
getent passwd "$uid" | cut -d: -f1
Malheureusement, l' getentutilitaire ne semble pas être spécifié par POSIX.
Utilisez la idcommande
id est l'utilitaire normalisé POSIX pour obtenir des données sur l'identité d'un utilisateur.
Les implémentations BSD et GNU acceptent un ID utilisateur comme opérande:
- id (1) - Pages de manuel OpenBSD
- id (1) - Page de manuel de FreeBSD
- GNU Coreutils: invocation d'un identifiant
Cela signifie qu'il peut être utilisé pour imprimer le nom de connexion associé à un ID utilisateur:
id -nu "$uid"
Cependant, fournir des ID utilisateur en tant qu'opérande n'est pas spécifié dans POSIX; il décrit uniquement l'utilisation d'un nom de connexion comme opérande.
Combiner tout ce qui précède
J'ai envisagé de combiner les trois approches ci-dessus en quelque chose comme ce qui suit:
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
}
Cependant, c'est maladroit, inélégant et - plus important encore - pas robuste; il se termine avec un état différent de zéro si l'ID utilisateur n'est pas valide ou n'existe pas. Avant d'écrire un script shell plus long et plus maladroit qui analyse et stocke l'état de sortie de chaque appel de commande, j'ai pensé demander ici:
Existe-t-il un moyen plus élégant et portable (compatible POSIX) d'obtenir le nom de connexion associé à un ID utilisateur?
getentni idne retournera quoi que ce soit après la première correspondance; la seule façon de les trouver tous est d'énumérer tous les utilisateurs, si la base de données des utilisateurs le permet. (Recherche dans les /etc/passwdœuvres pour les utilisateurs définis là, évidemment.)
/etc/passwdet /etc/shadowde tester ce scénario et vérifié que les deux idet getent passwdse comportent comme vous le décrivez. Si, à un moment donné, je finis par utiliser un système où un utilisateur a plusieurs noms, je ferai la même chose que ces utilitaires système et traiterai simplement la première occurrence comme le nom canonique de cet utilisateur.
setuid(some_id), et aucune exigence ne some_idpeut faire partie d'une base de données utilisateur. Avec des choses comme les espaces de noms d'utilisateurs sous Linux, cela peut devenir une hypothèse paralysante pour vos scripts.
getpwuid()fonction qui lsutilise pour traduire les UID en noms de connexion. La réponse de Gilles est une manière plus directe et efficace d'y parvenir.