Podczas uruchamiania skryptu przez sudo lub su chcę uzyskać oryginalnego użytkownika. Powinno to mieć miejsce niezależnie od wielu sudo
lub su
działa wewnątrz siebie, a konkretnie sudo su -
.
93
Wyniki:
Użyj who am i | awk '{print $1}'
OR, logname
ponieważ ż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 | awk '{print $1}'
who am i
to to samo, cowho smells bad
. Działa również tylko wtedy, gdySTDIN
jest powiązany z urządzeniem TTY. Więc jeśli uruchomiszecho "hello" | who am i
, po prostu nie zadziała.echo "hello" | who am i
normalnie, chyba że twój skrypt działa w środowisku, w którym nie ma terminala. Wtedy możesz zobaczyć błąd, którywho am i
nie działa, ponieważ jest jakiś problem z nieczytelnym stdin, w takim przypadku możesz spróbować przesłać dane dowho am i
z 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.logname
teraz, co jak się okazuje działa, gdziewho am i
nie.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
logname
iwho -m
implementują hack, w którym sprawdzają, do którego terminala jest podłączonystdin
, 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
who
wyświetla następujący wynik:tom
używanysu
do dostać się do korzeni i uruchamia program. JeśliSTDIN
nie jest przekierowywany, potem program jaklogname
pokaże na wyjściutom
. Jeśli JEST przekierowany (np. Z pliku) tak: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ącTeraz 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.źródło
To jest
ksh
funkcja, którą napisałem w HP-UX. Nie wiem, jak to będzie działaćBash
w Linuksie. Chodzi o to, żesudo
proces 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.
źródło
Co powiesz na użycie logname (1), aby uzyskać nazwę logowania użytkownika?
źródło
logname(1)
nie działa, alelogname
działa - dodając wyniki powyżej$LOGNAME
ale to nie zadziałało. Dodano również do powyższych wyników.logname
nadal 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.
źródło
Funkcja findUser () użytkownika1683793 została przeniesiona
bash
i 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"
źródło
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 }
logname
lubwho am i
nie da mi pożądaną odpowiedź, a zwłaszcza nie w dłuższych listachsu 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.
źródło
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 -o
ihead
.ograniczenie: polecenie nie może zawierać nawiasów klamrowych
()
(normalnie nie)źródło
W systemach
systemd-logind
The 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-status
ishow-ssession
systemowe Komendyloginctl
mieć różne zachowanie bez argumentów:session-status
korzysta z bieżącej sesji, aleshow-ssession
używa menedżera. Jednak używanieshow-session
jest preferowane w przypadku używania skryptów ze względu na jego dane wyjściowe do odczytu maszynowego. Dlategologinctl
potrzebne są dwie inwokacje .źródło