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 getent
commande
L'utilisation getent passwd
est plus portable que l'analyse /etc/passwd
car elle interroge également les bases de données NIS ou LDAP non locales.
getent passwd "$uid" | cut -d: -f1
Malheureusement, l' getent
utilitaire ne semble pas être spécifié par POSIX.
Utilisez la id
commande
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?
getent
ni id
ne 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/passwd
et /etc/shadow
de tester ce scénario et vérifié que les deux id
et getent passwd
se 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_id
peut 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 ls
utilise pour traduire les UID en noms de connexion. La réponse de Gilles est une manière plus directe et efficace d'y parvenir.