web-dev-qa-db-ja.com

複数のSudoおよびsuコマンドを使用して元のユーザーを見つけるにはどうすればよいですか?

Sudoまたはsuを介してスクリプトを実行するときに、元のユーザーを取得したい。これは、複数のSudoまたはsuが相互に実行され、具体的にはSudo su -

78
evan

結果:

つかいます 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$
125
evan

perfect答えはありません。ユーザーIDを変更すると、通常、元のユーザーIDは保持されないため、情報は失われます。 lognamewho -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)

tomsuを使用してルートにアクセスし、プログラムを実行します。 STDINがリダイレクトされない場合、lognameのようなプログラムはtomを出力します。 ISリダイレクト(ファイルからなど)の場合:

logname < /some/file

入力は端末ではないため、結果は「no login name」になります。さらに興味深いのは、ユーザーが別のログインユーザーになりすますということです。 Joeはpts/1にログインしているため、Tomは実行することで彼になりすますことができます。

logname < /dev/pts1

現在、tomがコマンドを実行した人であるにもかかわらず、joeと表示されます。言い換えると、このメカニズムを何らかのセキュリティロールで使用する場合、あなたは夢中になります。

13
tylerl

これは、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
}

元の質問は昔からのものでしたが、(私のような)人々はまだ尋ねているので、これは解決策を置くのに良い場所のように見えました。

8
user1683793

Logname(1)を使用してユーザーのログイン名を取得するのはどうですか?

5
sam
THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`

それは私のために働いた唯一のものです。

3

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"
2
asdfghjkl

サイクルバックしてユーザーのリストを提供する

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 user1su user2su user3...の長いリストではなく、希望する答えをくれませんでした

元の質問は昔からのものでしたが、(私のような)人々はまだ尋ねているので、これは解決策を置くのに良い場所のように見えました。

2
ULick

Psを複数回呼び出す代わりに、1つのpstree呼び出しを行います

pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1

出力(偶数としてログインした場合):(evan)

pstree引数:

  • -l:長い行(短縮しない)
  • -u:ユーザーが(userName)に変更されたときに表示します
  • -s $$:このプロセスの親を表示します

grep -oおよびheadを使用して、最初のユーザー変更(ログイン)を取得します。

制限:コマンドには中括弧()を含めることはできません(通常は含まれません)

1
simohe