Qui définit les variables d'environnement $ USER et $ USERNAME?

34

De plus, ces variables correspondront-elles toujours au nom d'utilisateur actuellement connecté (elles le sont sur mon système Debian)? Puis-je supposer leur disponibilité dans d'autres systèmes Unix?

Je suis également curieux de savoir pourquoi on utiliserait whoamiplutôt que de simplement lire l'une de ces variables.

Tshepang
la source
2
En regardant la manpage, vous whoamiindiquez le nom associé à votre ID utilisateur effectif. Ce qui signifie qu'il retournera quelque chose de différent si vous utilisez sudoou exécutez un exécutable setuid. Si vous avez sudoconfiguré, essayez sudo whoamipar exemple.
Joseph R.
4
USERet USERNAMEsont des variables d’environnement ordinaires, ce qui signifie que, si vous le souhaitez, vous pouvez les attribuer à des valeurs arbitraires. Il suffit de taper USER=xyz. En d'autres termes, même si ces variables existent, rien ne garantit que leurs valeurs correspondent au nom d'utilisateur actuellement connecté.
Uwe
@Uwe By guarantee, je voulais dire par défaut (c'est-à-dire en supposant que l'utilisateur ne les a pas changés).
Tshepang
2
@Tshepang Pour faire suite à mon premier commentaire: comparez les résultats de sudo whoamietsudo echo $USER
Joseph R.
2
@JosephR. Car sudo echo $USER, le shell se développe $USER, puis appelle sudo. Alors bien sûr, cela ne produit pas le même résultat que whoami. Comme sudo whoami, sudo sh -c 'echo $USER'fait (généralement) la sortie root. En ce qui concerne votre commentaire sur l’ whoamiutilisation de l’EUID , notez que cela sudo whoamiproduirait rootmême si whoamil’UID était utilisé. sudoensembles à la fois EUID et UID pour la commande il fonctionne (sauf dans le cas très rare que vous configurez explicitement à se comporter autrement). Comparez sudo id -uà sudo id -ru.
Eliah Kagan

Réponses:

29

C'est login .

La page de manuel de connexion Linux (1) indique:

Les valeurs pour $ HOME , $ USER , $ SHELL , $ PATH , $ LOGNAME et $ MAIL sont définies en fonction des champs appropriés dans l'entrée du mot de passe.

La page de manuel de connexion FreeBSD (1) indique:

L' utilitaire de connexion entre des informations dans l'environnement (voir environ (7) ) en spécifiant le répertoire de base de l'utilisateur (HOME), l'interpréteur de commandes (SHELL), le chemin de recherche (PATH), le type de terminal (TERM) et le nom d'utilisateur (LOGNAME et USER). .

Les pages de manuel NetBSD , OpenBSD et OS X disent la même chose.

Voici le code source de la connexion util-linux:

setenv("HOME", pwd->pw_dir, 0); /* legal to override */
setenv("USER", pwd->pw_name, 1);
setenv("SHELL", pwd->pw_shell, 1);
/* ... */
setenv("LOGNAME", pwd->pw_name, 1);

Voici le code source de la connexion FreeBSD:

(void)setenv("LOGNAME", username, 1);
(void)setenv("USER", username, 1);
(void)setenv("PATH", rootlogin ? _PATH_STDPATH : _PATH_DEFPATH, 0);
poige
la source
2
Sur ma boîte Fedora 16, j'ai les deux USERet USERNAMEmis et votre commande ne retourne que LOGNAME.
Joseph R.
1
@JosephR., Malheureusement, je n'ai pas Fedora à la main, mais j'ai aussi consulté les sources de FreeBSD, voir UPD ..
poige,
Mais ce n'est évidemment pas le cas sur Fedora. Tout ce que je dis, c'est loginque ne semble pas être la seule chose qui détermine ces variables.
Joseph R.
1
Notez que Linux n’est qu’un noyau, il n’a pas de logincommande. Les systèmes d'exploitation utilisant Linux comme noyau sont libres d'utiliser n'importe quelle implémentation qu'ils souhaitent. Par exemple, les systèmes basés sur Debian ont tendance à utiliser celui de shadow-utils, pas util-linux.
Stéphane Chazelas
1
Notez que, logindans la sshplupart des cas, la plupart des gestionnaires de connexion graphiques n'appellent pas cette option lors de la connexion.
Stéphane Chazelas
11

Il n'y a pas de règle. Quelques coquilles aiment tcshou zshensemble $LOGNAME. zshensembles $USER.

Il peut être fixé par certaines choses que vous vous connectez comme login(comme invoqué par gettylorsque la connexion sur un terminal et parfois par d' autres choses comme in.rlogind), cron, su, sudo, sshd, rshd, les gestionnaires de connexion graphique ou non.

D'après mon expérience, s'il y a déjà eu un login, il $USERest généralement défini (mais il se peut qu'il ne soit pas mis à jour après un changement d'identifiant d'utilisateur (via les commandes setuid) au sein de cette session. POSIX exige qu'il $LOGNAMEsoit défini lors de la connexion (et cron).

Pour obtenir le nom de connexion de manière portable, le mieux consiste à utiliser la lognamecommande (s'il n'y a pas eu de connexion, elle peut ne rien renvoyer). Pour obtenir l'identifiant de l'utilisateur, utilisez id -u. Pour obtenir un nom d' utilisateur correspondant à l'ID utilisateur effectif: id -un. Pour les obtenir tous (la plupart du temps, il n'y a qu'un seul nom d'utilisateur par identifiant, mais ce n'est pas garanti):

perl -le 'while ($n = getpwent()) {print $n if getpwnam($n) == $>}'

Bien que cela puisse ne pas fonctionner sur des systèmes où la base de données d'utilisateurs ne peut pas être énumérée (comme cela arrive parfois avec des bases de données d'utilisateurs en réseau, par exemple).

Stéphane Chazelas
la source
3

Vous voulez probablement vous appuyer sur le standard POSIX , car à un moment donné, vous vous soucierez probablement non seulement de la connexion utilisateur (gérée par le loginprogramme), mais également des cronemplois, etc.

Par conséquent, vous devez savoir que POSIX requiert, $LOGNAMEmais pas $USER. Par exemple, $USERne peut pas être défini par cron, comme indiqué dans une réponse de Keith Thompson , qui fait également référence à une partie de l’histoire sur la relation entre cela et l’histoire de System-V par rapport à BSD:

... du moins sur mon système (Ubuntu 14.04), la variable d’environnement $ USER n’est pas définie pour les travaux cron. Au lieu de cela, vous pouvez utiliser $ LOGNAME, qui fait partie de l'environnement pour les tâches cron.

Selon la page de manuel environ (7) (tapez man env pour le lire), $ USER est utilisé par les programmes dérivés de BSD et $ LOGNAME est utilisé par les programmes dérivés de System-V.

nealmcb
la source
1

Si vous souhaitez utiliser les variables d'environnement (au lieu de whoamiou getpwentet getpwnam) et que vous ne savez pas si elles sont toujours définies de la même manière sur tous les systèmes * NIX, essayez ceci sous bash:

THIS_USER=${USER:-${USERNAME:-${LOGNAME}}}
echo ${THIS_USER}

S'il est toujours vide après tout cela, alors vous êtes sur un système plutôt ésotérique. ;)

Jesse Chisholm
la source