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.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 получает контроль над компьютером, определяет диски, считывает главную загрузочную запись и запускает загрузчик. Загрузчик принимает управление, находит ядро на диске, считывает и запускает его. Затем ядро инициализируется и начинает поиск и монтирование корневой файловой системы и, наконец, запускает первую программу — init. Зачастую эти «корневой раздел» и init на самом деле находятся на виртуальной файловой системе, существующей только в ОЗУ (отсюда её название — initramfs, ранее — initrd, от "initialization RAM disk"). Эта файловая система загружается в память загрузчиком, часто из файла на жёстком диске или по сети. Он содержит самый минимум, необходимый для того, чтобы ядро загрузило «настоящую» корневую файловую систему: сюда могут входить модуля ядра для жёсткого диска или других устройств, без которых система не способна загрузиться, или, чаще, сценарии инициализации и модули для сборки массивов RAID, открытия зашифрованных разделов, активации томов LVM и т. п. Когда корневой раздел примонтирован, initramfs передаёт управление настоящему процессу "init", и система возвращается к стандартному процессу загрузки.
Порядок загрузки компьютера с Linux и systemd

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

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

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

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target
Alias=sshd.service
Как видно из примера, кода очень мало, только объявления. Также systemd описывает ход процесса, отслеживает их выполнение и даже перезапускает, если необходимо.
Файл «цели» в systemd описывает состояние системы, когда функционирует некоторый набор сервисов. Его можно рассматривать как эквивалент уровня запуска. Одна из целей — local-fs.target; при её достижении остальная система может рассчитывать, что все локальные файловые системы смонтированы и доступны. В число других целей входят network-online.target и sound.target. Зависимости цели могут быть указаны как внутри файла target (в строке 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, запускает несколько процессов. Первая команда (относящаяся к шагу sysvinit) — это сценарий /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 новый-уровень. 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 пользователь, чтобы начать сессию.