ฉันมักจะต้องการชื่อเข้าสู่ระบบที่เชื่อมโยงกับ ID ผู้ใช้และเนื่องจากมันพิสูจน์แล้วว่าเป็นกรณีการใช้งานทั่วไปฉันตัดสินใจที่จะเขียนฟังก์ชันเชลล์เพื่อทำสิ่งนี้ ในขณะที่ฉันใช้ดิสทริบิวชัน GNU / Linux เป็นหลักฉันพยายามเขียนสคริปต์ของฉันให้พกพาได้มากที่สุดและเพื่อตรวจสอบว่าสิ่งที่ฉันทำอยู่นั้นใช้กับ POSIX ได้
การแยกวิเคราะห์ /etc/passwd
วิธีแรกที่ฉันพยายามคือการแยกวิเคราะห์/etc/passwd
(โดยใช้awk
)
awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
อย่างไรก็ตามปัญหาด้วยวิธีนี้คือการเข้าสู่ระบบอาจไม่ได้อยู่ในพื้นที่เช่นการตรวจสอบผู้ใช้อาจจะผ่าน NIS หรือ LDAP
ใช้getent
คำสั่ง
การใช้getent passwd
เป็นแบบพกพามากกว่าการแยกวิเคราะห์/etc/passwd
เนื่องจากยังทำการสืบค้นฐานข้อมูล NIS หรือ LDAP ที่ไม่ใช่ท้องถิ่น
getent passwd "$uid" | cut -d: -f1
น่าเสียดายgetent
ที่ POSIX ไม่ได้ระบุยูทิลิตี
ใช้id
คำสั่ง
id
เป็นยูทิลิตี้มาตรฐาน POSIX สำหรับการรับข้อมูลเกี่ยวกับตัวตนของผู้ใช้
การปรับใช้ BSD และ GNU ยอมรับ ID ผู้ใช้ในฐานะตัวถูกดำเนินการ:
หมายความว่าสามารถใช้พิมพ์ชื่อล็อกอินที่เชื่อมโยงกับ ID ผู้ใช้:
id -nu "$uid"
อย่างไรก็ตามการระบุ ID ผู้ใช้เป็นตัวถูกดำเนินการไม่ได้ระบุใน POSIX; มันอธิบายการใช้ชื่อล็อกอินเป็นตัวถูกดำเนินการเท่านั้น
รวมทั้งหมดข้างต้น
ฉันถือว่าการรวมสามวิธีข้างต้นเป็นสิ่งต่อไปนี้:
get_username(){
uid="$1"
# First try using getent
getent passwd "$uid" | cut -d: -f1 ||
# Next try using the UID as an operand to id.
id -nu "$uid" ||
# As a last resort, parse `/etc/passwd`.
awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
}
อย่างไรก็ตามนี่คือ clunky, inelegant และ - ที่สำคัญกว่า - ไม่แข็งแกร่ง; มันออกจากสถานะไม่เป็นศูนย์หาก ID ผู้ใช้ไม่ถูกต้องหรือไม่มีอยู่ ก่อนที่ฉันจะเขียนสคริปต์เชลล์ที่ยาวกว่าและ clunkier ที่วิเคราะห์และเก็บสถานะการออกของการเรียกใช้คำสั่งแต่ละครั้งฉันคิดว่าฉันจะถามที่นี่:
มีวิธีที่สะดวกและพกพามากขึ้น (เข้ากันได้กับ POSIX) ในการรับชื่อล็อกอินที่เชื่อมโยงกับ ID ผู้ใช้หรือไม่?
getent
และid
จะไม่คืนสิ่งใด ๆ ในการแข่งขันครั้งแรก วิธีเดียวที่จะค้นหาพวกเขาทั้งหมดคือการระบุผู้ใช้ทั้งหมดหากฐานข้อมูลผู้ใช้อนุญาต (มองหา/etc/passwd
งานสำหรับผู้ใช้ที่กำหนดไว้อย่างชัดเจน)
/etc/passwd
และ/etc/shadow
เพื่อทดสอบสถานการณ์นี้และตรวจสอบว่าทั้งสองid
และgetent passwd
ทำงานตามที่คุณอธิบาย หากในบางขั้นตอนฉันจบลงด้วยการใช้ระบบที่ผู้ใช้มีชื่อหลายชื่อฉันจะทำเช่นเดียวกันกับระบบสาธารณูปโภคเหล่านี้
setuid(some_id)
ได้และไม่มีข้อกำหนดใด ๆ ที่some_id
อาจเป็นส่วนหนึ่งของฐานข้อมูลผู้ใช้ ด้วยสิ่งต่าง ๆ เช่นเนมสเปซของผู้ใช้บน Linux สิ่งนี้อาจกลายเป็นข้อสันนิษฐานที่ไม่แน่นอนสำหรับสคริปต์ของคุณ
getpwuid()
ฟังก์ชั่นที่มีราคาแพงซึ่งls
ใช้ในการแปล UID ให้เป็นชื่อล็อกอิน คำตอบของ Gillesเป็นวิธีที่ทำให้การทำสิ่งนี้สำเร็จและมีประสิทธิภาพมากขึ้น