รายชื่อผู้ใช้ที่เป็นมนุษย์ทั้งหมด


19

ฉันจะแสดงรายการผู้ใช้ที่เป็นมนุษย์ทั้งหมดที่ฉันสร้างได้อย่างไร ฉันลองcat /etc/passwdแล้วและมันก็มีรายการมากมาย

คำตอบ:


18

ผู้ใช้ที่เป็นมนุษย์มี UID เริ่มต้นที่ 1,000 ดังนั้นคุณสามารถใช้ข้อเท็จจริงนั้นเพื่อกรองผู้ที่ไม่ใช่มนุษย์:

cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1

วิธีนี้จะตัดฟิลด์ (ชื่อผู้ใช้) แรกและฟิลด์ที่คั่นด้วยโคลอน (UID) ที่สามจาก/etc/passwdนั้นกรองสำหรับบรรทัดผลลัพธ์ที่ลงท้ายด้วยเครื่องหมายโคลอนและตัวเลขสี่หลักจากนั้นตัดฟิลด์ (ชื่อผู้ใช้) แรกจากนั้นทำให้คุณมีรายการ ผู้ใช้ที่มี UID ระหว่าง 1,000 ถึง 9999

หากคุณมีผู้ใช้มากกว่าเก้าพันคนในระบบของคุณสิ่งนี้จะล้มเหลว - แต่จำเป็นต้อง จำกัด ผลลัพธ์เป็นnobodyUID 4 หลักเพื่อไม่ให้จับ(UID 65534)


15

นี่เป็นคำตอบที่ยอมรับได้ในคำสั่งเดียวแทนที่จะเป็นสามคำตอบ :

awk -F: '$3 >= 1000 && $1 != "nobody" {print $1}' /etc/passwd

และต้องขอบคุณ Karel ในความคิดเห็นnobodyผู้ใช้จะถูกกรองออกด้วย


@karel ใช่บางที แทนที่จะกรองโดย UID ฉันจะกรองชื่อผู้ใช้นั้นออกอย่างชัดเจน อาจมีเหตุผลในการมีผู้ใช้ที่ถูกกฎหมายด้วย UID ที่สูง ... ใครจะรู้;)
Oli

9

โดยส่วนตัวแล้วฉันชอบใช้แค่:

ls /home

เป็นที่ยอมรับว่านี่ไม่ใช่รายชื่อผู้ใช้ แต่เป็นรายการของโฮมไดเร็กตอรี่แทน ปัจจุบันผู้ใช้งานมนุษย์ที่มีอยู่ในระบบจะมีโฮมไดเร็กตอรี่/home , แต่คุณอาจเห็นโฮมไดเร็กตอรี่ของผู้ใช้ในอดีตที่ถูกลบ, เช่นกัน

สิ่งนี้ใช้ได้กับวัตถุประสงค์ของฉันและอาจใช้ได้กับคุณเช่นกัน ตัวอย่างเช่นหากคุณต้องการลบบัญชีผู้ใช้ที่ปรากฎว่าไม่มีอยู่อีกต่อไป ( nonexistent-user) และเรียกใช้คำสั่ง

sudo deluser nonexistent-user

มันจะบอกคุณว่าผู้ใช้รายนี้ไม่มีอยู่จริง


+1 ด้วยวิธีนี้ง่ายมันเป็นสิ่งที่ผู้ใช้ที่มีประสบการณ์มากที่สุดจะทำจริงและฉันคิดว่ามันมีความแข็งแกร่งไม่น้อยไปกว่าวิธีที่ตรวจสอบ UID ที่หลากหลาย ดูเหมือนว่าผู้ใช้ที่เป็นมนุษย์จะมีโฮมได/homeเร็กตอรี่นอก(ที่ไม่ได้เชื่อมโยงกับ/home) กว่าผู้ใช้ที่เป็นมนุษย์จะมี UID ต่ำกว่า 1,000 (หลังจากทั้งหมด) นี่เป็นวิธีที่ใช้กันโดยทั่วไปในการจัดการผู้จัดการหน้าจอ ผู้ใช้บนหน้าจอเข้าสู่ระบบซึ่งบางครั้งอาจทำเพื่อผู้ใช้ที่เป็นมนุษย์) ข้อเสียอย่างหนึ่งที่ค่อนข้างน้อยที่นี่คือที่lost+foundจะแสดงรายการในระบบที่มี/homeพาร์ทิชันแยกต่างหาก
Eliah Kagan

