คุณจะค้นหาผู้ใช้ดั้งเดิมผ่านคำสั่ง sudo และ su หลายคำสั่งได้อย่างไร


93

เมื่อเรียกใช้สคริปต์ผ่าน sudo หรือ su ฉันต้องการรับผู้ใช้ดั้งเดิม นี้ควรจะเกิดขึ้นโดยไม่คำนึงถึงหลาย ๆsudoหรือsuทำงานภายในของแต่ละอื่น ๆ sudo su -และโดยเฉพาะ

คำตอบ:


136

ผล:

ใช้who am i | awk '{print $1}'หรือ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 ]#

ซูโดซู -; สุทอม:

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
ในกรณีนี้คุณสามารถใช้who | awk '{print $1}'
SiegeX

2
... หากคุณเป็นเพียงคนเดียวที่เข้าสู่ระบบ (และเป็นเพียงครั้งเดียว)
หยุดชั่วคราวจนกว่าจะมีประกาศอีกครั้ง

9
สิ่งที่คุณต้องการคือ 2 อาร์กิวเมนต์: who am iเหมือนกับwho smells bad. นอกจากนี้ยังใช้งานได้เฉพาะเมื่อSTDINเชื่อมโยงกับ TTY ดังนั้นหากคุณเรียกใช้echo "hello" | who am iมันจะไม่ทำงาน
tylerl

1
คุณจะไม่ทำงานecho "hello" | who am iตามปกติเว้นแต่สคริปต์ของคุณจะทำงานในสภาพแวดล้อมที่ไม่มีเทอร์มินัล จากนั้นคุณอาจเห็นข้อผิดพลาดที่who am iใช้งานไม่ได้เนื่องจากมีปัญหาบางอย่างเกี่ยวกับ stdin ที่ไม่สามารถอ่านได้ซึ่งในกรณีนี้คุณอาจลองวางข้อมูลให้who am iหมดสิ้นเพื่อให้เป็นไปตามข้อกำหนด stdin tylerl เพียงแค่สังเกตว่าเขาอยู่ในเส้นทางนั้นแล้วและไปป์จะไม่ทำงานเพราะ stdin ต้องอ่านได้และเชื่อมโยงกับ TTY
Edwin Buck

4
@even ทรู แต่ฉันต้องการที่จะต้องกำหนดค่าน้อยที่สุดเท่าที่เป็นไปได้เพื่อให้ฉันใช้lognameในขณะนี้ซึ่งมันจะเปิดออกไม่ทำงานที่who am iไม่ได้
Bart van Heukelom

18

ไม่มีคำตอบที่สมบูรณ์แบบ เมื่อคุณเปลี่ยน 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 ทอมสามารถแกล้งทำเป็นเขาได้โดยการวิ่ง

logname < /dev/pts1

ตอนนี้มันบอกว่าjoeถึงแม้ทอมจะเป็นคนสั่งการ กล่าวอีกนัยหนึ่งถ้าคุณใช้กลไกนี้ใน Security role ใด ๆ คุณก็บ้า


2
หากคุณกำลังเรียกใช้สคริปต์ด้วยตัวเอง (ตามหลักฐานจากคำสั่งที่ใช้) ความปลอดภัยไม่ใช่ปัญหา หากเป็นเช่นนั้นคุณจะมีปัญหามากกว่านี้เนื่องจากมีการเข้าถึง sudo ด้วย บุคคลนั้นสามารถคัดลอกสคริปต์และแก้ไขได้ตามที่ต้องการ นี่เป็นเพียงวิธีรับชื่อล็อกอินเพื่อใช้ในสคริปต์ หรือฉันพลาดอะไรบางอย่างเกี่ยวกับสิ่งที่คุณกำลังพูด?
evan

1
@evan: การเข้าถึง sudo ไม่ได้หมายความถึงความสามารถในการเขียนทับไฟล์
Flimzy

@Flimzy ในกรณีใดที่รูทไม่มีความสามารถในการเขียนทับไฟล์?
evan

