Podczas uruchamiania skryptu przez sudo lub su chcę uzyskać oryginalnego użytkownika. Powinno to mieć miejsce niezależnie od wielu sudolub sudziała wewnątrz siebie, a konkretnie sudo su -.
Odpowiedzi:
Wyniki:
Użyj who am i | awk '{print $1}'OR, lognameponieważ żadne inne metody nie są gwarantowane.
Zalogowany jako siebie:
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>
Normalne 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 ito to samo, co who smells bad. Działa również tylko wtedy, gdy STDINjest powiązany z urządzeniem TTY. Więc jeśli uruchomisz echo "hello" | who am i, po prostu nie zadziała.
echo "hello" | who am inormalnie, chyba że twój skrypt działa w środowisku, w którym nie ma terminala. Wtedy możesz zobaczyć błąd, który who am inie działa, ponieważ jest jakiś problem z nieczytelnym stdin, w takim przypadku możesz spróbować przesłać dane do who am iz desperacji, aby spełnić wymagania stdin. tylerl po prostu zauważa, że już podążał tą ścieżką, a potok nie będzie działał, ponieważ stdin musi być zarówno czytelny, jak i powiązany z TTY.
lognameteraz, co jak się okazuje działa, gdzie who am inie.
Nie ma idealnej odpowiedzi. Po zmianie identyfikatorów użytkownika pierwotny identyfikator użytkownika zwykle nie jest zachowywany, więc informacje są tracone. Niektóre programy, takie jak lognamei who -mimplementują hack, w którym sprawdzają, do którego terminala jest podłączony stdin, a następnie sprawdzają, który użytkownik jest zalogowany na tym terminalu.
To rozwiązanie często działa, ale nie jest niezawodne i na pewno nie powinno być uważane za bezpieczne. Na przykład wyobraź sobie, że whowyświetla następujący wynik:
tom pts/0 2011-07-03 19:18 (1.2.3.4)
joe pts/1 2011-07-03 19:10 (5.6.7.8)
tomużywany sudo dostać się do korzeni i uruchamia program. Jeśli STDINnie jest przekierowywany, potem program jak lognamepokaże na wyjściu tom. Jeśli JEST przekierowany (np. Z pliku) tak:
logname < /some/file
Wtedy wynikiem jest „ no login name”, ponieważ wejście nie jest terminalem. Jednak jeszcze ciekawsze jest to, że użytkownik może udawać innego zalogowanego użytkownika. Ponieważ Joe jest zalogowany na pts / 1, Tom mógłby udawać go biegając
logname < /dev/pts1
Teraz jest napisane, joeże to Tom jest tym, który zarządzał. Innymi słowy, jeśli używasz tego mechanizmu w jakiejkolwiek roli bezpieczeństwa, jesteś szalony.
To jest kshfunkcja, którą napisałem w HP-UX. Nie wiem, jak to będzie działać Bashw Linuksie. Chodzi o to, że sudoproces działa jako oryginalny użytkownik, a procesy potomne są użytkownikiem docelowym. Przechodząc wstecz przez procesy nadrzędne, możemy znaleźć użytkownika pierwotnego procesu.
#
# 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
}
Wiem, że pierwotne pytanie było dawno temu, ale ludzie (tacy jak ja) wciąż o nie pytają, a to wyglądało na dobre miejsce na znalezienie rozwiązania.
Co powiesz na użycie logname (1), aby uzyskać nazwę logowania użytkownika?
logname(1)nie działa, ale lognamedziała - dodając wyniki powyżej
$LOGNAMEale to nie zadziałało. Dodano również do powyższych wyników.
lognamenadal wymaga tty? Z moimi testami zawsze mija. (Może coś nie tak.) Używam Linuksa z Coreutils 8.26.
THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`
To jedyna rzecz, która mi pomogła.
Funkcja findUser () użytkownika1683793 została przeniesiona bashi rozszerzona, więc zwraca również nazwy użytkowników przechowywane w bibliotekach NSS.
#!/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"
z powrotem i podając listę użytkowników
na podstawie odpowiedzi użytkownika1683793
Pomijając procesy inne niż TTY, pomijam roota jako inicjatora logowania. Nie jestem pewien, czy w niektórych przypadkach może to zbytnio wydzielać
#!/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
}
lognamelub who am inie da mi pożądaną odpowiedź, a zwłaszcza nie w dłuższych listach su user1, su user2, su user3,...
Wiem, że pierwotne pytanie było dawno temu, ale ludzie (tacy jak ja) wciąż o nie pytają, a to wyglądało na dobre miejsce na znalezienie rozwiązania.
Alternatywa dla wielokrotnego wywoływania ps: wykonaj jedno wywołanie pstree
pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1
wyjście (po zalogowaniu jako parzyste): (evan)
argumenty pstree:
Uzyskaj pierwszą zmianę użytkownika (czyli logowanie) za pomocą grep -oi head.
ograniczenie: polecenie nie może zawierać nawiasów klamrowych ()(normalnie nie)
W systemach systemd-logindThe Systemd API udostępnia tę informację . Jeśli chcesz uzyskać dostęp do tych informacji ze skryptu powłoki, użyj czegoś takiego:
$ loginctl session-status \
| (read session_id ignored; loginctl show-session -p User $session_id)
User=1000
Te session-statusi show-ssessionsystemowe Komendy loginctlmieć różne zachowanie bez argumentów: session-statuskorzysta z bieżącej sesji, ale show-ssessionużywa menedżera. Jednak używanie show-sessionjest preferowane w przypadku używania skryptów ze względu na jego dane wyjściowe do odczytu maszynowego. Dlatego loginctlpotrzebne są dwie inwokacje .
who | awk '{print $1}'