Saat menjalankan skrip melalui sudo atau su saya ingin mendapatkan pengguna asli. Ini harus terjadi terlepas dari beberapa sudo
atau su
berjalan di dalam satu sama lain dan secara khusus sudo su -
.
Jawaban:
Hasil:
Gunakan who am i | awk '{print $1}'
ATAU logname
karena tidak ada metode lain yang dijamin.
Masuk sebagai diri:
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>
Sudo normal:
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
sama dengan who smells bad
. Selain itu, ini hanya berfungsi jika STDIN
dikaitkan dengan TTY. Jadi jika Anda menjalankannya echo "hello" | who am i
tidak akan berhasil.
echo "hello" | who am i
normal, kecuali skrip Anda berjalan di lingkungan di mana tidak ada terminal. Kemudian Anda mungkin melihat kesalahan yang who am i
tidak berfungsi karena ada semacam masalah dengan stdin yang tidak dapat dibaca, dalam hal ini Anda dapat mencoba memasukkan data ke who am i
dalam keadaan putus asa untuk memenuhi persyaratan stdin itu. tylerl hanya mencatat bahwa dia sudah melalui jalur itu, dan pipa tidak berfungsi karena stdin harus dapat dibaca dan dikaitkan dengan TTY.
logname
sekarang, yang ternyata berhasil, di mana who am i
tidak.
Tidak ada jawaban yang sempurna . Saat Anda mengubah ID pengguna, ID pengguna asli biasanya tidak disimpan, sehingga informasinya hilang. Beberapa program, seperti logname
dan who -m
menerapkan peretasan di mana mereka memeriksa untuk melihat terminal mana yang terhubung stdin
, dan kemudian memeriksa untuk melihat pengguna mana yang masuk di terminal itu.
Solusi ini sering kali berhasil, tetapi tidak selalu berhasil, dan tentunya tidak boleh dianggap aman. Misalnya, bayangkan jika who
menghasilkan yang berikut:
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
digunakan su
untuk mendapatkan root, dan menjalankan program Anda. Jika STDIN
tidak diarahkan, maka program seperti logname
akan keluar tom
. Jika IS diarahkan ulang (misalnya dari file) sebagai berikut:
logname < /some/file
Maka hasilnya adalah " no login name
", karena inputnya bukan terminal. Lebih menarik lagi, bagaimanapun, adalah fakta bahwa pengguna dapat menyamar sebagai pengguna login yang berbeda. Karena Joe login pada poin / 1, Tom bisa berpura-pura menjadi dia dengan berlari
logname < /dev/pts1
Sekarang, dikatakan joe
meskipun tom adalah orang yang menjalankan perintah. Dengan kata lain, jika Anda menggunakan mekanisme ini dalam peran keamanan apa pun, Anda gila.
Ini adalah ksh
fungsi yang saya tulis di HP-UX. Saya tidak tahu bagaimana ini akan bekerja Bash
di Linux. Idenya adalah bahwa sudo
proses tersebut berjalan sebagai pengguna asli dan proses anak adalah pengguna target. Dengan bersepeda kembali melalui proses induk, kita dapat menemukan pengguna dari proses aslinya.
#
# 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
}
Saya tahu pertanyaan aslinya sudah lama sekali tetapi orang-orang (seperti saya) masih bertanya dan sepertinya ini adalah tempat yang bagus untuk memberikan solusi.
Bagaimana jika menggunakan logname (1) untuk mendapatkan nama login pengguna?
logname(1)
tidak berfungsi tetapi berfungsi logname
- menambahkan hasil di atas
$LOGNAME
tetapi tidak berhasil. Juga ditambahkan ke hasil di atas.
logname
masih membutuhkan tty? Dengan tes saya, itu selalu berlalu. (Mungkin saya melakukan sesuatu yang salah.) Saya menjalankan linux dengan coreutils 8.26.
THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`
Itulah satu-satunya hal yang berhasil bagi saya.
Fungsi findUser () user1683793 diporting ke bash
dan diperpanjang sehingga mengembalikan nama pengguna yang disimpan di pustaka NSS juga.
#!/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"
bersepeda kembali dan memberikan daftar pengguna
berdasarkan jawaban pengguna1683793
Dengan mengecualikan proses non-TTY, saya melewati root sebagai inisiator login. Saya tidak yakin apakah itu mungkin terlalu berlebihan dalam beberapa kasus
#!/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
atau who am i
tidak memberi saya jawaban yang diinginkan, terutama di daftar panjang su user1
, su user2
, su user3
,...
Saya tahu pertanyaan aslinya sudah lama sekali tetapi orang-orang (seperti saya) masih bertanya dan sepertinya ini adalah tempat yang bagus untuk memberikan solusi.
Alternatif untuk memanggil ps beberapa kali: lakukan satu panggilan pstree
pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1
keluaran (saat masuk sebagai genap): (evan)
argumen pstree:
Dapatkan perubahan pengguna pertama (yaitu login) dengan grep -o
danhead
.
batasan: perintah tidak boleh mengandung kurung kurawal ()
(biasanya tidak)
Pada sistem yang berjalan systemd-logind
, API systemd menyediakan informasi ini . Jika Anda ingin mengakses informasi ini dari skrip shell, perlu menggunakan sesuatu seperti ini:
$ loginctl session-status \
| (read session_id ignored; loginctl show-session -p User $session_id)
User=1000
The session-status
dan show-ssession
sistem perintah dari loginctl
memiliki perilaku yang berbeda tanpa argumen: session-status
menggunakan sesi saat ini, tetapi show-ssession
menggunakan manajer. Namun, penggunaan show-session
lebih disukai untuk penggunaan skrip karena keluarannya yang dapat dibaca mesin. Inilah sebabnya mengapa loginctl
dibutuhkan dua pemanggilan .
who | awk '{print $1}'