Làm cách nào tôi có thể liệt kê tất cả người dùng mà tôi đã tạo? Tôi đã thử cat /etc/passwd
và nó chỉ liệt kê rất nhiều thứ.
Làm cách nào tôi có thể liệt kê tất cả người dùng mà tôi đã tạo? Tôi đã thử cat /etc/passwd
và nó chỉ liệt kê rất nhiều thứ.
Câu trả lời:
Người dùng con người có UID bắt đầu từ 1000, vì vậy bạn có thể sử dụng thực tế đó để lọc ra những người không phải là con người:
cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1
Thao tác này sẽ cắt các trường được phân tách bằng dấu hai chấm (tên người dùng) và thứ ba (UID) /etc/passwd
, sau đó lọc các dòng kết quả kết thúc bằng dấu hai chấm và bốn chữ số, sau đó cắt trường (tên người dùng) đầu tiên từ đó, để lại cho bạn một danh sách người dùng có UID trong khoảng từ 1000 đến 9999.
Nếu bạn có hơn chín nghìn người dùng trên hệ thống của mình, điều này sẽ thất bại - nhưng cần hạn chế kết quả đối với UID 4 chữ số để không bắt nobody
(UID 65534).
Điều này thực hiện khá nhiều những gì câu trả lời được chấp nhận làm, chỉ trong một lệnh thay vì ba:
awk -F: '$3 >= 1000 && $1 != "nobody" {print $1}' /etc/passwd
Và nhờ Karel trong các bình luận, nobody
người dùng cũng được lọc ra.
Cá nhân tôi chỉ thích sử dụng:
ls /home
Phải thừa nhận rằng đây không phải là danh sách người dùng mà thay vào đó là danh sách các thư mục nhà của họ. Hiện tại người dùng hiện tại trên hệ thống sẽ có thư mục chính trong/home
, nhưng bạn cũng có thể thấy các thư mục chính của những người dùng trước đây đã bị xóa.
Điều này hoạt động cho mục đích của tôi và cũng có thể làm việc cho bạn. Ví dụ: nếu bạn đang tìm cách xóa tài khoản người dùng hóa ra không còn tồn tại ( nonexistent-user
) và chạy lệnh
sudo deluser nonexistent-user
nó sẽ chỉ cho bạn biết rằng người dùng này không tồn tại.
/home
(không liên kết với nhau /home
) so với người dùng con người sẽ có UID dưới 1000 (xét cho cùng, đây là phương pháp phổ biến nhất để giữ trình quản lý hiển thị khỏi danh sách một người dùng trên màn hình đăng nhập, đôi khi có thể được thực hiện cho người dùng con người). Một nhược điểm tương đối nhỏ ở đây là lost+found
sẽ được liệt kê trên các hệ thống có /home
phân vùng riêng .
useradd --no-create-home username
?
useradd --no-create-home
- thư mục chính có thể đã tồn tại hoặc có thể được tạo ngay sau đó - nhưng ls /home
phương thức này hoạt động tốt cho những trường hợp đó.
Mặc dù nó có vẻ như là một ý tưởng rõ ràng, nhưng thực sự có sự mơ hồ trong ý nghĩa của người dùng . Là một tài khoản người dùng cố tình bị ẩn khỏi màn hình đăng nhập vì nó chỉ được sử dụng cho các mục đích chuyên biệt (nhưng bởi con người) là người dùng? Còn ubuntu
người dùng (UID 999) trên CD trực tiếp thì sao? Và các tài khoản khách trong Ubuntu được tạo nhanh chóng và bị hủy sau khi đăng xuất; Họ có phải là người dùng không? Nhiều ví dụ có thể được nghĩ ra.
Do đó, thật phù hợp khi nhiều câu trả lời không tương đương đã được đưa ra. Giải pháp chạy bộ của Saige Hamblinls /home
là những gì mọi người thực sự làm, và trừ khi bạn viết một kịch bản, có lẽ bạn chỉ nên sử dụng nó.
ls /home
mạnh mẽ hơnNhưng có lẽ bạn có người dùng đã bị xóa nhưng thư mục nhà vẫn còn tồn tại /home
và bạn phải tránh liệt kê chúng. Hoặc có thể vì một số lý do khác, bạn phải đảm bảo chỉ các mục trong/home
đó tương ứng với các tài khoản thực được liệt kê.
Trong trường hợp đó, tôi khuyên bạn nên đi qua các tên của tất cả mọi thứ trong /home
để getent
(để lấy passwd
mục của người dùng với những cái tên đó), sau đó cô lập và hiển thị chỉ là lĩnh vực tên người dùng (với grep
, sed
hoặc awk
, theo sở thích của bạn). Bất kỳ một trong số này sẽ làm:
getent passwd $(ls /home) | grep -o '^[^:]*'
getent passwd $(ls /home) | sed 's/:.*//'
getent passwd $(ls /home) | awk -F: '{print $1}'
Điều này sẽ hoạt động tốt, vì bạn không nên có tài khoản người dùng có khoảng trắng hoặc ký tự điều khiển trong tên của họ; không thể, mà không cấu hình lại Ubuntu để cho phép nó ; và nếu bạn làm, bạn có vấn đề lớn hơn. Do đó, các vấn đề thông thường với phân tích cú pháp ls
là không thể áp dụng. Nhưng ngay cả khi nó thực sự ổn ở đây, nếu bạn xem xét việc thay thế lệnh bằng phương pháp ls
thẩm mỹ hoặc chỉ là một thói quen xấu, bạn có thể thích:
getent passwd $(basename -a /home/*) | grep -o '^[^:]*'
getent passwd $(basename -a /home/*) | sed 's/:.*//'
getent passwd $(basename -a /home/*) | awk -F: '{print $1}'
Chúng không chứa khoảng trắng hoặc ký tự điều khiển. Tôi cung cấp cho họ chỉ vì $(ls /home)
trông sai ngay cả khi nó đúng, và do đó chà xát nhiều người dùng sai cách. Trong hầu hết các tình huống, có những lý do thực tế, tốt để tránh phân tích cú phápls
và trong những tình huống đó, phân tích cú pháp basename -a
thường chỉ kém hơn một chút. Tuy nhiên, trong tình huống này, do giới hạn về những ký tự thực tế có thể xảy ra trong tên người dùng , cả hai đều ổn.
Tôi sử dụng getent
chủ yếu vì nó chấp nhận tên người dùng làm đối số để hạn chế đầu ra của nó, nhưng cũng vì nó phổ biến hơn một chút so với kiểm tra /etc/passwd
trực tiếp, trong trường hợp phương tiện xác thực và cơ sở dữ liệu mật khẩu được cung cấp bởi các dịch vụ mạng.
Phương pháp này có lợi ích bổ sung hơn ls /home
là, trên các hệ thống có /home
phân vùng riêng , lost+found
thường xuất hiện trong đầu ra của ls /home
.
lost+found
sẽ chỉ xuất hiện nếu có người dùng (người hoặc không) được gọi lost+found
, điều này là không thể.ls /home
thì tốt thôi-- bạn biết bạn không có người dùng được gọi lost+found
.Không thường xuyên, phương pháp này (trong bất kỳ biến thể nào ở trên) sẽ tạo ra đầu ra không đạt yêu cầu:
/home
hoặc hoàn toàn không có, điều này cho thấy nhưng không ngụ ý tài khoản không nên được coi là đại diện cho người dùng. Phương pháp này chỉ liệt kê người dùng khi có một thư mục cùng tên /home
./home
đó thực sự không phải là thư mục chính của bất kỳ ai và chúng có cùng tên với một người dùng không phải là người hiện tại - hoặc bao gồm các từ được phân tách bằng khoảng trắng, một hoặc nhiều từ có cùng tên với tư cách là một người dùng không phải con người hiện tại - sau đó một số người dùng không phải là con người có thể được đưa vào đầu ra. getent
, vì vậy việc tách từ không tạo ra đầu ra giả. Nhưng sự phức tạp không được bảo đảm; về cơ bản, nếu bạn sử dụng /home
như một nơi khác ngoài thư mục gốc của người dùng, phương thức này sẽ không tạo ra đầu ra đáng tin cậy.)Nếu bạn quyết định thực hiện một phương pháp kiểm tra ID người dùng để đảm bảo chúng nằm trong phạm vi có khả năng cho các tài khoản đại diện cho con người, như trong câu trả lời được chấp nhận hoặc câu trả lời của Oli's , thì tôi khuyên bạn nên làm điều này cho ngắn gọn:
getent passwd | grep -oP '^[^:]+(?=:x:\d{4}:)'
Điều này sử dụng biểu thức chính quy Perl ( -P
) để hiển thị:
^
) không chứa :
s ( [^:]+
) - đây là trường đầu tiên, cũng như :
dấu phân cách trường trongpasswd
(?=
)
) trường mật khẩu x
- phải luôn như vậy x
, vì trong băm mật khẩu Ubuntu được lưu trữ trong shadow
cơ sở dữ liệu, không phải passwd
cơ sở dữ liệu dễ đọc trên thế giới:\d{4}:
).Do đó, đây là một biến thể ngắn hơn đáng kể và có phần đơn giản hơn của kỹ thuật trong câu trả lời được chấp nhận . (Kỹ thuật được mô tả ở đó cũng hoạt động tốt và nó có lợi ích là có thể di chuyển đến các hệ thống grep
không phải GNU / Linux mà không hỗ trợ -P
.)
Nếu bạn muốn chứa UID rất cao và kiểm tra nobody
rõ ràng, bạn có thể sử dụng phương pháp trong câu trả lời của Oli's . Tuy nhiên, bạn có thể cân nhắc, nếu người dùng có UID rất cao nên thực sự là người, hoặc nếu họ có nhiều khả năng là một người dùng không phải là người đặc biệt khác (như nobody
). Trong thực tế những người dùng như vậy - bên cạnh nobody
- không phổ biến, vì vậy thực sự đây là một lời kêu gọi phán xét từ phía bạn.
Một sự thỏa hiệp có thể là liệt kê người dùng trong phạm vi UID thực sự được gán cho người dùng mới được tạo, không thuộc "hệ thống". Bạn có thể kiểm tra điều này trongadduser.conf
:
$ grep -E '^(FIRST|LAST)_UID' /etc/adduser.conf
FIRST_UID=1000
LAST_UID=29999
Dưới đây là hai cách để liệt kê người dùng có UID nằm trong khoảng từ 1000 đến 29999:
getent passwd | grep -oP '^[^:]+(?=:x:[12]?\d{4}:)'
getent passwd | awk -F: '999<$3 && $3<30000 {print $1}'
basename
là xấu xí. Nó không tốt hơn ls
. Lý do chính mà chúng tôi không phân tích ls là vì đó là một công việc có thể được thực hiện bằng các công cụ khác an toàn và sạch sẽ hơn nhiều, không phải là phong cách. Trong trường hợp này, vỏ : cd /home; getent passwd *
.
ls
thường là về phong cách. Điểm đạn thứ 2 về "đầu ra không đạt yêu cầu" đã đề cập đến vấn đề này, nhưng nó sẽ xuất hiện trong phần sau. Tôi đã điều chỉnh lại để làm rõ lý do tại sao phân tích cú pháp ls
là phù hợp trong tình huống này . Mặc dù cd /home; getent passwd *
có một hình thức thường biểu thị cho cách tiếp cận âm thanh hơn, tôi đã tránh nó để không khiến độc giả tin vào nội dung của các /home
thư mục, với các mục được thêm kỳ lạ không tương ứng với người dùng thực, vẫn có thể dựa vào một cách nào đó để làm hướng dẫn cho những gì người dùng tồn tại.
TL; DR : chỉ người dùng con người có SystemAccount = false
Một cách khác là liệt kê đầu ra trong khi bỏ qua root ls /var/lib/AccountsService/users/ | grep -v root
. Bây giờ, có một cách giải quyết - gdm, màn hình chào / đăng nhập (hoặc chính thức hơn là trình quản lý máy tính để bàn) cũng được liệt kê dưới dạng người dùng. Vì vậy, chỉ từ danh sách, chúng tôi không thể biết nếu gdm là con người hay không.
Một cách tiếp cận hiệu quả và đúng đắn hơn là duyệt qua các tệp trong thư mục đó và tìm ra người dùng nào được liệt kê là có SystemAccount=false
. Dưới một lớp lót đạt được rằng
grep SystemAccount=false /var/lib/AccountsService/users/* | awk -F '/' '{gsub(":","/");print $6}'
mini.iso
và không có trình quản lý hiển thị hoặc X11 được cài đặt), tôi có một tài khoản người dùng - nhưng vẫn /var/lib/AccountsService/users
là một thư mục trống. Tôi hy vọng điều này sẽ tương tự không hoạt động trên bản cài đặt Ubuntu Server ngoài luồng. Hơn nữa, khi điều này không hoạt động, nó thực hiện theo một khái niệm hơi hạn chế về điều khiến tài khoản người dùng trở thành "con người": làm cho người dùng có useradd
, ngay cả khi không --system
, không tạo tệp AccountsService/users
.
Tham gia bữa tiệc, tôi giám sát một hệ thống mạng bằng LDAP, có các thư mục chính bên ngoài /home
và UID (do trục trặc kịch bản) trong hàng triệu. Không có câu trả lời hiện tại, do đó, làm việc. Thử nghiệm phù hợp với tôi là kiểm tra xem người dùng có vỏ đăng nhập hợp lệ hay không. Một vỏ hợp lệ là một vỏ được liệt kê trong /etc/shells
. Hình thức đơn giản nhất:
getent passwd | grep -wFf /etc/shells
Tệp có thể chứa các nhận xét (hoặc dòng trống), vì vậy người ta có thể phải lọc chúng ra:
getent passwd | grep -wFf <(grep '^/' /etc/shells)
root
( có lẽ không nên được coi là người dùng, vì con người thường tạm thời root và vì mục đích cụ thể, thay vì sử dụng nó cho công việc thường xuyên của họ), có vẻ như đó là khả năng thất bại ít nhất bất kỳ cách chính. Các phương pháp trong câu trả lời khác (kể cả tôi) có thể thất bại, tùy thuộc vào phương pháp, nếu thư mục nhà đang không ở trong /home
, rác khác là trong /home
, UID là lạ, hoặc hệ thống không sử dụng một DM. Câu trả lời này hoạt động khá tốt trong tất cả các kịch bản.
Trên các hệ thống buntu, người dùng thông thường (nghĩa là người dùng) có UID bắt đầu bằng 1000 được gán liên tục cho họ khi tài khoản của họ được tạo lần đầu tiên. Tất cả những điều này có nghĩa là tài khoản đầu tiên được tạo trên hệ thống buntu có UID là 1000. Tài khoản tiếp theo được tạo có UID là 1001. Cứ tiếp tục như vậy.
Vì vậy, cách đơn giản nhất để liệt kê tất cả các tài khoản người dùng có trên hệ thống, theo tôi, là kiểm tra xem cột thứ ba trong /etc/passwd
tệp chứa UID của người dùng có lớn hơn hoặc bằng 1000 và nhỏ hơn không, giả sử, 2000 (rất khó để một máy tính để bàn thông thường có nhiều hơn một nghìn tài khoản người dùng, bạn có nghĩ vậy không?):
$ awk -F$':' '{ if ($3 >= 1000 && $3 < 2000) print $1; }' /etc/passwd
nobody
. =)