Wenn ich ein Skript über sudo oder su ausführe, möchte ich den ursprünglichen Benutzer erhalten. Dies sollte unabhängig von mehreren sudo
oder su
ineinander und spezifisch geschehen sudo su -
.
Antworten:
Ergebnisse:
Verwenden Sie who am i | awk '{print $1}'
OR, logname
da keine anderen Methoden garantiert sind.
Als Selbst angemeldet:
evan> echo $USER
evan
evan> echo $SUDO_USER
evan> echo $LOGNAME
evan
evan> whoami
evan
evan> who am i | awk '{print $1}'
evan
evan> logname
evan
evan>
Normaler Sudo:
evan> sudo -s
root> echo $USER
root
root> echo $SUDO_USER
evan
root> echo $LOGNAME
root
root> whoami
root
root> who am i | awk '{print $1}'
evan
root> logname
evan
root>
sudo su -:
evan> sudo su -
[root ]# echo $USER
root
[root ]# echo $SUDO_USER
[root ]# echo $LOGNAME
root
[root ]# whoami
root
[root ]# who am i | awk '{print $1}'
evan
[root ]# logname
evan
[root ]#
sudo su -; su tom:
evan> sudo su -
[root ]# su tom
tom$ echo $USER
tom
tom$ echo $SUDO_USER
tom$ echo $LOGNAME
tom
tom$ whoami
tom
tom$ who am i | awk '{print $1}'
evan
tom$ logname
evan
tom$
who am i
ist das gleiche wie who smells bad
. Außerdem funktioniert es nur, wenn STDIN
es einem TTY zugeordnet ist. Wenn Sie es ausführen echo "hello" | who am i
, funktioniert es einfach nicht.
echo "hello" | who am i
normal ausgeführt, es sei denn, Ihr Skript wird in einer Umgebung ausgeführt, in der kein Terminal vorhanden ist. Dann sehen Sie möglicherweise den Fehler, der who am i
nicht funktioniert, weil es ein Problem mit dem nicht lesbaren Standard gibt. In diesem Fall können Sie versuchen, Daten who am i
aus Verzweiflung weiterzuleiten, um die Standardanforderungen zu erfüllen. tylerl bemerkt nur, dass er diesen weg bereits eingeschlagen hat und die Pipe nicht funktioniert, da stdin sowohl lesbar als auch mit einem TTY verknüpft sein muss.
logname
jetzt, was, wie sich herausstellt, funktioniert, wo who am i
nicht.
Es gibt keine perfekte Antwort. Wenn Sie Benutzer-IDs ändern, wird die ursprüngliche Benutzer-ID normalerweise nicht beibehalten, sodass die Informationen verloren gehen. Einige Programme, wie z. B. logname
und who -m
implementieren einen Hack, bei dem überprüft wird, mit welchem Terminal verbunden ist stdin
, und anschließend überprüft wird, welcher Benutzer an diesem Terminal angemeldet ist.
Diese Lösung funktioniert oft , ist aber nicht kinderleicht und sollte auf keinen Fall als sicher angesehen werden. Stellen Sie sich zum Beispiel vor, Sie geben who
Folgendes aus:
tom pts/0 2011-07-03 19:18 (1.2.3.4)
joe pts/1 2011-07-03 19:10 (5.6.7.8)
tom
wird verwendet su
, um zu root zu gelangen, und führt Ihr Programm aus. Wenn STDIN
nicht umgeleitet wird, wird ein Programm wie logname
ausgegeben tom
. Wenn es wie folgt umgeleitet wird (z. B. aus einer Datei):
logname < /some/file
Dann ist das Ergebnis " no login name
", da der Eingang nicht das Terminal ist. Interessanter ist jedoch die Tatsache, dass sich der Benutzer als ein anderer angemeldeter Benutzer ausgeben könnte. Da Joe bei pts / 1 angemeldet ist, könnte Tom vorgeben, er zu sein, indem er rennt
logname < /dev/pts1
Jetzt heißt es, joe
obwohl Tom derjenige ist, der den Befehl ausgeführt hat. Mit anderen Worten, wenn Sie diesen Mechanismus in irgendeiner Sicherheitsrolle verwenden, sind Sie verrückt.
Dies ist eine ksh
Funktion, die ich unter HP-UX geschrieben habe. Ich weiß nicht, wie es unter Bash
Linux funktionieren wird . Die Idee ist, dass der sudo
Prozess als der ursprüngliche Benutzer ausgeführt wird und die untergeordneten Prozesse der Zielbenutzer sind. Durch Zurücklaufen durch übergeordnete Prozesse können wir den Benutzer des ursprünglichen Prozesses finden.
#
# The options of ps require UNIX_STD=2003. I am setting it
# in a subshell to avoid having it pollute the parent's namespace.
#
function findUser
{
thisPID=$$
origUser=$(whoami)
thisUser=$origUser
while [ "$thisUser" = "$origUser" ]
do
( export UNIX_STD=2003; ps -p$thisPID -ouser,ppid,pid,comm ) | grep $thisPID | read thisUser myPPid myPid myComm
thisPID=$myPPid
done
if [ "$thisUser" = "root" ]
then
thisUser=$origUser
fi
if [ "$#" -gt "0" ]
then
echo $origUser--$thisUser--$myComm
else
echo $thisUser
fi
return 0
}
Ich weiß, dass die ursprüngliche Frage von vor langer Zeit stammt, aber Leute (wie ich) fragen immer noch und dies schien ein guter Ort zu sein, um die Lösung zu finden.
Wie wäre es mit logname (1), um den Anmeldenamen des Benutzers zu erhalten?
logname(1)
funktioniert nicht, funktioniert aber logname
- die obigen Ergebnisse hinzufügen
$LOGNAME
aber das hat nicht funktioniert. Auch zu den obigen Ergebnissen hinzugefügt.
logname
noch ein tty? Bei meinen Tests besteht es immer. (Vielleicht habe ich etwas falsch gemacht.) Ich verwende Linux mit Coreutils 8.26.
THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`
Das ist das einzige, was für mich funktioniert hat.
Die findUser () -Funktion von user1683793 wurde portiert bash
und erweitert, sodass auch in NSS-Bibliotheken gespeicherte Benutzernamen zurückgegeben werden.
#!/bin/bash
function findUser() {
thisPID=$$
origUser=$(whoami)
thisUser=$origUser
while [ "$thisUser" = "$origUser" ]
do
ARR=($(ps h -p$thisPID -ouser,ppid;))
thisUser="${ARR[0]}"
myPPid="${ARR[1]}"
thisPID=$myPPid
done
getent passwd "$thisUser" | cut -d: -f1
}
user=$(findUser)
echo "logged in: $user"
zurückfahren und eine Liste der Benutzer geben
basierend auf der Antwort von user1683793
Durch das Ausschließen von Nicht-TTY-Prozessen überspringe ich root als Initiator der Anmeldung. Ich bin mir nicht sicher, ob dies in einigen Fällen zu viel ausschließen kann
#!/bin/ksh
function findUserList
{
typeset userList prevUser thisPID thisUser myPPid myPid myTTY myComm
thisPID=$$ # starting with this process-ID
while [ "$thisPID" != 1 ] # and cycling back to the origin
do
( ps -p$thisPID -ouser,ppid,pid,tty,comm ) | grep $thisPID | read thisUser myPPid myPid myTTY myComm
thisPID=$myPPid
[[ $myComm =~ ^su ]] && continue # su is always run by root -> skip it
[[ $myTTY == '?' ]] && continue # skip what is running somewhere in the background (without a terminal)
if [[ $prevUser != $thisUser ]]; then # we only want the change of user
prevUser="$thisUser" # keep the user for comparing
userList="${userList:+$userList }$thisUser" # and add the new user to the list
fi
#print "$thisPID=$thisUser: $userList -> $thisUser -> $myComm " >&2
done
print "$userList"
return 0
}
logname
oder who am i
habe ich nicht die gewünschte Antwort, vor allem nicht in längeren Listen su user1
, su user2
, su user3
,...
Ich weiß, dass die ursprüngliche Frage von vor langer Zeit stammt, aber Leute (wie ich) fragen immer noch und dies schien ein guter Ort zu sein, um die Lösung zu finden.
Alternative zum mehrmaligen Aufruf von ps: Führen Sie einen pstree-Aufruf durch
pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1
Ausgabe (wenn als gerade angemeldet): (evan)
pstree Argumente:
Holen Sie sich die erste Benutzeränderung (die Anmeldung ist) mit grep -o
und head
.
Einschränkung: Der Befehl darf keine geschweiften Klammern enthalten ()
(normalerweise nicht).
who | awk '{print $1}'