1
@evan: ทุกครั้งที่การเข้าถึง sudo ของคุณไม่ให้คุณเข้าถึงเชลล์หรือคำสั่งอื่น ๆ ที่สามารถเขียนทับไฟล์ได้
Flimzy

การเข้าถึง @evan sudo ไม่เสมอไป (ไม่ควรเป็นในกรณีผู้ดูแลระบบส่วนใหญ่) การเข้าถึงรูททั้งหมด เป็นชุดของบริบทการดำเนินการที่ จำกัด ที่กำหนดค่าได้
DylanYoung

8

นี่คือkshฟังก์ชันที่ฉันเขียนบน HP-UX ฉันไม่รู้ว่ามันจะทำงานกับBashLinux ได้อย่างไร แนวคิดคือ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
}

ฉันรู้ว่าคำถามเดิมมาจากเมื่อนานมาแล้ว แต่ผู้คน (เช่นฉัน) ยังคงถามอยู่และดูเหมือนว่านี่จะเป็นจุดที่ดีในการแก้ปัญหา


5

วิธีการใช้ logname (1) เพื่อรับชื่อล็อกอินของผู้ใช้?


logname(1)ใช้งานไม่ได้ แต่lognameเพิ่มผลลัพธ์ด้านบน
evan

เดิมทีฉันพยายาม$LOGNAMEแล้วแต่ไม่ได้ผล นอกจากนี้ยังเพิ่มในผลลัพธ์ด้านบน
evan

ไม่lognameยังคงต้อง TTY หรือไม่? ด้วยการทดสอบของฉันมันมักจะผ่านไป (บางทีฉันอาจจะทำอะไรผิดพลาด) ฉันใช้งาน linux กับ coreutils 8.26
simohe

ชื่อบันทึกของฉัน (GNU coreutils) 8.28 เมื่อคืนค่า "logname: no login name" เสมอ (Ubuntu 18.04.2)
sondra.kinsey


2

ฟังก์ชัน findUser () ของ user1683793 พอร์ต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"

FYI: ฟังก์ชั่นนี้ (และฟังก์ชั่นที่ใช้) จะไม่วนกลับผ่านหลาย ๆ เชลล์ที่เกิดโดย sudo ที่ซ้อนกัน
asdfghjkl

2

ขี่จักรยานกลับและให้รายชื่อผู้ใช้

ตามคำตอบของ user1683793

โดย exlcuding กระบวนการที่ไม่ใช่ 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,...

ฉันรู้ว่าคำถามเดิมมาจากเมื่อนานมาแล้ว แต่ผู้คน (เช่นฉัน) ยังคงถามอยู่และดูเหมือนว่านี่จะเป็นจุดที่ดีในการแก้ปัญหา


2

ทางเลือกในการโทร ps หลายครั้ง: ทำการโทร pstree หนึ่งครั้ง

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

เอาต์พุต (เมื่อล็อกอินเป็นคู่): (evan)

ข้อโต้แย้ง pstree:

  • -l: เส้นยาว (ไม่ทำให้สั้นลง)
  • -u: แสดงเมื่อผู้ใช้เปลี่ยนเป็น (userName)
  • -s $$: แสดงผู้ปกครองของกระบวนการนี้

ได้รับการเปลี่ยนแปลงที่ผู้ใช้รายแรก (ซึ่งก็คือการเข้าสู่ระบบ) ด้วยและgrep -ohead

ข้อ จำกัด : คำสั่งต้องไม่มีวงเล็บปีกกา()(ปกติไม่ได้)


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

0

บนระบบที่ใช้systemd-logindในAPI systemd ให้ข้อมูลนี้ หากคุณต้องการเข้าถึงข้อมูลนี้จากเชลล์สคริปต์จำเป็นต้องใช้สิ่งนี้:

$ 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เป็นที่นิยมสำหรับการใช้สคริปต์เนื่องจากเอาต์พุตที่เครื่องอ่านได้ นี่คือเหตุผลว่าทำไมจึงloginctlต้องมีการร้องขอสองครั้ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.