当我将 /etc/passwd /etc/shadow /etc/group 从 /etc 移动到 /home 并创建符号链接以便 /etc/{passwd,shadow,group} 分别指向 /home/{passwd,shadow,group} 时,我在 useradd 方面遇到了问题
我无法创建任何用户并有 useradd 输出:
root@client:/home# useradd testuser
Adding user `testuser' ...
Adding new group `testuser' (1000) ...
groupadd: cannot open /etc/group
顺便说一下 useradd 输出是
root@client:/home# adduser testuser
useradd: cannot open /etc/passwd
答案1
为什么useradd
拒绝打开符号链接/etc/passwd
?
要回答这个问题,我们需要看一下源代码useradd
(我在 Ubuntu 12.04 上做了这个,在 Debian 上可能略有不同):
找出哪个包拥有
/usr/sbin/useradd
:$ dpkg-query -S /usr/sbin/useradd passwd: /usr/sbin/useradd
安装源:
$ apt-get source passwd Reading package lists... Done Building dependency tree Reading state information... Done Picking 'shadow' as source package instead of 'passwd' (...) dpkg-source: info: extracting shadow in shadow-4.1.4.2+svn3283 dpkg-source: info: unpacking shadow_4.1.4.2+svn3283.orig.tar.gz dpkg-source: info: applying shadow_4.1.4.2+svn3283-3ubuntu5.1.diff.gz (...)
cd
到源目录:$ cd shadow-4.1.4.2+svn3283/
在目录中搜索 的
useradd
源文件,理想情况下该文件应该被称为useradd.c
:$ find . -name useradd.c ./src/useradd.c
答对了!
查找错误消息
cannot open /etc/passwd
(实际上我只搜索cannot open
,因为整个字符串没有返回任何结果):$ grep -B 1 'cannot open' src/useradd.c (...) if (pw_open (O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); (...)
-B 1
表示在匹配行之前打印 1 行前导上下文。这就是您看到的错误消息生成的地方。函数
pw_open
控制是否/etc/passwd
可以打开或是否应抛出错误。pw_open
不是Linux系统调用(apropos pw_open
没有返回任何结果),所以它很可能在这个包中实现。我们来搜索一下。追踪结果
pw_open
显示:$ grep -R pw_open * (...) lib/pwio.c:int pw_open (int mode) (...)
pw_open
实施方案是:$ grep -A 3 'int pw_open (int mode)' lib/pwio.c int pw_open (int mode) { return commonio_open (&passwd_db, mode); }
越来越近了,但我们还没有到达。
commonio_open
这是我们的新目标。搜索
commonio_open
:$ grep -R commonio_open * (...) lib/commonio.c:int commonio_open (struct commonio_db *db, int mode)
打开
lib/commonio.c
并滚动到功能commonio_open
:int commonio_open (struct commonio_db *db, int mode) { (...) fd = open (db->filename, (db->readonly ? O_RDONLY : O_RDWR) | O_NOCTTY | O_NONBLOCK | O_NOFOLLOW);
你看到了
O_NOFOLLOW
吗?这就是罪魁祸首(来自man 2 open
):O_NOFOLLOW If pathname is a symbolic link, then the open fails.
总而言之,useradd.c
使用pw_open
,进而使用,使用带有选项的系统调用commonio_open
打开,拒绝符号链接。/etc/passwd
open
O_NOFOLLOW
尽管在很多(我想说大多数)情况下符号链接可以用来替换文件,但它useradd
却很挑剔并拒绝它,可能是因为符号链接/etc/passwd
强烈暗示该文件/etc
已被篡改。
我为什么要passwd
离开/etc
?
启动和登录需要几个文件/etc
,例如(但不限于):fstab
、、和中的 init 脚本。任何系统管理员都希望这些文件在那里,而不是符号链接到inittab
或任何地方。passwd
shadow
init.d/
/home
因此,即使可以,你也应该passwd
离开/etc
。
此外,Linux中的文件系统结构定义明确,请在此处查看:http://www.pathname.com/fhs/pub/fhs-2.3.html。还有一章/etc
。不建议移动物品。
答案2
医生,我这样做的时候会很痛。
那就别这么做!
说真的,不要把如此重要的文件放在意想不到的位置。无论您要测试什么:找到更好的方法。如果您要进行集中身份验证:请使用 ldap。或者如果必须,请使用 nis。
答案3
系统无法对文件 /etc/passwd、/etc/shadow 进行任何更改
再生问题:
[root@ubuntu]# useradd salten
cannot open /etc/passwd
useradd: cannot open /etc/group
useradd: cannot open /etc/gshadow
下面显示文件是不可变的,如果您设置了参数-i
,文件将被标记为“不可变”,这意味着它的数据(和一些重要的元数据)不能被更改,即使是由 root 更改,直到属性被取消设置。
列出属性:
[root@salten]#lsattr /etc/passwd
----i-------- /etc/shadow
更改文件属性:
[root@salten]# chattr -i /etc/passwd
[root@salten]# lsattr /etc/passwd
[root@salten]# chattr -i /etc/group
[root@salten]# chattr -i /etc/gshadow
尝试添加用户:
[root@salten]# useradd apache
有用 !!!