ปัญหาเล็ก ๆ แต่จะเกิดอะไรขึ้นหากผู้ใช้ถูกสร้างขึ้นด้วยuseradd --no-create-home username?
Sergiy Kolodyazhnyy

@ เซอร์ฉันคิดว่ามันเกิดขึ้นกับความกำกวมโดยธรรมชาติในคำอธิบายปัญหา บัญชีที่ไม่มีโฮมไดเร็กตอรี่เป็นตัวแทนของผู้ใช้มนุษย์จริง ๆ หรือไม่? ในทางปฏิบัติบัญชีดังกล่าวมักจะ - แม้ว่าจะไม่ได้รับการยอมรับเสมอ - ใช้สำหรับงานที่มีความเชี่ยวชาญสูง (โดยทั่วไปคือคนที่มีบัญชีแยกต่างหาก) หรือสำหรับผู้ใช้ที่ต้องการเข้าถึงระบบผ่านบริการที่ จำกัด และเฉพาะ แน่นอนว่ามีกรณีการใช้งานอื่นสำหรับuseradd --no-create-home- โฮมไดเรกทอรีอาจมีอยู่แล้วหรืออาจถูกสร้างขึ้นหลังจากนั้นไม่นาน - แต่ls /homeวิธีการนี้ใช้ได้ผลดีสำหรับกรณีเหล่านั้น
Eliah Kagan

4

ในขณะที่มันอาจจะดูเหมือนเป็นความคิดที่ชัดเจนจริงมีความคลุมเครือในความหมายของผู้ใช้ของมนุษย์ บัญชีผู้ใช้ถูกซ่อนอย่างจงใจจากหน้าจอเข้าสู่ระบบเพราะมันใช้เพื่อวัตถุประสงค์เฉพาะ (แต่โดยมนุษย์) เป็นผู้ใช้ที่เป็นมนุษย์หรือไม่? วิธีการเกี่ยวกับubuntuผู้ใช้ (UID 999) ในไลฟ์ซีดี? และบัญชีผู้เยี่ยมชมในอูบุนตูก็ถูกสร้างขึ้นทันทีและถูกทำลายหลังจากออกจากระบบ พวกเขาเป็นมนุษย์หรือไม่ สามารถสร้างตัวอย่างเพิ่มเติมได้

ดังนั้นจึงเหมาะสมที่มีคำตอบที่ไม่เทียบเท่าหลายคำตอบ วิธีแก้ปัญหาการทำงานของSaige Hamblinls /homeคือสิ่งที่ผู้คนจริงทำและถ้าคุณกำลังเขียนสคริปต์คุณอาจจะใช้เพียงว่า

การทำ ls /homeแข็งแกร่งมากขึ้น

แต่บางทีคุณอาจมีผู้ใช้ที่ถูกลบออกไป แต่ยังมีโฮมไดเรกทอรีอยู่/homeและคุณต้องหลีกเลี่ยงการแสดงรายการ หรืออาจเป็นเพราะเหตุผลอื่นคุณต้องแน่ใจว่ามีเพียงรายการเท่านั้น/homeที่สอดคล้องกับบัญชีจริงเท่านั้น

ในกรณีที่ผมขอแนะนำให้ผ่านชื่อของทุกอย่างใน/homeการgetent(เพื่อดึงpasswdรายการของผู้ใช้ที่มีชื่อเหล่านั้น) แล้วแยกและการแสดงผลเพียงฟิลด์ชื่อผู้ใช้ (มีgrep, sedหรือawkตามความต้องการของคุณ) หนึ่งในสิ่งเหล่านี้จะทำ:

getent passwd $(ls /home) | grep -o '^[^:]*'
getent passwd $(ls /home) | sed 's/:.*//'
getent passwd $(ls /home) | awk -F: '{print $1}'

