Product SiteDocumentation Site

Глава 9. Сервисы Unix

9.1. Загрузка системы
9.1.1. Система инициализации systemd
9.1.2. Система инициализации System V
9.2. Удалённый вход
9.2.1. Защищённый удалённый вход: SSH
9.2.2. Использование удалённых графических рабочих столов
9.3. Управление правами
9.3.1. Владельцы и разрешения
9.3.2. ACLs - Access Control Lists (Списки контроля доступа)
9.4. Интерфейсы для администрирования
9.4.1. Администрирование через веб-интерфейс: webmin
9.4.2. Настройка пакетов: debconf
9.5. Системные события syslog
9.5.1. Принципы и механизм
9.5.2. Конфигурационный файл
9.6. Суперсервер inetd
9.7. Планирование задач с помощью cron и atd
9.7.1. Формат файла crontab
9.7.2. Использование команды at
9.8. Планирование асинхронных задач: anacron
9.9. Квоты
9.10. Резервное копирование
9.10.1. Резервное копирование с помощью rsync
9.10.2. Восстановление машин без резервных копий
9.11. Горячее подключение: hotplug
9.11.1. Введение
9.11.2. Проблема именования
9.11.3. Как работает udev
9.11.4. Конкретный пример
9.12. Управление питанием: ACPI
Эта глава посвящена нескольким основным сервисам, общим для многих Unix-систем. Все администраторы должны быть хорошо знакомы с ними.

9.1. Загрузка системы

Когда вы загружаете компьютер, множество сообщений, прокручиваемых на консоли, отображают множество выполняемых автоматических процессов инициализации и конфигурирования. Иногда может возникнуть желание несколько изменить работу этого этапа, а значит, необходимо хорошо её понимать. Помочь в этом — назначение данного раздела.
В системах с BIOS сначала BIOS берет на себя управление компьютером, инициализирует контроллеры и аппаратное обеспечение, обнаруживает диски и соединяет всё воедино. Затем он просматривает Master Boot Record (MBR) первого диска в порядке загрузки и загружает сохранённый там код (первый этап). Затем этот код запускает второй этап и, наконец, исполняет загрузчик.
В отличие от BIOS, UEFI более сложный, он знает файловые системы и может читать таблицы разделов. Интерфейс выполняет поиск в системном хранилище раздела, помеченного определенным глобальным уникальным идентификатором (GUID), который помечает его как EFI System Partition (ESP), где находятся загрузчики, менеджеры загрузки, оболочка UEFI и т.д. и запускает нужный загрузчик. Если включена безопасная загрузка, процесс загрузки проверит подлинность двоичных файлов EFI с помощью подписи (таким образом, в этом случае требуется grub-efi-arch-signed). Спецификация UEFI также определяет поддержку загрузки в устаревшем режиме BIOS (legacy BIOS mode). Это называется Compatibility Support Module (CSM). Если CSM включен, он попытается загрузиться с MBR диска. Однако многие новые системы больше не поддерживают режим CSM.
В обоих случаях фактический загрузчик принимает управление на себя, находит либо связанный загрузчик, либо ядро на диске, загружает и выполняет его. Затем ядро инициализируется и начинает поиск и монтирование раздела, содержащего корневую файловую систему, и, наконец, запускает первую программу — init. Зачастую эти «корневой раздел» и init на самом деле находятся на виртуальной файловой системе, существующей только в ОЗУ (отсюда её название — initramfs, ранее — initrd, от "initialization RAM disk"). Эта файловая система загружается в память загрузчиком, часто из файла на жёстком диске или по сети. Он содержит самый минимум, необходимый для того, чтобы ядро загрузило «настоящую» корневую файловую систему: сюда могут входить модули драйверов для жёсткого диска или других устройств, без которых система не способна загрузиться, или, чаще, сценарии инициализации и модули для сборки массивов RAID, открытия зашифрованных разделов, активации томов LVM и т. п. Когда корневой раздел примонтирован, initramfs передаёт управление настоящему процессу "init", и система возвращается к стандартному процессу загрузки.

