当我移动
/ etc / passwd文件
/ etc / shadow中
的/ etc /组
从/ etc到/ home并创建一个符号链接,以便/ etc / {passwd,shadow,group}分别指向/ home / {passwd,group}
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的源代码(我在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
答对了!
>查找错误消息无法打开/ etc / passwd(实际上我只搜索无法打开,因为整个字符串不返回任何结果):
$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 syscall(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了吗?这是罪魁祸首(来自男子2开放):
O_nofollow If pathname is a symbolic link,then the open fails.
总结一下,useradd.c使用pw_open,后者又使用commonio_open,它使用带有选项O_nofollow的系统调用打开/ etc / passwd,拒绝符号链接.
尽管在很多(我说的是大多数情况)情况下,符号链接可以用作文件的替换,但是useradd非常挑剔并拒绝它,可能是因为符号链接/ etc / passwd强烈暗示/ etc已被篡改.
我为什么要在/ etc中留下passwd?
/ etc中有几个文件需要引导和登录,例如(但不限于):fstab,inittab,passwd,shadow和init.d /中的init脚本.任何系统管理员都希望这些文件存在,而不是符号链接到/ home或者任何地方.
所以,即使你可以,你也应该把密码留在/ etc中.
此外,Linux中的文件系统结构已经明确定义,请在此处查看:http://www.pathname.com/fhs/pub/fhs-2.3.html.还有一章为/etc
.不推荐移动.