sudoまたはsuを介してスクリプトを実行する場合、元のユーザーを取得したいと思います。これは、複数に関係なく発生するsudo
かsu
、相互に実行される必要がありますsudo su -
。
回答:
結果:
他の方法は保証されていないため、who am i | awk '{print $1}'
ORlogname
を使用してください。
自己としてログイン:
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$
who am i
同じwho smells bad
です。また、STDIN
がTTYに関連付けられている場合にのみ機能します。したがって、実行するecho "hello" | who am i
と、単に機能しません。
echo "hello" | who am i
、あなたのスクリプトは搭載していない環境で実行されていない限り、通常は。次にwho am i
、読み取り不可能なstdinに何らかの問題があるために機能していないエラーが表示される場合があります。その場合、who am i
stdin要件を満たすために、必死になってデータをパイプで接続してみてください。tylerlは、彼がすでにその道を進んでいることを指摘しているだけであり、stdinは読み取り可能であり、TTYに関連付けられている必要があるため、パイプは機能しません。
logname
、現在使用who am i
しています。これは、実際には機能しますが、機能しない場合もあります。
完璧な答えはありません。ユーザー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
。それが(例えばファイルから)リダイレクトされた場合:
logname < /some/file
no login name
入力が端末ではないため、結果は「」になります。ただし、さらに興味深いのは、ユーザーが別のログインユーザーを装う可能性があるという事実です。ジョーはpts / 1にログインしているので、トムは走って彼のふりをすることができます
logname < /dev/pts1
さて、joe
トムがコマンドを実行したのに、それは言います。言い換えれば、このメカニズムを何らかのセキュリティの役割で使用すると、頭がおかしくなります。
これはksh
私がHP-UXで書いた関数です。Bash
Linuxでどのように機能するかわかりません。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)を使用してユーザーのログイン名を取得するのはどうですか?
logname(1)
動作しませんが、logname
ない-上記の結果を追加
$LOGNAME
たのですが、うまくいきませんでした。上記の結果にも追加されました。
logname
まだ端末を必要と?私のテストでは、常に合格です。(多分私は何か間違っているかもしれません。)私はcoreutils8.26でLinuxを実行しています。
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以外のプロセスを除外することで、ログインの開始者としてrootをスキップします。場合によってはそれが多すぎるかどうかはわかりません
#!/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
。
制限:コマンドには中括弧を含める()
ことはできません(通常は含まれません)
を実行しているシステムsystemd-logind
では、systemdAPIがこの情報を提供します。シェルスクリプトからこの情報にアクセスする場合は、次のようなものを使用する必要があります。
$ loginctl session-status \
| (read session_id ignored; loginctl show-session -p User $session_id)
User=1000
のsession-status
およびshow-ssession
システムコマンドは、loginctl
引数なしで動作が異なります。session-status
現在のセッションをshow-ssession
使用しますが、マネージャを使用します。ただし、show-session
スクリプトの使用には、機械可読な出力があるため、使用することをお勧めします。これが、の2回の呼び出しloginctl
が必要な理由です。
who | awk '{print $1}'