Sudoまたはsuを介してスクリプトを実行するときに、元のユーザーを取得したい。これは、複数のSudo
またはsu
が相互に実行され、具体的にはSudo su -
。
結果:
つかいます who am i | awk '{print $1}'
OR logname
。他の方法は保証されていません。
自己としてログイン:
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>
通常の須藤:
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>
須藤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 ]#
須藤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$
perfect答えはありません。ユーザーIDを変更すると、通常、元のユーザーIDは保持されないため、情報は失われます。 logname
やwho -m
などの一部のプログラムは、stdin
に接続されている端末を確認し、その端末にログインしているユーザーを確認するためのハックを実装します。 。
このソリューション多くの場合は機能しますが、万全ではなく、確かに安全と見なされるべきではありません。たとえば、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
がリダイレクトされない場合、logname
のようなプログラムはtom
を出力します。 ISリダイレクト(ファイルからなど)の場合:
logname < /some/file
入力は端末ではないため、結果は「no login name
」になります。さらに興味深いのは、ユーザーが別のログインユーザーになりすますということです。 Joeはpts/1にログインしているため、Tomは実行することで彼になりすますことができます。
logname < /dev/pts1
現在、tomがコマンドを実行した人であるにもかかわらず、joe
と表示されます。言い換えると、このメカニズムを何らかのセキュリティロールで使用する場合、あなたは夢中になります。
これは、HP-UXで書いたksh
関数です。 LinuxでBash
でどのように機能するかわかりません。これは、Sudo
プロセスが元のユーザーとして実行され、子プロセスがターゲットユーザーであるという考え方です。親プロセスを循環させることで、元のプロセスのユーザーを見つけることができます。
#
# 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)を使用してユーザーのログイン名を取得するのはどうですか?
THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`
それは私のために働いた唯一のものです。
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の回答に基づく
非TTYプロセスを除外することで、ログインのイニシエーターとしてルートをスキップします。場合によってはそれが過度に排泄されるかどうかはわかりません
#!/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
、...
の長いリストではなく、希望する答えをくれませんでした
元の質問は昔からのものでしたが、(私のような)人々はまだ尋ねているので、これは解決策を置くのに良い場所のように見えました。
Psを複数回呼び出す代わりに、1つのpstree呼び出しを行います
pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1
出力(偶数としてログインした場合):(evan)
pstree引数:
grep -o
およびhead
を使用して、最初のユーザー変更(ログイン)を取得します。
制限:コマンドには中括弧()
を含めることはできません(通常は含まれません)