9.1.1. Система инициализации systemd

«Настоящий init» сейчас предоставляется системой systemd, и в данном разделе описывается эта система инициализации.
Порядок загрузки компьютера с Linux и systemd

Рисунок 9.1. Порядок загрузки компьютера с Linux и systemd

Systemd запускает несколько процессов для настройки клавиатуры, драйверов, файловых систем, сети, служб. При этом сохраняется глобальное представление о системе в целом и требованиях к её компонентам, каждый из которых описан в “unit file” (иногда в нескольких). Синтаксис заимствован из «*.ini файлов» с парами «ключ = значение» — key = value, разделёнными заголовками [section]. Unit-файлы хранятся в каталогах /lib/systemd/system/ и /etc/systemd/system/. Далее будут описаны типы unit «сервис» — service и «цель» — target.
systemd файл “.service file” описывает процесс, управляемый systemd. Он содержит примерно ту же информацию, что и init-скрипты старого стиля, но выраженную в декларативном (и гораздо более кратком) виде. Systemd берет на себя основную часть повторяющихся задач (запуск и остановка процесса, проверка его статуса, ведение журнала, удаление привилегий и т. д.), а служебный файл должен лишь заполнить специфику процесса. Например, вот служебный файл для SSH:
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
Alias=sshd.service
Раздел [Unit] содержит общую информацию о сервисе, такую как его описание и ресурсы страницы руководства, а также связи (зависимость и порядок) с другими сервисами. Часть [Service] содержит объявления, относящиеся к выполнению службы (запуск, остановка, уничтожение, перезапуск), используемые каталоги и файлы конфигурации. Последний раздел [Install] снова содержит общую информацию, в какую цель устанавливать службу, и, в данном случае, псевдоним, который можно использовать вместо имени службы. Как видите, кода там очень мало, только объявления. Systemd отображает отчеты о ходе работы, отслеживает процессы и даже перезапускает их при необходимости. Синтаксис этих файлов полностью описан на нескольких страницах руководства (например, systemd.service(5), systemd.unit(5), systemd.exec(5), и т.д.).
Файл «цели» “.target file” в systemd описывает состояние системы, при котором известно, что набор служб работает. Его можно рассматривать как эквивалент уровня запуска старого стиля. Одной из заранее определенных целей является — local-fs.target; при её достижении остальная система может рассчитывать, что все локальные файловые системы смонтированы и доступны. В число других целей входят network-online.target и sound.target (полный список специальных целей см. systemd.special(7)). Зависимости цели могут быть перечислены либо внутри целевого файла (в строке Requires=), либо с использованием символьной ссылки на файл service в каталоге /lib/systemd/system/targetname.target.wants/. Например /etc/systemd/system/printer.target.wants/ cодержит ссылку на /lib/systemd/system/cups.service, поэтому systemd запустит CUPS для достижения цели printer.target.
Так как файлы unit декларативны, в отличие от сценарием и программ, они не могут запускаться отдельно и интерпретируются только systemd, хотя несмотря на это, несколько вспомогательных программ позволяют администратору взаимодействовать с systemd, контролировать состояние системы и отдельных компонентов.
Первая из них — systemctl. При запуске без параметров, выводится список всех unit-файлов, известных системе (за исключением отключенных) и их статус. systemctl status дает лучший обзор сервисов и связанных процессов. Выводится имя файла service (как в systemctl status ntp.service), также дополнительная информация и последние несколько строчек из журнала, касающиеся этого процесса (позднее про это будет сказано более подробно).
Для запуска сервиса вручную, нужно просто набрать systemctl start servicename.service. Как можно догадаться, для остановки: systemctl stop servicename.service. Есть другие подкоманды: reload и restart.
Для контроля за активность сервиса (запускается при загрузки системы или нет), нужно использовать systemctl enable servicename.service (или disable). Для проверки запущен ли сервис — is-enabled.
Интересная особенность systemd состоит в журнале journald. Он идет как дополнение к традиционному syslogd, но содержит особенности, как например формальная ссылка между сервисом и сообщениям, им создаваемыми при процедуре инициализации и способность захватывать сообщения об ошибках, генерируемые последовательностью инициализации. Сообщения можно посмотреть с помощью команды journalctl. Без каких-либо аргументов он просто выводит все сообщения журнала, произошедшие с момента загрузки системы; он редко будет использоваться таким образом. Большую часть времени он будет использоваться с идентификатором сервиса:
# journalctl -u ssh.service
-- Logs begin at Tue 2015-03-31 10:08:49 CEST, end at Tue 2015-03-31 17:06:02 CEST. --
Mar 31 10:08:55 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.
Mar 31 10:08:55 mirtuel sshd[430]: Server listening on :: port 22.
Mar 31 10:09:00 mirtuel sshd[430]: Received SIGHUP; restarting.
Mar 31 10:09:00 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.
Mar 31 10:09:00 mirtuel sshd[430]: Server listening on :: port 22.
Mar 31 10:09:32 mirtuel sshd[1151]: Accepted password for roland from 192.168.1.129 port 53394 ssh2
Mar 31 10:09:32 mirtuel sshd[1151]: pam_unix(sshd:session): session opened for user roland by (uid=0)
Другой полезный флаг -f используется с journalctl для просмотра появления новых сообщений (похоже на tail -f file).
Если сервис не работает как ожидалось, то первым делом нужно проверить его статус с systemctl status, если проблема не решена, то проверьте его журнал. Допустим сервер SSH не работает:
# systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
   Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
   Active: failed (Result: start-limit) since Tue 2015-03-31 17:30:36 CEST; 1s ago
  Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
  Process: 1188 ExecStart=/usr/sbin/sshd -D $SSHD_OPTS (code=exited, status=255)
 Main PID: 1188 (code=exited, status=255)

Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
# journalctl -u ssh.service
-- Logs begin at Tue 2015-03-31 17:29:27 CEST, end at Tue 2015-03-31 17:30:36 CEST. --
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Received SIGHUP; restarting.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:30:10 mirtuel sshd[1147]: Accepted password for roland from 192.168.1.129 port 38742 ssh2
Mar 31 17:30:10 mirtuel sshd[1147]: pam_unix(sshd:session): session opened for user roland by (uid=0)
Mar 31 17:30:35 mirtuel sshd[1180]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1182]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1184]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1186]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1188]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
# vi /etc/ssh/sshd_config
# systemctl start ssh.service
# systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
   Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
   Active: active (running) since Tue 2015-03-31 17:31:09 CEST; 2s ago
  Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
 Main PID: 1222 (sshd)
   CGroup: /system.slice/ssh.service
           └─1222 /usr/sbin/sshd -D
