簡體   English   中英

可能是在/ etc / passwd中在后台添加/刪除了用戶嗎?

[英]Could it be that users are added/removed in the background from /etc/passwd?

from pwd import getpwuid
getpwuid(48).pw_name

該Python程序有99%的時間打印apache 48是顯示在/etc/passwd中的apache用戶的ID。 沒有明顯的原因,Python有時會打印錯誤:

KeyError: 'getpwuid(): uid not found: 48'

我需要了解為什么有時會發生這種情況。 可以出於某種原因將apache用戶從文件中刪除嗎?

這是pwd模塊的CPython 2.7源代碼,尤其是getpwuid()調用: https : //github.com/python/cpython/blob/2.7/Modules/pwdmodule.c#L114它看起來像是整個系統的包裝器不需要太多代碼的getpwuid調用getpwuid無法直接從/ etc / passwd中讀取。

這是(3)getpwuid的當前Ubuntu手冊頁(您未提及任何特定的操作系統): http : //manpages.ubuntu.com/manpages/wily/man3/getpwuid.3posix.html ,其中包括:

錯誤

如果發生以下情況,則getpwuid()和getpwuid_r()函數可能會失敗:

  EIO An I/O error has occurred. EINTR A signal was caught during getpwuid(). EMFILE {OPEN_MAX} file descriptors are currently open in the calling process. ENFILE The maximum allowable number of files is currently open in the system. 

既然您沒有提到任何可能會重新生成用戶帳戶的用戶管理流程,所以我要回答的是,不會,apache不會從/ etc / passwd中刪除,但是您的網絡服務器確實遇到了一些沉重的IO或太多打開文件的情況下,無法讀取/ etc / passwd。

這是一個非常有趣的現象(也是一個很好的問題),但是我懷疑Apache已從您的/etc/passwd文件中刪除。

在GNU / Linux系統上,可以使用多種不同的身份驗證機制。 在現代系統中, 名稱服務交換機(NSS)用於解析用戶名和ID。 這是在/etc/nsswitch.confpasswd行中配置的,例如,以下配置意味着將首先搜索/etc/passwd ,如果找不到用戶或ID,則使用已配置的NIS服務器確定用戶名/ ID。

passwd:     files nis

但是,在某些系統中,NSS庫函數實際上可能未用於解析名稱請求。 某些系統可能會運行諸如nscd的服務。 這是一個緩存名稱服務請求的守護程序,例如,如果以前已經查找過Apache用戶,則其名稱將存儲在nscd緩存中,並且它將返回正確的名稱或ID,而無需搜索/etc/passwd

調試

我將嘗試通過strace運行Python程序來調試此問題。 在輸出文件的最后,您應該看到用於檢索用戶名的系統調用。

strace -o getpwuid_test.trace  getpwuid_test.py

您將需要運行此命令足夠的時間才能捕獲對getpwuid的調用,但無法查看失敗的原因。 我想對結果感興趣。

例子

這是輸出示例,其中沒有運行緩存守護程序,並且使用NSS讀取/etc/passwd文件:

open("/etc/nsswitch.conf", O_RDONLY)    = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=1717, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fa9000
read(3, "#\n# /etc/nsswitch.conf\n#\n# An ex"..., 4096) = 1717
read(3, "", 4096)                       = 0
close(3)                                = 0
...
open("/etc/passwd", O_RDONLY)           = 3
fcntl64(3, F_GETFD)                     = 0
fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0
fstat64(3, {st_mode=S_IFREG|0644, st_size=3012, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fa9000
read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 3012
close(3)                                = 0
...
write(1, "apache\n", 7)

這是一個運行nscd服務並且繞過NSS庫的示例:

socket(PF_FILE, SOCK_STREAM, 0)         = 3
connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"...}, 110) = 0
send(3, "\2\0\0\0\v\0\0\0\7\0\0\0passwd\0", 19, MSG_NOSIGNAL) = 19
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 5000) = 1 ([{fd=3, revents=POLLIN|POLLHUP}])
recvmsg(3, {msg_name(0)=NULL, msg_iov(2)=[{"passwd\0", 7}, {"\270O\3\0\0\0\0\0", 8}], msg_controllen=16, {cmsg_len=16, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, {4}}, msg_flags=0}, 0) = 15
...
write(1, "apache\n", 7)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM