如何通过多个sudo和su命令find原始用户?

当通过sudo或su运行脚本时,我想获取原始用户。 这应该发生,无论多个sudosu在彼此内部运行,特别是sudo su -

结果:

使用who am i | awk '{print $1}' who am i | awk '{print $1}'或者没有其他方法保证。

以自己身份login:

 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:

 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 – ; 苏姆:

 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$ 

没有完美的答案。 当您更改用户标识时,通常不会保留原始用户标识,因此信息会丢失。 有些程序,比如lognamewho -m执行一个黑客程序,检查哪个terminal连接到stdin ,然后检查该terminal上login的用户。

这个解决scheme通常是可行的,但并不是万无一失的,当然不应该被认为是安全的。 例如,想象who输出以下内容:

 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使用su来到根,并运行您的程序。 如果STDIN没有被redirect,那么像logname这样的程序将会输出tom 。 如果它被redirect(例如从一个文件),如下所示:

 logname < /some/file 

那么结果是“ no login name ”,因为input不是terminal。 然而更有趣的是,用户可以构成不同的login用户。 由于Joe以pts / 1login,Tom可以通过跑步假装他

 logname < /dev/pts1 

现在,即使汤姆是掌pipe命令的人,也会说joe 。 换句话说,如果你在任何安全angular色中使用这个机制,你就疯了。

这是我在HP-UX上编写的ksh函数。 我不知道它将如何在Linux中与Bash一起工作。 这个想法是, sudo进程以原始用户身份运行,subprocess是目标用户。 通过循环父进程,我们可以find原始进程的用户。

 # # 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 } 

我知道最初的问题是很久以前的,但是人们(比如我)仍然在问,这看起来是一个解决问题的好地方。

如何使用logname(1)获取用户的login名?

user1683793的findUser()函数移植到bash和扩展,所以它也返回存储在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" 

骑自行车回来,给出用户名单

根据user1683793的回答

通过parsing非TTY进程,我跳过root作为login的发起者。 我不确定在某些情况下,这可能会过多

 #!/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 } 

lognamewho am i没有给我想要的答案,尤其是不是在较长的名单su user1su user2su user3...

我知道最初的问题是很久以前的,但是人们(比如我)仍然在问,这看起来是一个解决问题的好地方。