# 
После проверки статуса (ошибка), был проверен журнал, была обнаружена ошибка в конфигурационном файле. После его редактирования и исправления ошибки, сервис запускается заново, далее проверяется его статус.

9.1.2. Система инициализации System V

Система инициализации System V (которую для краткости мы будем называть init) выполняет несколько процессов, следуя инструкциям из файла /etc/inittab. Первая программа, которая выполняется (что соответствует шагу sysinit) это /etc/init.d/rcS скрипт, который выполняет все программы в каталоге /etc/rcS.d/.
Среди них можно найти последовательность программ, отвечающих за:
  • настройку клавиатуры в консоли;
  • загрузку драйверов: большая часть модулей ядра загружается самим ядром при обнаружении оборудования; дополнительные драйверы затем загружаются автоматически, если соответствующие модули указаны в /etc/modules;
  • проверку целостности файловых систем;
  • монтирование локальных разделов;
  • настройку сети;
  • монтирование сетевых файловых систем (NFS).
Следом, init запускает программы уровня запуска по умолчанию (обычно runlevel 2). Запускается сценарий /etc/init.d/rc 2, который, в свою очередь, запускает сервисы, перечисленные в /etc/rc2.d/. Названия файлов в каталоге начинаются с буквы «S», за которой идут две цифры, что определяет очерёдность запуска. В настоящее время, загрузочная система по умолчанию использует программу insserv, которая автоматически всё организовывает, основываясь на зависимостях сценариев. Каждый сценарий объявляет условия, необходимые для его запуска и остановки (например, очерёдность по отношению к другим сценариям), init запускает сценарии в соответствующей последовательности для удовлетворения зависимостей. Поэтому наименование сценариев больше не учитывается (хотя они всё еще должны начинаться с «S» и далее продолжаться двумя цифрами и названием сервиса, которое и используется для организации зависимостей). В общем, основные сервисы (как журналирование с rsyslog или назначение портов с portmap) запускаются в первую очередь, затем следуют стандартные сервисы и графический интерфейс (gdm3).
Такая основанная на зависимостях система загрузки делает возможной автоматизацию смены нумерации, которая была бы весьма утомительной, если бы её приходилось выполнять вручную, и снижает риск человеческой ошибки, поскольку планирование выполняется в соответствии с формальными параметрами. Другим преимуществом является возможность параллельного запуска сервисов, независимых друг от друга, что может ускорить процесс загрузки.
init различает несколько уровней запуска, так что она может переключаться с одного на другой при посредстве команды telinit new-level. init сразу же запускает /etc/init.d/rc заново с новым уровнем запуска. Этот сценарий после этого запускает недостающие сервисы и останавливает те, которые более не нужны. Для этого он руководствуется содержимым /etc/rcX.d (где X означает новый уровень запуска). Сценарии, начинающиеся с «S» (как в слове «Start») — это сервисы, которые должны быть запущены; те, что начинаются с «K» (как в слове «Kill») — сервисы, которые должны быть остановлены. Сценарий не запускает никаких сервисов, которые уже были активированы на прежнем уровне запуска.
По умолчанию, System V init Debian использует четыре разных уровня запуска:
  • Уровень 0 используется только временно, при выключении питания компьютера. Поэтому он содержит только «K»-сценарии.
  • Уровень 1, также известный как однопользовательский режим, соответствует системе с урезанной функциональностью; он включает только основные сервисы и предназначается для операций по обслуживанию, когда взаимодействие с обычными пользователями нежелательно.
  • Уровень 2 — уровень для нормальной работы, включающий сетевые сервисы, графический интерфейс, вход пользователей и т. п.
  • Уровень 6 похож на уровень 0 с той разницей, что он используется во время остановки системы перед перезагрузкой.
