Wer setzt die Umgebungsvariablen $ USER und $ USERNAME?

34

Stimmen diese Variablen auch immer mit dem aktuell angemeldeten Benutzernamen überein (auf meinem Debian-System)? Kann ich ihre Verfügbarkeit in anderen Unix-ähnlichen Systemen annehmen?

Ich bin auch neugierig, warum man whoamidiese Variablen verwenden sollte, anstatt sie nur zu lesen.

Tshepang
quelle
2
Wenn Sie sich die manSeite ansehen, whoamiwird der Name angezeigt, der Ihrer effektiven Benutzer-ID zugeordnet ist. Dies bedeutet, dass etwas anderes zurückgegeben wird, wenn Sie sudoeine Setuid-Programmdatei verwenden oder ausführen. Wenn Sie sudoeingerichtet haben, versuchen Sie es sudo whoamizum Beispiel.
Joseph R.
4
USERund USERNAMEsind gewöhnliche Umgebungsvariablen, was bedeutet, dass Sie sie, wenn Sie möchten, auf beliebige Werte setzen können. Einfach tippen USER=xyz. Mit anderen Worten, auch wenn diese Variablen existieren, gibt es keine Garantie dafür, dass ihre Werte mit dem aktuell angemeldeten Benutzernamen übereinstimmen.
Uwe
@Uwe By guarantee, meinte ich standardmäßig (dh vorausgesetzt Benutzer hat sie nicht geändert).
Tshepang
2
@ Tshepang Als Follow-up zu meinem ersten Kommentar: Vergleichen Sie die Ergebnisse von sudo whoamiundsudo echo $USER
Joseph R.
2
@ JosephR. Denn sudo echo $USERdie Shell expandiert $USERund ruft dann aufsudo . Natürlich wird nicht die gleiche Ausgabe wie erzeugt whoami. Wie sudo whoami, sudo sh -c 'echo $USER'gibt (normalerweise) aus root. In Bezug auf Ihre Kommentare über whoamidie EUID mit , Notiz , die sudo whoamiAusgabe würde , rootwenn auch whoamidie UID verwendet. sudoSätze sowohl EUID und UID für den Befehl es (außer in der sehr ungewöhnlichen Situation , dass Sie konfigurieren es ausdrücklich anders verhalten) läuft. Vergleichen Sie sudo id -umit sudo id -ru.
Eliah Kagan

Antworten:

29

Es ist ein Login .

Die Linux Login (1) Manpage sagt:

Der Wert für $ HOME , $ USER , $ SHELL , $ PATH , $ LOGNAME und $ MAIL wird gemäß den entsprechenden Feldern in der Kennworteingabe festgelegt.

Die FreeBSD Login (1) Manpage sagt:

Das Anmeldedienstprogramm gibt Informationen in die Umgebung ein (siehe environ (7) ) und gibt das Ausgangsverzeichnis (HOME) des Benutzers, den Befehlsinterpreter (SHELL), den Suchpfad (PATH), den Terminaltyp (TERM) und den Benutzernamen (LOGNAME und USER) an. .

Die NetBSD- , OpenBSD- und OS X- Manpages sagen dasselbe.

Hier ist der Quellcode aus dem Util-Linux-Login:

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);

Hier ist der Quellcode aus dem FreeBSD-Login:

(void)setenv("LOGNAME", username, 1);
(void)setenv("USER", username, 1);
(void)setenv("PATH", rootlogin ? _PATH_STDPATH : _PATH_DEFPATH, 0);
Poige
quelle
2
Auf meiner Fedora 16-Box habe ich beides USERund USERNAMEsetze und dein Befehl kehrt nur zurück LOGNAME.
Joseph R.
1
@JosephR., Leider habe ich Fedora nicht in der Hand, aber ich habe mir auch die Quellen von FreeBSD angesehen, siehe UPD ..
poige
Dies ist jedoch bei Fedora offensichtlich nicht der Fall. Ich sage nur, logines scheint nicht das Einzige zu sein, was diese Variablen einstellt.
Joseph R.
1
Beachten Sie, dass Linux nur ein Kernel ist und keinen loginBefehl hat. Betriebssysteme, die Linux als Kernel verwenden, können jede beliebige Implementierung verwenden. Zum Beispiel neigen Debian-basierte Systeme dazu, das von shadow-utils zu verwenden, nicht util-linux.
Stéphane Chazelas
1
Beachten Sie, dass dies loginhäufig nicht aufgerufen wird, wenn Sie sich über sshoder von den meisten grafischen Anmeldemanagern anmelden.
Stéphane Chazelas
11

Es gibt keine Regel. Einige Muscheln mögen tcshoder zshsetzen $LOGNAME. zshsetzt $USER.

Es kann durch einige Dinge eingestellt werden , dass Sie in wie log login(wie durch aufgerufen , gettywenn Anmeldung an einem Terminal und manchmal durch andere Dinge wie in.rlogind) cron, su, sudo, sshd, rshd, grafische Login - Manager oder auch nicht.

Wenn es jedoch eine Anmeldung gibt, wird diese nach meiner Erfahrung $USERim Allgemeinen festgelegt (möglicherweise wird sie jedoch nach einer Änderung der Benutzer-ID (über setuid-Befehle) in dieser Anmeldesitzung nicht aktualisiert. POSIX erfordert, dass $LOGNAMEdiese bei der Anmeldung festgelegt wird (und cron).

Um den Anmeldenamen portabel zu erhalten, verwenden Sie am besten den lognameBefehl (wenn keine Anmeldung erfolgt ist, wird möglicherweise nichts zurückgegeben). Verwenden Sie, um die Benutzer-ID abzurufen id -u. Um einen Benutzernamen der aktuellen effektiven Benutzer - ID entspricht: id -un. Um alle zu erhalten (meistens gibt es nur einen Benutzernamen pro Benutzer-ID, aber das ist nicht garantiert):

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

Dies funktioniert jedoch möglicherweise nicht auf Systemen, auf denen die Benutzerdatenbank nicht aufgelistet werden kann (wie dies manchmal bei vernetzten Benutzerdatenbanken der Fall ist).

Stéphane Chazelas
quelle
3

Sie möchten sich hier wahrscheinlich auf den POSIX- Standard verlassen, da Sie sich zu einem bestimmten Zeitpunkt wahrscheinlich nicht nur um die Benutzeranmeldung (die vom loginProgramm verwaltet wird ), sondern auch um cronAufträge und dergleichen kümmern werden .

Daher sollten Sie wissen, dass POSIX dies erfordert, $LOGNAMEjedoch nicht $USER. ZB $USERdarf nicht von cron gesetzt werden, wie in einer Antwort von Keith Thompson ausgeführt , die auch einen Hinweis auf die Beziehung zwischen System-V und BSD enthält:

... zumindest auf meinem System (Ubuntu 14.04) ist die Umgebungsvariable $ USER nicht für Cronjobs gesetzt. Stattdessen können Sie $ LOGNAME verwenden, das Teil der Umgebung für Cron-Jobs ist.

Gemäß der Manpage environ (7) (zum Lesen geben Sie man environ ein) wird $ USER von BSD-abgeleiteten Programmen und $ LOGNAME von System-V-abgeleiteten Programmen verwendet.

Nealmcb
quelle
1

Wenn Sie die Umgebungsvariablen (anstelle von whoamioder getpwentund getpwnam) verwenden möchten und nicht sicher sind, ob sie auf allen * NIX-Systemen immer auf die gleiche Weise festgelegt sind, versuchen Sie dies in bash:

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

Wenn es danach immer noch leer ist, befinden Sie sich auf einem eher esoterischen System. ;)

Jesse Chisholm
quelle