У меня проблемы с useradd, когда я перемещаю / etc / passwd / etc / shadow / etc / group из / etc в / home и создаю символическую ссылку, чтобы / etc / {passwd, shadow, group} соответственно указывали на / главная / {passwd, shadow, group}
я не могу создать ни одного пользователя и выводить 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/
Найдите в каталоге 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
, inittab
, passwd
, shadow
и сценарии инициализации в init.d/
. Любой системный администратор ожидает, что эти файлы будут там, а не привязаны к /home
или где угодно.
Так что даже если бы ты мог, ты должен уйти passwd
в /etc
.
Кроме того, структура файловой системы в Linux четко определена, взгляните на нее здесь: http://www.pathname.com/fhs/pub/fhs-2.3.html. Также есть глава для /etc
. Перемещать вещи не рекомендуется.
Доктор, мне больно, когда я это делаю.
Что ж, тогда не делай этого!
Серьезно, не помещайте такие важные файлы в неожиданное место. Что бы вы ни пытались проверить: найдите лучший способ. Если вы пытаетесь выполнить централизованную аутентификацию: используйте ldap. Или ниш, если нужно.