สิ่งนี้ควรใช้งานได้ดีเนื่องจากคุณไม่ควรมีบัญชีผู้ใช้ที่มีช่องว่างหรืออักขระควบคุมในชื่อ ไม่สามารถโดยไม่ต้องกำหนดค่าอูบุนตูจะให้มัน ; และถ้าคุณทำคุณมีปัญหามากขึ้น ดังนั้นปัญหาปกติของการแยกวิเคราะห์lsจึงไม่เหมาะสม แต่ถึงแม้ว่ามันจะไม่เป็นไรจริงๆถ้าคุณพิจารณาการแทนที่คำสั่งด้วยlsความไม่พอใจอย่างสุนทรีย์หรือเป็นนิสัยที่ไม่ดีคุณอาจต้องการ:

getent passwd $(basename -a /home/*) | grep -o '^[^:]*'
getent passwd $(basename -a /home/*) | sed 's/:.*//'
getent passwd $(basename -a /home/*) | awk -F: '{print $1}'

สิ่งเหล่านี้ไม่รองรับช่องว่างหรืออักขระควบคุม ฉันให้พวกเขาเพียงเพราะ$(ls /home)ดูผิดแม้ในขณะที่ถูกต้องและทำให้ผู้ใช้หลายคนถูวิธีที่ผิด ในสถานการณ์ส่วนใหญ่มีเหตุผลจริงที่ดีเพื่อหลีกเลี่ยงการแยกวิเคราะห์lsและในสถานการณ์เหล่านั้นการแยกวิเคราะห์basename -aมักจะไม่ดีเพียงเล็กน้อยเท่านั้น ในสถานการณ์นี้อย่างไรก็ตามเนื่องจากข้อ จำกัด เกี่ยวกับตัวละครที่อาจเกิดขึ้นจริงในชื่อผู้ใช้พวกเขาทั้งคู่ก็ดี

คำอธิบายประโยชน์และข้อเสีย

ฉันใช้getentเป็นหลักเพราะยอมรับชื่อผู้ใช้เป็นอาร์กิวเมนต์เพื่อ จำกัด การส่งออก แต่ยังเพราะมันเป็นสากลมากกว่าการตรวจสอบ/etc/passwdโดยตรงเล็กน้อยในกรณีที่สิ่งอำนวยความสะดวกการตรวจสอบและฐานข้อมูลรหัสผ่านให้บริการเครือข่าย

วิธีการนี้มีประโยชน์เพิ่มเติมกว่าls /homeว่าในระบบที่มีการแยก/homeพาร์ทิชันมักจะปรากฏในการส่งออกของlost+foundls /home

  • ด้วยวิธีการที่มีประสิทธิภาพมากขึ้นที่นำเสนอข้างต้นlost+foundจะปรากฏเฉพาะในกรณีที่มีผู้ใช้ (เรียกว่าlost+foundเป็นมนุษย์หรือไม่) ซึ่งไม่น่าจะเกิดขึ้น
  • แต่ถ้าคุณกำลังป้อนคำสั่งโต้ตอบมากกว่าการเขียนสคริปต์ls /homeเป็น fine-- คุณlost+foundรู้ว่าคุณไม่ได้มีผู้ใช้ที่เรียกว่ามนุษย์

ไม่บ่อยนักวิธีนี้ (ในรูปแบบใด ๆ ข้างต้น) จะสร้างผลลัพธ์ที่ไม่น่าพอใจ:

  • หากโฮมไดเร็กตอรี่ของผู้ใช้มีอยู่ภายนอก/home, หรือไม่เลย, สิ่งนี้แนะนำ แต่ไม่ได้หมายความว่าบัญชีนั้นไม่ควรถูกนำมาพิจารณาเพื่อแสดงถึงผู้ใช้ที่เป็นมนุษย์ /homeวิธีการนี้จะแสดงเฉพาะผู้ใช้เมื่อมีการไดเรกทอรีที่มีชื่อเดียวกันใน
  • หากคุณสร้างไดเรกทอรีเพิ่มเติมใน/homeนั้นไม่ใช่ไดเรกทอรีบ้านของใครและพวกเขามีชื่อเดียวกันกับผู้ใช้ที่ไม่ใช่มนุษย์ - หรือประกอบด้วยคำที่คั่นด้วยช่องว่างหนึ่งหรือมากกว่านั้นมีชื่อเดียวกัน ในฐานะผู้ใช้ที่ไม่ใช่มนุษย์ - ผู้ใช้ที่ไม่ใช่มนุษย์บางรายอาจรวมอยู่ในผลลัพธ์
    (วิธีนี้สามารถนำมาใช้กับการวนซ้ำและgetentการขอร้องแยกดังนั้นการแยกคำไม่ได้สร้างผลลัพธ์ที่น่าเกรงขาม แต่ความซับซ้อนนั้นไม่ได้รับการรับประกันโดยพื้นฐานถ้าคุณใช้/homeเป็นอย่างอื่นนอกเหนือจากที่สำหรับไดเรกทอรีบ้านของผู้ใช้ ไม่สร้างผลลัพธ์ที่เชื่อถือได้)

ทำให้การตรวจสอบ UID ง่ายขึ้น

ถ้าคุณตัดสินใจที่จะไปด้วยวิธีการที่รหัสผู้ใช้ตรวจสอบเพื่อให้แน่ใจว่าพวกเขาจะอยู่ในช่วงแนวโน้มสำหรับบัญชีที่เป็นตัวแทนของมนุษย์เช่นเดียวกับในคำตอบที่ได้รับการยอมรับหรือคำตอบของ Oliแล้วฉันขอแนะนำนี้สำหรับความกะทัดรัด:

getent passwd | grep -oP '^[^:]+(?=:x:\d{4}:)'

นี่ใช้นิพจน์ปกติ Perl ( -P) เพื่อแสดง:

  • ข้อความที่จุดเริ่มต้นของบรรทัด ( ^) ที่ไม่มี:s ( [^:]+) - นี่คือฟิลด์แรกเช่นเดียว:กับตัวคั่นฟิลด์ในpasswd
  • ที่อยู่ก่อนหน้า แต่ไม่รวม ( (?= )) ฟิลด์รหัสผ่านx- ควรเป็นxเพราะในแฮ็กรหัสผ่าน Ubuntu ถูกเก็บไว้ในshadowฐานข้อมูลไม่ใช่passwdฐานข้อมูลที่อ่านได้ทั่วโลก
  • และฟิลด์ UID ประกอบด้วยตัวเลข 4 หลัก ( :\d{4}:)

นี้จึงเป็นตัวแปรที่มีนัยสำคัญสั้นและค่อนข้างง่ายของเทคนิคในคำตอบที่ได้รับการยอมรับ (เทคนิคที่อธิบายไว้ก็ทำงานได้ดีเช่นกันและมีประโยชน์ในการพกพาไปยังระบบที่ไม่ใช่ GNU / Linux ซึ่งgrepไม่รองรับ-P)

พิจารณาช่วง UID "มนุษย์"

หากคุณต้องการที่จะรองรับ UIDs สูงมากและตรวจสอบnobodyอย่างชัดเจนคุณสามารถใช้วิธีในคำตอบของ Oli อย่างไรก็ตามคุณอาจต้องการพิจารณาหากผู้ใช้ที่มี UID สูงมากควรเป็นมนุษย์จริงๆหรือหากพวกเขามีแนวโน้มที่จะเป็นผู้ใช้ที่ไม่ใช่มนุษย์ (เช่นnobody) ในทางปฏิบัติผู้ใช้ดังกล่าว - นอกเหนือจาก - เป็นnobodyเรื่องผิดปกติดังนั้นนี่เป็นการเรียกการตัดสินในส่วนของคุณ

การประนีประนอมที่เป็นไปได้คือการแสดงผู้ใช้ในช่วงของ UID ที่ได้รับการกำหนดให้กับผู้ใช้ที่สร้างขึ้นใหม่ไม่ใช่ผู้ใช้ "ระบบ" คุณสามารถตรวจสอบสิ่งนี้ได้ในadduser.conf :

$ grep -E '^(FIRST|LAST)_UID' /etc/adduser.conf
FIRST_UID=1000
LAST_UID=29999

ต่อไปนี้เป็นสองวิธีในการแสดงรายการผู้ใช้ที่มี UID อยู่ในช่วง 1,000 ถึง 29999:

getent passwd | grep -oP '^[^:]+(?=:x:[12]?\d{4}:)'
getent passwd | awk -F: '999<$3 && $3<30000 {print $1}'

หากคุณต้องการที่จะเป็นที่ชื่นชอบโวหารbasenameเป็นที่น่าเกลียด lsมันไม่ดีกว่า เหตุผลหลักที่เราไม่แยกวิเคราะห์ ls ก็คือมันเป็นงานที่สามารถทำได้โดยเครื่องมืออื่น ๆ ได้อย่างปลอดภัยและสะอาดไม่มีสไตล์ cd /home; getent passwd *ในกรณีนี้เปลือก:
muru

ฉันเห็นด้วยกับคุณใน / บ้านไม่น่าเชื่อถือ (มันไม่มีประโยชน์สำหรับฉันดูคำตอบของฉัน) ฉันแค่บอกว่าถ้าคุณจะเทศนาเกี่ยวกับสไตล์คาดหวัง nitpicking
muru

@muru ฉันเห็นว่าการใช้ถ้อยคำดั้งเดิมของฉันทำให้ผู้คนเข้าใจผิดคิดว่าการหลีกเลี่ยงการแยกวิเคราะห์lsมักเกี่ยวกับสไตล์ สัญลักษณ์แสดงหัวข้อย่อยที่ 2 เกี่ยวกับ "ผลลัพธ์ที่ไม่น่าพอใจ" ครอบคลุมถึงปัญหา แต่จะปรากฏในส่วนภายหลัง ฉันได้ป้อนข้อความใหม่เพื่อชี้แจงว่าทำไมการแยกวิเคราะห์lsจึงเหมาะสมในสถานการณ์นี้ แม้ว่าcd /home; getent passwd *จะใช้รูปแบบที่มักจะแสดงให้เห็นถึงวิธีการ SOUNDER ผมได้หลีกเลี่ยงมันเพื่อที่จะไม่นำไปสู่ผู้อ่านจะเชื่อว่าเนื้อหาของ/homeไดเรกทอรีกับแปลกรายการเพิ่มไม่สอดคล้องกับผู้ใช้งานจริงอาจยังคงอย่างใดเป็นที่พึ่งเป็นแนวทางในสิ่งที่ มีผู้ใช้งานอยู่
Eliah Kagan

1

TL; DR : เฉพาะผู้ใช้ที่เป็นมนุษย์เท่านั้นที่มี SystemAccount = false

อีกวิธีหนึ่งคือการแสดงรายการของในขณะที่ไม่สนใจรูls /var/lib/AccountsService/users/ | grep -v rootต ตอนนี้มีการเล่นโวหาร - gdm, หน้าจอ greeter / login (หรือมากกว่า desktop manager อย่างเป็นทางการ) ก็แสดงเป็นผู้ใช้ด้วย ดังนั้นจากรายการเราไม่สามารถบอกได้ว่า gdm เป็นมนุษย์หรือไม่

SystemAccount=falseวิธีการที่มีประสิทธิภาพมากขึ้นและถูกต้องคือการไปผ่านไฟล์ในโฟลเดอร์ที่และหาที่ผู้ใช้มีการระบุไว้ว่ามี ร้องหนึ่งซับประสบความสำเร็จ

grep SystemAccount=false /var/lib/AccountsService/users/* | awk -F '/' '{gsub(":","/");print $6}'


1
แม้ว่าบางครั้งก็มีประโยชน์ แต่ก็ล้มเหลวในบางสถานการณ์ที่พบบ่อย ตัวอย่างเช่นในระบบขั้นต่ำของ Ubuntu 15.04 ของฉัน (ติดตั้งจากmini.isoและไม่มีผู้จัดการการแสดงผลหรือติดตั้ง X11) ฉันมีบัญชีผู้ใช้ที่มนุษย์คนหนึ่ง - ยัง/var/lib/AccountsService/usersเป็นไดเรกทอรีว่างเปล่า ฉันคาดหวังว่าสิ่งนี้จะไม่ทำงานในการติดตั้ง Ubuntu Server ที่ไม่ทันสมัย นอกจากนี้เมื่อนี้ไม่ทำงานก็ไม่ได้อยู่ภายใต้ความคิดที่ค่อนข้างเข้มงวดของสิ่งที่ทำให้บัญชีผู้ใช้ "คน": การทำให้ผู้ใช้ที่มีuseraddแม้โดยไม่ต้อง ไม่สร้างแฟ้มใน--system AccountsService/users
Eliah Kagan

1

ฉันเข้าร่วมงานปาร์ตี้ฉันดูแลระบบเครือข่ายโดยใช้ LDAP มีโฮมไดเรกทอรีภายนอก/homeและ UID (เนื่องจากข้อผิดพลาดของสคริปต์) เป็นล้าน ๆ ดังนั้นจึงไม่มีคำตอบปัจจุบัน การทดสอบที่ใช้งานได้สำหรับฉันกำลังตรวจสอบว่าผู้ใช้มีเชลล์ล็อกอินที่ถูกต้องหรือไม่ เปลือกหอยที่ถูกต้องเป็นหนึ่งซึ่งเป็น บริษัท /etc/shellsจดทะเบียนใน แบบฟอร์มที่ง่ายที่สุด:

getent passwd | grep -wFf /etc/shells

ไฟล์อาจมีความคิดเห็น (หรือบรรทัดว่าง) ดังนั้นอาจมีการกรองพวกเขาออก:

getent passwd | grep -wFf <(grep '^/' /etc/shells)

+1 นี่อาจเป็นวิธีที่มีประสิทธิภาพที่สุดที่แนะนำจนถึงตอนนี้ แม้ว่าจะมีข้อเสียของการแสดงroot(ซึ่งอาจไม่ควรพิจารณาว่าเป็นผู้ใช้ที่เป็นมนุษย์เนื่องจากมนุษย์มักจะกลายเป็นรูตชั่วคราวและเพื่อวัตถุประสงค์เฉพาะแทนที่จะใช้เพื่อการทำงานปกติ) ดูเหมือนว่ามีโอกาสน้อยที่จะล้มเหลวใน วิธีการที่สำคัญใด ๆ วิธีการในคำตอบอื่น ๆ (รวมถึงของฉัน) อาจล้มเหลวขึ้นอยู่กับวิธีการหากไดเรกทอรีบ้านไม่ได้อยู่ใน/homeขยะอื่น ๆ ที่อยู่ใน/homeUIDs จะแปลกหรือระบบไม่ได้ใช้ DM คำตอบนี้ใช้ได้ดีในทุกสถานการณ์
Eliah Kagan

1

บนระบบ buntu ผู้ใช้ปกติ (ผู้ใช้ที่เป็นมนุษย์) มี UID ที่ขึ้นต้นด้วย 1,000 ซึ่งกำหนดตามลำดับเมื่อสร้างบัญชีครั้งแรก สิ่งทั้งหมดนี้ทำให้เกิดขึ้นได้ก็คือบัญชีแรกที่สร้างขึ้นในระบบ buntu มี UID 1,000 รายการถัดไปที่สร้างขึ้นมี UID 1001 และอื่น ๆ

ดังนั้นวิธีที่ง่ายที่สุดในการแสดงรายการบัญชีผู้ใช้ที่เป็นมนุษย์ทั้งหมดในระบบในความคิดของฉันคือการตรวจสอบว่าคอลัมน์ที่สามใน/etc/passwdไฟล์ที่มี UID ของผู้ใช้มากกว่าหรือเท่ากับ 1,000 และน้อยกว่าสมมติว่า 2000 (เป็นไปได้ยากที่พีซีเดสก์ท็อปทั่วไปจะมีบัญชีผู้ใช้มากกว่าหนึ่งพันบัญชีคุณไม่คิดอย่างนั้นหรือ):

$ awk -F$':' '{ if ($3 >= 1000 && $3 < 2000) print $1; }' /etc/passwd

ขอบคุณที่อธิบายคำตอบของ Oli พร้อมรายละเอียด nobodyนอกจากนี้คุณยังจะต้องกรอง =)
Anatoly techtonik

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