是否可以在/ etc / passwd的后台添加/删除用户?

时间:2015-11-26 19:04:34

标签: linux python-2.7

from pwd import getpwuid
getpwuid(48).pw_name

这个Python程序99%的时间打印apache。 48是apache用户/etc/passwd中显示的ID。没有任何明显的原因,Python有时会打印错误:

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

我需要了解为什么有时会发生这种情况。出于某种原因,是否可以从文件中删除apache用户?

2 个答案:

答案 0 :(得分:1)

以下是pwd模块的CPython 2.7源代码,特别是getpwuid()调用:https://github.com/python/cpython/blob/2.7/Modules/pwdmodule.c#L114它看起来像是系统getpwuid调用的包装器,代码不是很多 - Python没有直接从/ etc / passwd读取。

以下是(3)getpwuid:http://manpages.ubuntu.com/manpages/wily/man3/getpwuid.3posix.html的当前Ubuntu联机帮助页(您没有提及任何特定操作系统),其中包括:

  

<强>错误

     

如果出现以下情况,则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变得不可能。

答案 1 :(得分:0)

这是一个非常有趣的现象(也是一个很好的问题),但我怀疑Apache是​​从newArr[weekNum] = []; 文件中删除的。

在GNU / Linux系统上,可以使用许多不同的身份验证机制。在现代系统中,Name Service Switch (NSS)用于解析用户名和ID。这是在/etc/passwd的{​​{1}}行中配置的,例如,以下配置意味着将首先搜索passwd,如果找不到用户或ID,则配置的NIS服务器用于确定用户名/ ID。

/etc/nsswitch.conf

但是,在某些系统中,NSS库函数实际上可能不会用于解析名称请求。某些系统可能会运行/etc/passwd等服务。这是一个缓存名称服务请求的守护程序,例如,如果以前查找过Apache用户,它的名称将存储在passwd: files nis 缓存中,并且它将返回正确的名称或ID而不nscd被搜查。

调试

我会尝试通过nscd运行Python程序来调试此问题。在输出文件的最后,您应该看到用于检索用户名称的系统调用。

/etc/passwd

您需要足够长时间运行此命令以捕获对strace的调用,而无法查看失败的原因。举个例子,我很想看到结果。

实施例

以下是没有运行缓存守护程序的输出示例,NSS用于读取strace -o getpwuid_test.trace getpwuid_test.py 文件:

getpwuid

以下是运行/etc/passwd服务并绕过NSS库的示例:

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)