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 -
.
Odpowiedzi:
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 am i
to to samo, co who smells bad
. Działa również tylko wtedy, gdy STDIN
jest 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 i
normalnie, 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 i
nie działa, ponieważ jest jakiś problem z nieczytelnym stdin, w takim przypadku możesz spróbować przesłać dane do who 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, gdzie who 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
i who -m
implementują 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 who
wyś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)
tom
używany su
do dostać się do korzeni i uruchamia program. Jeśli STDIN
nie jest przekierowywany, potem program jak logname
pokaż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 ksh
funkcja, którą napisałem w HP-UX. Nie wiem, jak to będzie działać Bash
w Linuksie. Chodzi o to, że sudo
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.
Co powiesz na użycie logname (1), aby uzyskać nazwę logowania użytkownika?
logname(1)
nie działa, ale logname
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.
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"
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
lub who am i
nie 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 -o
i head
.
ograniczenie: polecenie nie może zawierać nawiasów klamrowych ()
(normalnie nie)
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
i show-ssession
systemowe Komendy loginctl
mieć różne zachowanie bez argumentów: session-status
korzysta z bieżącej sesji, ale show-ssession
używa menedżera. Jednak używanie show-session
jest preferowane w przypadku używania skryptów ze względu na jego dane wyjściowe do odczytu maszynowego. Dlatego loginctl
potrzebne są dwie inwokacje .
who | awk '{print $1}'