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>
일반 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-; 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$
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
입력이 터미널이 아니기 때문에 결과는 " "입니다. 하지만 더 흥미로운 것은 사용자가 다른 로그인 사용자로 위장 할 수 있다는 사실입니다. Joe가 pts / 1에 로그인했기 때문에 Tom은 다음을 실행하여 자신을 가장 할 수 있습니다.
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
여전히 tty가 필요 합니까 ? 내 테스트에서는 항상 통과합니다. (아마 내가 뭔가 잘못했을 수도 있습니다.) coreutils 8.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 프로세스를 제외하여 로그인 시작 자로서 루트를 건너 뜁니다. 어떤 경우에는 너무 많이 빠져 나갈 수 있는지 잘 모르겠습니다
#!/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를 여러 번 호출하는 대안 : pstree 호출 한 번 수행
pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1
출력 (짝수로 로그인했을 때) : (evan)
pstree 인수 :
와 (로그인입니다) 첫 번째 사용자의 변화를 가져 grep -o
와 head
.
제한 : 명령에 중괄호가 포함될 수 없습니다 ()
(일반적으로는 아님).
실행중인 시스템 systemd-logind
에서 systemd API는이 정보를 제공합니다 . 쉘 스크립트에서이 정보에 액세스하려면 다음과 같이 사용해야합니다.
$ 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
컴퓨터에서 읽을 수있는 출력으로 인해 스크립트 사용 에는 using을 사용하는 것이 좋습니다. 이것이 두 번의 호출 loginctl
이 필요한 이유 입니다.
who | awk '{print $1}'