Khi chạy script qua sudo hoặc su, tôi muốn lấy người dùng ban đầu. Điều này sẽ xảy ra bất kể nhiều sudo
hoặc su
chạy bên trong nhau và cụ thể sudo su -
.
Câu trả lời:
Các kết quả:
Sử dụng who am i | awk '{print $1}'
HOẶC logname
vì không có phương pháp nào khác được đảm bảo.
Đăng nhập với tư cách là chính mình:
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 bình thường:
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
giống như who smells bad
. Ngoài ra, nó chỉ hoạt động nếu STDIN
được liên kết với TTY. Vì vậy, nếu bạn chạy echo "hello" | who am i
nó đơn giản sẽ không hoạt động.
echo "hello" | who am i
bình thường, trừ khi tập lệnh của bạn đang chạy trong môi trường không có thiết bị đầu cuối. Sau đó, bạn có thể thấy lỗi who am i
không hoạt động bởi vì có một số loại vấn đề với stdin không thể đọc được, trong trường hợp đó, bạn có thể thử nhập dữ liệu who am i
trong tình trạng tuyệt vọng để đáp ứng yêu cầu stdin của nó. tylerl chỉ lưu ý rằng anh ấy đã đi xuống con đường đó và đường ống sẽ không hoạt động vì stdin phải vừa có thể đọc được vừa được liên kết với TTY.
logname
ngay bây giờ, nó thực sự hoạt động, nơi who am i
thì không.
Không có câu trả lời hoàn hảo . Khi bạn thay đổi ID người dùng, ID người dùng ban đầu thường không được giữ nguyên, vì vậy thông tin sẽ bị mất. Một số chương trình, chẳng hạn như logname
và who -m
thực hiện một cuộc tấn công trong đó chúng kiểm tra xem thiết bị đầu cuối nào được kết nối với stdin
, sau đó kiểm tra xem người dùng nào đã đăng nhập trên thiết bị đầu cuối đó.
Giải pháp này thường hoạt động, nhưng không an toàn và chắc chắn không nên được coi là an toàn. Ví dụ, hãy tưởng tượng nếu who
kết quả đầu ra như sau:
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
được sử dụng su
để root và chạy chương trình của bạn. Nếu STDIN
không được chuyển hướng, thì một chương trình như thế logname
sẽ xuất ra tom
. Nếu nó được chuyển hướng (ví dụ từ một tệp) như vậy:
logname < /some/file
Sau đó, kết quả là " no login name
", vì đầu vào không phải là thiết bị đầu cuối. Tuy nhiên, điều thú vị hơn vẫn là thực tế là người dùng có thể đóng vai một người dùng đã đăng nhập khác. Vì Joe đã đăng nhập trên pts / 1, Tom có thể giả làm anh ấy bằng cách chạy
logname < /dev/pts1
Bây giờ, nó nói joe
mặc dù tom là người điều hành lệnh. Nói cách khác, nếu bạn sử dụng cơ chế này trong bất kỳ loại vai trò bảo mật nào, bạn thật điên rồ.
Đây là một ksh
chức năng tôi đã viết trên HP-UX. Tôi không biết nó sẽ hoạt động như thế nào Bash
trong Linux. Ý tưởng là sudo
quy trình đang chạy với tư cách là người dùng ban đầu và các quy trình con là người dùng mục tiêu. Bằng cách quay lại các quy trình mẹ, chúng tôi có thể tìm thấy người dùng của quy trình ban đầu.
#
# 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
}
Tôi biết câu hỏi ban đầu đã có từ rất lâu rồi nhưng mọi người (chẳng hạn như tôi) vẫn đang hỏi và đây có vẻ là một nơi tốt để đưa ra giải pháp.
Còn việc sử dụng logname (1) để lấy tên đăng nhập của người dùng thì sao?
logname(1)
không hoạt động nhưng logname
có - thêm các kết quả ở trên
$LOGNAME
nhưng điều đó không hoạt động. Cũng được thêm vào các kết quả ở trên.
logname
vẫn đòi hỏi một tty? Với các bài kiểm tra của tôi, nó luôn luôn vượt qua. (Có thể tôi đã làm sai điều gì đó.) Tôi đang chạy linux với coreutils 8.26.
THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`
Đó là điều duy nhất làm việc cho tôi.
Hàm findUser () của user1683793 được chuyển đến bash
và mở rộng để nó cũng trả về tên người dùng được lưu trữ trong các thư viện 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"
quay trở lại và đưa ra danh sách người dùng
dựa trên câu trả lời của user1683793
Bằng cách loại bỏ các quy trình không phải TTY, tôi bỏ qua root với tư cách là người khởi tạo đăng nhập. Tôi không chắc liệu điều đó có thể quá nhiều trong một số trường hợp
#!/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
hoặc who am i
đã không cho tôi câu trả lời mong muốn, đặc biệt là không trong danh sách dài su user1
, su user2
, su user3
,...
Tôi biết câu hỏi ban đầu đã có từ rất lâu rồi nhưng mọi người (chẳng hạn như tôi) vẫn đang hỏi và đây có vẻ là một nơi tốt để đưa ra giải pháp.
Thay thế để gọi ps nhiều lần: thực hiện một cuộc gọi pstree
pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1
đầu ra (khi đăng nhập với tư cách chẵn): (evan)
đối số pstree:
Nhận thay đổi người dùng đầu tiên (là đăng nhập) với grep -o
vàhead
.
giới hạn: lệnh có thể không chứa bất kỳ dấu ngoặc nhọn nào ()
(nó không bình thường)
Trên các hệ thống đang chạy systemd-logind
, API systemd cung cấp thông tin này . Nếu bạn muốn truy cập thông tin này từ tập lệnh shell, cần sử dụng một cái gì đó như sau:
$ loginctl session-status \
| (read session_id ignored; loginctl show-session -p User $session_id)
User=1000
Các lệnh session-status
và show-ssession
hệ thống của loginctl
có hành vi khác nhau mà không có đối số: session-status
sử dụng phiên hiện tại, nhưng show-ssession
sử dụng trình quản lý. Tuy nhiên, việc sử dụng show-session
được ưu tiên hơn cho việc sử dụng tập lệnh do đầu ra có thể đọc được bằng máy. Đây là lý do tại sao hai lệnh gọi loginctl
là cần thiết.
who | awk '{print $1}'