当我将/ etc / passwd / etc / shadow / etc / group从/ etc移动到/ home并创build符号链接以使/ etc / {passwd,shadow,group}分别指向/家用/ {passwd文件,阴影,组}
我不能创build任何用户,并有useradd输出:
root@client:/home# useradd testuser Adding user `testuser' ... Adding new group `testuser' (1000) ... groupadd: cannot open /etc/group
btw useradd输出是
root@client:/home# adduser testuser useradd: cannot open /etc/passwd
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/
searchuseradd的源文件的目录,理想的应该是useradd.c :
$ find . -name useradd.c ./src/useradd.c
答对了!
找错误信息cannot open /etc/passwd (其实我只searchcannot open ,因为整个string不返回任何结果):
$ 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不返回任何结果),所以它可能在这个包中实现。 我们来search一下吧
跟踪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是我们的新目标。
searchcommonio_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 open系统调用,拒绝符号链接。
尽pipe一个符号链接可以用来代替许多文件(我会说是最多的),但是useradd是相当挑剔的,可能是因为符号链接的/etc/passwd强烈暗示/etc已被篡改。
/etc留下passwd ? 在/etc有几个文件需要引导和login,例如(但不限于): fstab , inittab , passwd , shadow和init.d/的init脚本。 任何系统pipe理员都期望这些文件在那里,而不是符号链接到/home或任何地方。
所以即使你可以,你也应该在/etc留下passwd 。
此外,Linux中的文件系统结构已经定义好了,请看这里: http : //www.pathname.com/fhs/pub/fhs-2.3.html 。 还有一个/etc的章节。 移动的东西不build议。
医生,当我这样做的时候很痛
那么不要这样做!
严重的是,不要把文件粘贴在意想不到的地方。 无论你想要testing什么:find一个更好的方法。 如果您正在尝试执行中央身份validation,请使用ldap。 或者如果必须的话。