Есть и другие уровни, в частности с 3 по 5. По умолчанию они настроены, чтобы работать точно так же, как уровень 2, но администратор может изменить их (путём добавления или удаления сценариев в соответствующие каталоги /etc/rcX.d), чтобы приспособить их под свои специфические нужды.
Последовательность загрузки компьютера с Linux и System V init

Рисунок 9.2. Последовательность загрузки компьютера с Linux и System V init

Все сценарии, содержащиеся в различных каталогах /etc/rcX.d на самом деле являются лишь символьными ссылками — созданными при установке пакета программой update-rc.d — указывающими на сами сценарии, хранящиеся в /etc/init.d/. Администратор может настроить доступность сервисов на каждом уровне запуска путём повторного запуска update-rc.d с изменёнными параметрами. На странице руководства update-rc.d(8) подробно описан синтаксис. Обратите внимание, что удаление всех символьных ссылок (с помощью параметра remove) — не лучший метод отключения сервиса. Вместо этого следует просто настроить, чтобы он не запускался на нужном уровне запуска (сохранив соответствующие вызовы для остановки его в случае, если сервис работал на предыдущем уровне запуска). Поскольку интерфейс update-rc.d несколько запутанный, может оказаться более удобным использовать rcconf (из пакета rcconf), интерфейс которой более дружествен к пользователю.
Наконец, init запускает программу управления виртуальными консолями (getty). Она выводит приглашение, ожидает ввода имени пользователя, а затем выполняет login пользователь, чтобы начать сессию.