如何通过多个sudo和su命令find原始用户?
当通过sudo或su运行脚本时,我想获取原始用户。 这应该发生,无论多个sudo
或su
在彼此内部运行,特别是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$
没有完美的答案。 当您更改用户标识时,通常不会保留原始用户标识,因此信息会丢失。 有些程序,比如logname
和who -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 }
logname
或who am i
没有给我想要的答案,尤其是不是在较长的名单su user1
, su user2
, su user3
, ...
我知道最初的问题是很久以前的,但是人们(比如我)仍然在问,这看起来是一个解决问题的好地方。