Làm thế nào để bạn tìm thấy người dùng ban đầu thông qua nhiều lệnh sudo và su?


93

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 sudohoặc suchạy bên trong nhau và cụ thể sudo su -.

Câu trả lời:


136

Các kết quả:

Sử dụng who am i | awk '{print $1}'HOẶC lognamevì 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$

1
Trong trường hợp đó bạn chỉ có thể sử dụngwho | awk '{print $1}'
SiegeX

2
... nếu bạn là người duy nhất đăng nhập (và chỉ một lần).
Tạm dừng cho đến khi có thông báo mới.

9
tất cả những gì bạn cần là 2 đối số: who am igiố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 inó đơn giản sẽ không hoạt động.
tylerl

1
Bạn sẽ không chạy echo "hello" | who am ibì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 ikhô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 itrong 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.
Edwin Buck

4
@even True, mặc dù tôi muốn nó yêu cầu cấu hình càng ít càng tốt, vì vậy tôi đang sử dụng lognamengay bây giờ, nó thực sự hoạt động, nơi who am ithì không.
Bart van Heukelom

18

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ư lognamewho -mthự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 whokế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 STDINkhông được chuyển hướng, thì một chương trình như thế lognamesẽ 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 joemặ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ồ.


2
Nếu bạn đang tự chạy tập lệnh (bằng chứng là các lệnh được sử dụng), bảo mật không phải là vấn đề. Nếu đúng như vậy, bạn có nhiều vấn đề hơn vì họ cũng có quyền truy cập sudo. Người đó có thể sao chép kịch bản và sửa đổi nó theo bất kỳ cách nào họ muốn. Đây chỉ đơn giản là một cách để lấy tên đã đăng nhập để sử dụng trong tập lệnh. Hay tôi thiếu điều gì đó về những gì bạn đang nói?
evan

1
@evan: Có quyền truy cập sudo không ngụ ý khả năng ghi đè tệp.
Flimzy

@Flimzy Trong trường hợp nào thì root không có khả năng ghi đè tệp?
evan

1
@evan: Bất cứ lúc nào quyền truy cập sudo của bạn không cung cấp cho bạn quyền truy cập vào trình bao hoặc bất kỳ lệnh nào khác có thể ghi đè tệp, hiển nhiên.
Flimzy

Không phải lúc nào cũng có quyền truy cập @evan sudo (không nên có trong hầu hết các trường hợp quản trị) toàn bộ quyền truy cập root. Đó là một tập hợp các ngữ cảnh thực thi hạn chế có thể định cấu hình.
DylanYoung

8

Đây là một kshchứ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 Bashtrong Linux. Ý tưởng là sudoquy 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.


5

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 lognamecó - thêm các kết quả ở trên
evan

ban đầu tôi đã thử $LOGNAMEnhưng điều đó không hoạt động. Cũng được thêm vào các kết quả ở trên.
evan

Liệu lognamevẫ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.
simohe

Tên đăng nhập của tôi (GNU coreutils) 8.28 trên luôn trả về "tên đăng nhập: không có tên đăng nhập" (Ubuntu 18.04.2)
sondra.kinsey


2

Hàm findUser () của user1683793 được chuyển đến bashvà 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"

FYI: chức năng này (và chức năng dựa trên nó) sẽ không quay trở lại qua nhiều shell được tạo ra bởi sudo lồng vào nhau.
asdfghjkl

2

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
}

lognamehoặ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.


2

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:

  • -l: dòng dài (không rút ngắn)
  • -u: hiển thị khi người dùng thay đổi thành (userName)
  • -s $$: hiển thị cho phụ huynh của quá trình này

Nhận thay đổi người dùng đầu tiên (là đăng nhập) với grep -ohead .

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)


pstree -lu -s $$ | head -n1 | sed -e 's / [^ (] * (([^)] *)). * / \ 1 /'
Alexx Roche

0

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-statusshow-ssessionhệ thống của loginctlcó hành vi khác nhau mà không có đối số: session-statussử dụng phiên hiện tại, nhưng show-ssessionsử 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 loginctllà cần thiết.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.