Подсистема учётных записей
Несколько конфигурационных файлов и способы работы с ними заслуживают отдельного рассмотрения. В первую очередь Мефодий заинтересовался системой учётных записей, о которой упоминалось сразу в нескольких предыдущих лекциях. Итак, существует два файла, доступных для чтения всем пользователям: /etc/passwd
, хранящий учётные данные пользователей, и /etc/group
, определяющий членство пользователей в группах (во всех, кроме группы по умолчанию):
methody@localhost:~ $ cat /etc/passwd
root:x:0:0:System Administrator:/root:/bin/bash
bin:x:1:1:bin:/:/dev/null
daemon:x:2:2:daemon:/:/dev/null
adm:x:3:4:adm:/var/adm:/dev/null
lp:x:4:7:lp:/var/spool/lpd:/dev/null
. . .
nobody:x:99:99:Nobody:/var/nobody:/dev/null
shogun:x:400:400:Лев Гуревич:/home/shogun:/bin/zsh
methody:x:503:503:Мефодий Кашин:/home/methody:/bin/bash
methody@localhost:~ $ cat /etc/group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
adm:x:4:root,adm,daemon,shogun
wheel:x:10:root,shogun
. . .
proc:x:19:root,shogun
shogun:x:400:
methody:x:503:
Пример 6. Файлы /etc/passwd
и /etc/group
Оба файла состоят из строк, поля которых разделяются двоеточиями. В файле passwd
— семь полей. Первое из них определяет входное имя пользователя — то самое, что вводится в ответ на «login:
». Второе поле раньше, в ранних версиях UNIX, использовалось для хранения ключа пароля. В Linux пользовательские пароли не хранятся нигде, ни в явном виде, ни в зашифрованном. Вместо этого хранится ключ (hash) пароля — комбинация символов, однозначно соответствующая паролю, из которой, однако, сам пароль получить нельзя. Иными словами, существует алгоритм превращения пароля в ключ, а алгоритма превращения ключа в пароль нет. Когда пользователь регистрируется в системе, из введённого им пароля изготавливается ещё один ключ. Если он совпадает с тем, что хранится в учётной записи, значит, пароль правильный.
Авторы UNIX предполагали, что, раз пароль из ключа получить нельзя, ключ можно выставлять на всеобщее обозрение, однако выяснилось, что, узнав ключ, пароль можно попросту подобрать на очень мощной машине или в предположении, что пароль — это английское слово, год рождения, имя любимой кошки и т. п. Если подбор пароля сопровождается неудачными попытками входа в систему, это отражается в системных журналах и может быть легко замечено. А завладев ключом, злоумышленник сможет заняться подбором втихомолку на каком-нибудь суперкомпьютре. В конце концов, ключ не нужен никому, кроме подсистемы идентификации, поэтому его, вместе с другими полями учётной заиси, о которых знать всем не обязательно, из /etc/passwd
перенесли в «теневой» файл учётных записей /etc/shadow
. На месте ключа в Linux должна быть буква «x
»; если там стоит что-то другое, идентификация пользователя не сработает, и он не сможет войти в систему.
Третье и четвёртое поля passwd
— идентификатор пользователя и идентификатор группы по умолчанию. Как уже говорилось в лекции Права доступа именно идентификатор пользователя, а не его входное имя, однозначно определяет пользователя в системе и его права. Вполне возможно создать несколько учётных записей с одинаковыми UID, которые различаются другими полями. Тогда при регистрации в системе под именами из этих записей, пользователи могут получать разные домашние каталоги и командные оболочки, разное членство в группах, но иметь одинаковый UID. Пятое поле отводится под «полное имя» пользователя; это единственное поле passwd
, содерджимое которого ни на что не влияет. Наконец, шестое и седьмое поля содержат домашний каталог и стартовый командный интерпретатор пользователя. Если седьмое поле пусто, подразумевается /bin/sh
, а если его содержиимое не встречается в файле /etc/shells
, содержащего допустимые командные интерпретаторы, неизбежны трудности при идентификации пользователя.
Строки файла /etc/group
состоят из четырёх полей, причём второе — ключ группового пароля — обычно не используется. Первое поле — это имя группы, третье — это идентификатор группы, а четвёртое — это список входных имён пользователей, которые в эту группу входят (более точно — для которых эта группа является дополнительной, так как группа по умолчанию указывается в /etc/passwd
, хотя никто не мешает продублировать группу по умолчанию и в /etc/group
). Таким образом, определение членства пользователя в группах зависит не от его UID, а от входного имени.
Упомянутый выше файл /etc/shadow
, доступ к котрому имеет только суперпользователь, также состоит из полей, разделяемых двоеточиями. Помимо входного имени и ключа пароля там указываются различные временные характеристики учётной записи: нижняя и верхняя граница времени жизни пароля, самой учётной записи, дата последнего изменения и т. п. Ключ пароля (второе поле) указывается в одном из поддерживаемых форматов, а если формат не опознан, вся учётная запись считается недействительной. Поэтому один из способов запретить регистрацию пользователя в системе — добавить один символ (например, «!
») прямо в поле ключа, отчего всё поле становится синтаксически неправильным. Вновь разрешить пользователью входить в систему можно, удалив из поля лишний символ. Именно так работает (с ключами «-L
», lock, и «-U
», unlock) утилита usermod
, изменяющая учётную запись. С помощью этой утилиты можно отредактировать и все остальные поля как passwd
, так и shadow
.
Добавить и удалить пользователя или группу можно с помощью утилит useradd
, userdel
, groupadd
и groupdel
соответственно. Не стоит пользоваться текстовым редактором, так как он не гарантирует атомарности операции добавления/удаления, хотя бы потому, что изменению подлежат сразу два файла — passwd
и shadow
. Даже если необходимо отредактировать/etc/passwd
или /etc/group
(например, для добавления пользователя в группу или удаления его оттуда), стоит запускать не просто редактор, а vipw
или vigr
(именно их поведение, позволяющее соблюсти атомарность, копирует утилита visudo
, описанная ранее).
[root@localhost root]# useradd -g users -G proc,cdrom -c "Incognito" incognito
[root@localhost root]# id incognito
uid=504(incognito) gid=100(users) groups=100(users),19(proc),22(cdrom)
[root@localhost root]# userdel -r incognito
[root@localhost root]# id incognito
id: incognito: No such user
Пример 7. Добавление и удаление пользователя
Здесь был добавлен пользователь incognito
, группа по умолчанию — users
, член групп proc
и cdrom
, полное имя — «Incognito». Стоит заметить, что пароль для этой учётной записи установлен не был (чтобы создать пароль, стоило запустить команду passwd incognito
), и, даже если бы пользователя тут же не удалили (userdel -r
удаляет также и домашний каталог, и почтовый ящик), зарегистрироваться в системе под имененем incognito
было бы всё равно невозможно.
Подсистема идентификации
Подсистемой учётных записей пользуется подсистема идентификации, которая в Linux имеет модульную структуру и называется PAM (Pluggable Authentication Modules, т. е. Подключаемые Модули Идентификации). Идея PAM — в том, чтобы унифицировать и, вместе с тем, сделать более гибкой любые процедуры идентификации в системе — начиная от команды login
и заканчивая доступом к файлам по протоколу, скажем, FTP. Для этого недостаточно просто написать «библиотеку идентификации» и заставить все программы её использовать. В зависимости от того, для чего производится идентификация, условия, при которых оня будет успешной, могут быть более или менее строгими, а если она прошла успешно, бывает нужно выполнить действия, связанные не с определением пользователя, а с настройкой системы.
В большинстве дистрибутивов PAM обучен схеме «. d», и настройки каждой службы, которая использует идентификацию, лежат в отдельном файле:
[root@localhost root]# ls /etc/pam.d
chpasswd groupdel other system-auth userdel
chpasswd-newusers groupmod passwd system-auth-use_first_pass usermod
crond login sshd user-group-mod
groupadd newusers su useradd
Пример 8. Подключаемые Модули Идентификации (PAM)
В PAM определено четыре случая, требующие идентифкации: auth
— собственно идентификация, определние, тот ли пользователь, за кого он себя выдаёт, account
— определение, всё ли хорошо с учётной записью пользователя, password
— изменение пароля в учётной записи, и session
— дополнительные действия непосредственно перед или непосредственно после того, как пользователь получит доступ к затребованной услуге. Эти значения принимает первое поле любого файла настройки из pam.d
, а в третьем поле записывается модуль, который проверяет какой-нибудь из аспектов идентификации. Второе поле определяет, как успех или неуспех проверки одного модуля влияет на общий успех или неуспех идентификации данного типа (например, required
означает, что в случае неуспеха модуля проверка пройдена не будет). Четвёртое и последующие поля отведены под параметры модуля.
[root@localhost root]# cat /etc/pam.d/login
auth include system-auth
auth required pam_nologin.so
account include system-auth
password include system-auth
session include system-auth
session optional pam_console.so
[root@localhost root]# cat /etc/pam.d/system-auth
auth required pam_tcb.so shadow count=8 nullok
account required pam_tcb.so shadow
password required pam_tcb.so use_authtok shadow count=8 write_to=tcb
session required pam_tcb.so
Пример 9. Настройка PAM для login
Такие настройки login
обнаружил Мефодий на своём компьютере. Во всех четырёх случаях используется включаемый файл system-auth
(к нему обращаются и другие службы), с некоторыми дополнениями: во время идентификации pam_nologin.so
дополнительно проверяет, не запрещено ли пользователям регистрироваться вообще (как это бывает за несколько минут до перезагрузки системы), а перед входом в систему и после выхода из неё pam_console.so
выполняет описанную в лекции Права доступа «передачу прав на владение устройствами» (и, соответственно, лишение пользователя этих прав).
Каталог /etc/pam.d
— замечательный пример того, как профиль определяет поведение системы. В частности, четыре первых строки из system-auth
показывают, что в этом дистрибутиве используется не просто «теневой» файл паролей, а схема TCB, описанная в лекции Права доступа. (Как уже известно Мефодию, в этой схеме вместо общего для всех /etc/shadow
задействованы файлы вида /etc/tcb/входное_имя/shadow
, причём права доступа к ним устроены таким образом, чтобы при выполнении команды passwd
можно было обойтись без подмены пользовательского идентификатора на суперпользовательский).
Подсистема системных журналов
Проста и остроумна в Linux подсистема ведения системных журналов — демон syslogd
, управляемый конфигурационным файлом /etc/syslog.conf
и «. d»-каталогом /etc/syslog.d
. Если какой-нибудь демон или служба желает сообщить системе о том, что наступило событие, которое стоит запомнить, у неё есть два пути. Во-первых, можно просто добавлять очередную запись в файл, который сам этот демон и открыл; этот файл будет журналом его сообщений. Во-вторых, можно воспользоваться системным вызовомsyslog()
, который переадресует текстовое сообщение специальному демону — syslogd
— а уж тот разберётся, что с этим сообщением делать: записать в файл, вывести на 12-ю консоль или забыть о нём. Второй путь (централизованная журнализация) предпочтительнее почти всегда; исключение — случай, когда сообщения по какой-то причине не могут быть текстовыми или этих сообщений предполагается посылать так много, что syslogd
просто не справится.
Все события, сообщаемые syslogd
, подразделяются горизонтально — по типу службы (facility), с которой это событие произошло события, и вертикально — по степени его важности (priority). Типов событий насчитывается около двадцати (среди них auth
, daemon
, kern
, mail
и т. п., а также восемь неименованных, от local0
до local7
). Степеней важности всего восемь, по возрастанию важности: debug
, info
, notice
, warning
, err
, crit
, alert
и emerg
. Таким образом, каждое событие определяется парой значений, например, mail.err
означает для syslogd
событие, связанное с почтой, притом важности не меньшейerr
. Из таких пар (с возможной заменой типа или важности на «*
», что означает «любые», или none
, что означает «никакие») составляется конфигурационный файл /etc/syslog.conf
:
[root@localhost root]# cat /etc/syslog.conf
*.notice;mail.err;authpriv.err /var/log/messages
authpriv.*;auth.* /var/log/security.log
*.emerg *
*.* /dev/tty12
mail.info /var/log/maillog
Пример 10. Настройка системных журналов
В первом поле строки указываются профили сообщений, разделённые символом «;
», а во втором — хранилище сообщений (файл, терминал, есть способы отдавать их на обработку программе и пересылать по сети). В примере в файл /var/log/messages
попадают все сообщения важности не меньшей, чем notice
, за исключением сообщений типа mail
и authpriv
, которые попадают туда, только если имеют важность не ниже err
. Сообщения типа authpriv
и auth
любой важности попадают в файл /var/log/security.log
, а типа mail
и важности не ниже info
— в файл /var/log/maillog
. Сообщения типа emerg
(наивысшей важности) выводятся на все терминалы системы, и, наконец, все сообщения выводятся на 12-ю виртуальную консоль.
Во многих системах используется основательно доработанный syslogd
, позволяющий фильтровать сообщения не только по типу/важности, но и, например, по отправителю, задавать точные (а не «не меньшие») значения priority и т. п., однако такие доработки нужны для того, чтобы либо вести практически нефильтрованную журнализацию (получаются системные журналы совершенно нечитаемого объёма), либо отводить поток сообщений определённой службы в отдельный журнал, опять-таки, не для чтения, а для последующей обработки.
Стоит заметить, что каталог /etc/syslog.d
в новых версиях syslogd
предназначен для хранения не профильных конфигурационных файлов в стиле «. d», а сокетов, из которых демон может получать сообщения так же, как и из сети или в результате системного вызова syslog()
.
Выполнение действий по расписанию
Другой пример типичной для Linux службы, управляемой конфигурационным файлом, — демон cron
, регулярно выполняющий в заданное время заданные действия.
Программисты имели в виду Хроноса, стихийное божество времени у древних греков. Уже сами греки часто называли так «владыку неба» титана Крона (отца богов-кронидов и, среди прочих, Зевса, который впоследствии папу и других титанов заключил в Тартар, и стал владыкой неба сам). У древних римлян и Крон и Хронос почитались под именем Сатурна, божества неумолимого времени.
Время от времени в системе необходимо обновлять разнообразные файлы, например, базы данных антивирусов (вирусов в Linux нет, а антивирусы есть!), базу данных whatis
или список всех доступных на чтение файлов системы, locatedb
(поискать по этому списку можно командой locate
); нужно собирать статистику по работе системы, анализировать цельность системы (этим занимаются службы OSec, TripWire или AIDE) и производить множество других регулярных действий. Всем этим и занимается демон cron
.
Конфигурационный файл демона cron
называется /etc/crontab
.
[root@localhost root]# cat /etc/crontab
#minute (0-59),
#| hour (0-23),
#| | day of the month (1-31),
#| | | month of the year (1-12),
#| | | | day of the week (0-6 with 0=Sunday).
#| | | | | user
#| | | | | | commands
01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly
Пример 11. Настройка cron
Первые пять полей этого файла определяют время запуска команды: минуту, час, число месяца, месяц и день недели. Символ «*
» означает, что соответствующая часть даты не учитывается. Шестое поле — имя пользователя, от лица которого зпускаются команда, указанная в остальных полях строки. Так, в примере команда run-parts /etc/cron.weekly
будет запускаться в 4 часа 22 минуты каждое воскресенье (нулевой день) любого числа любого месяца.
Как видно из примера, обычно /etc/crontab
невелик: чаще всего он состоит из почасового, подённого, понедельного и помесячного запуска специального сценария (в примере — run-parts
). Этот сценарии реализует упрощённую схему «. d», он попросту запускает отсортированные в лексикографическом порядке сценарии из соответствующего каталога (например, из /etc/cron.daily
):
То есть в таком порядке, в котором они были бы расставлены в словаре. Причём цифры предшествуют алфавитным знакам, а между собой сортируются по возрастанию, от 0 до 9. Отсюда «000anacron
» — такое имя обеспечит, чтобы этот сценарий был выполнен самым первым.
[root@localhost root]# ls /etc/cron.daily
000anacron logrotate makewhatis osec stmpclean updatedb
Пример 12. Сценарии, запускаемые ежедневно
Вот что происходит каждый день на машине Мефодия: запуск anacron
и «прокручивание» системных журналов (об этом речь пойдёт далее), обновление базы whatis
, проверка цельности системы с помощью osec
, прореживание старых и неиспользуемых файлов в /tmp
(утилита stmpclean
) и, наконец, обновление базы locatedb
.
Пользователям системы можно разрешить иметь собственные расписания, также обрабатываемые демоном cron. Эти расписания имеют тот же синтаксис, что и crontab
, только шестое поле («user») в них отсутствует. Редактировать пользовательские таблицы рекомендуется с помощью команды crontab -e
(чтобы не подсунуть демону синтаксически неверный файл). Сами таблицы могут храниться, в зависимости от версии и настроек cron
, в /var/spool/cron/crontabs
, /var/spool/cron
, /var/cron/tabs
или ещё где-нибудь.
Служба anacron
появилась в Linux-системах в то время, когда их начали активно использовать на пресональных рабочих станциях. Такие станции, в отличие от серверов, не обязаны работать круглосуточно. Скорее всего, на ночь, на праздники и на время отпуска их выключают. Это значит, что все настройки cron
надо менять в соответствии с графиком включений/выключений (иначе cron.daily
никогда не выполнится в четыре часа ночи) — или запускать отдельную службу, которая будет выполнять некоторые задачи не по расписанию, а потому что их давно уже пора запустить.
Название этого демона пародирует cron
с намёком на анахронизм, то есть несвоевременность выполнения заданий.
Дополнительно anacron
рассчитывает запуск задач так, чтобы не перегрузить компьютер работой, если их накопилось слишком много. Конфигурационный файл anacron
называется /etc/anacrontab
.
«Прокручивание» системных журналов
Ещё изучая работу syslog
, Мефодий не расставался с мыслью, что файл, в котором записывается системный журнал, постоянно растёт. Это значит, что каков бы ни был размер файловой системы /var
, она в конце концов заполнится журналами под завязку — если как-то их не укорачиваить. К сожалению, в Linux укоротить файл от начала, отрезав самые старые записи, нельзя, как нельзя и добавлять новые записи в начало файла. Эти операции легко реализовать с помощью копирования нужной области в новый файл и последующего переименования, но, во-первых, соблюсти атомарность таких составных операций нелегко, а во-вторых, они требуют удвоенного места в файловой системе на время работы (и, стало быть, каких-то аварийных процедур на случай нехватки места).
Поэтому в Linux принят другой, существенно менее ресурсоёмкий алгоритм, позволяющий избежать переполнения /var
: т. н. «прокручивание» системных журналов. Суть алгоритма в следующем: когда настаёт пора укоротить журнал (например, раз в неделю или если файл журнала достиг определённого размера), этот файл переименовывают, и открывают новый пустой файл с тем же именем. Если хранить несколько (скажем, семь) переименованных старых файлов, с ними уже можно произвоить операцию «отбрасывния старого»: самый старый — седьмой — файл удаляется, шестой переименовывается в седьмой, пятый — в шестой, и т. д. до первого (моложе которого только текущий журнал), который переименовывается во второй. Только тогда можно переименовать текущий журнал в «первый старый», и открыть новый. Получается очередь устаревающих файлов, пополняемая с одной стороны и усекаемая с другой.
Как правило имя «первого старого» журнала получается добавлением к имени журнала суффикса «.1
», второго — «.2
» и т. д.:
[root@localhost root]# ls -l /var/log/syslog/messages*
-rw-r----- 1 root adm 292654 Dec 15 14:01 /var/log/syslog/messages
-rw-r----- 1 root adm 34452 Dec 13 01:09 /var/log/syslog/messages.1.bz2
-rw-r----- 1 root adm 35892 Dec 6 09:38 /var/log/syslog/messages.2.bz2
-rw-r----- 1 root adm 60806 Nov 28 10:59 /var/log/syslog/messages.3.bz2
-rw-r----- 1 root adm 61063 Nov 21 10:47 /var/log/syslog/messages.4.bz2
-rw-r----- 1 root adm 60079 Nov 14 21:18 /var/log/syslog/messages.5.bz2
Пример 13. Системный журнал messages
Прокручиванием системных журналов занимается утилита logrotate
, которая тоже управляется и конфигурационным файлом /etc/logrotate.conf
и «. d»-каталогом /etc/logrotate.d/
. Согласно настройкам, старые файлы можно сжимать упаковщиками bzip2
(как в примере) или gzip
, можно задавать им определённые права доступа, можно посылать сигнал некоторой службе (чтобы она заметила подмену журнала, если она сама, а не syslogd
занимается его пополнением) и т. п.