Погодин Евгений — ИТ Заметки
🐧Linux Обновлено 28.10.2026

Linux для админа Windows 06. Службы и процессы: systemd, journalctl, cron

Note

Материал сверен с официальной документацией (Ubuntu Server, man-страницы и документация проектов; ссылки — в конце статьи). Примеры вывода — иллюстрации: на вашем сервере значения и формат могут отличаться. Перед работой на боевом сервере проверьте команды на тестовой машине.

Сервер полезен тем, что на нём что-то работает: веб-сервер, база, скрипт резервного копирования. В Windows за это отвечают Диспетчер задач, оснастка «Службы», Просмотр событий и Планировщик заданий. В Ubuntu те же задачи решаются другими инструментами, и в этой статье вы научитесь:

  • смотреть процессы и завершать их, не навредив системе (ps, top, kill);
  • управлять службами через systemctl и написать собственную службу;
  • читать журналы через journalctl и понимать, что лежит в /var/log;
  • запускать задания по расписанию в cron и в таймерах systemd.
Windows Linux
Диспетчер задач, Get-Process ps, top
taskkill, Stop-Process kill, pkill
Оснастка «Службы», Get-Service, Set-Service systemctl
Тип запуска «Автоматически» systemctl enable
Просмотр событий, Get-WinEvent journalctl, файлы в /var/log
Планировщик заданий, schtasks cron, таймеры systemd

Что нужно знать заранее

Процессы

PID, родитель и дерево

Процесс — запущенная программа. У каждого есть номер PID, номер родителя PPID, владелец и состояние. Процессы образуют дерево: первый процесс системы с PID 1 — это systemd, он запускает остальные.

ps: снимок процессов

ps -ef
ps aux
ps -eo pid,ppid,user,%cpu,%mem,etime,args --sort=-%cpu | head

ps -ef — стиль UNIX, ps aux (без дефиса) — стиль BSD; список процессов у них один, различается набор колонок. Последняя команда сама выбирает колонки и сортирует по загрузке процессора. Пример вывода (значения вымышленные):

  PID  PPID USER      %CPU %MEM     ELAPSED COMMAND
 1432     1 www-data   4.2  1.8  3-02:41:19 /usr/bin/example-app --serve
  907     1 root       0.1  0.2  3-02:41:30 /usr/sbin/cron -f
 2210  2198 admin-lab  0.0  0.1       00:00 ps -eo pid,ppid,user,%cpu,%mem

ELAPSED — время с запуска в формате [[ДД-]чч:]мм:сс. В колонке STAT (её показывает ps aux) первая буква — состояние: R работает, S спит в ожидании события, D ждёт ввода-вывода и не прерывается, T остановлен, Z — «зомби». Зомби (<defunct>) — уже завершившийся процесс, результат которого родитель ещё не забрал; kill на него не действует, он исчезнет, когда родитель заберёт результат или сам завершится.

top: живой монитор

top обновляет картину каждые несколько секунд. Первые строки — сводка (пример, значения вымышленные):

top - 14:02:11 up 12 days,  3:41,  1 user,  load average: 0.15, 0.22, 0.19
Tasks: 112 total,   1 running, 111 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.3 us,  0.7 sy,  0.0 ni, 97.7 id,  0.2 wa,  0.0 hi,  0.1 si,  0.0 st

В первой строке: время работы и три значения средней загрузки за 1, 5 и 15 минут. Во второй — число процессов по состояниям. В третьей — доли процессора: us — программы пользователей, sy — ядро, id — простой, wa — ожидание диска, st — время, «украденное» гипервизором.

Внутри top: q — выход, h — справка со всеми клавишами, P и M — сортировка по процессору и по памяти, k — отправить сигнал процессу (по умолчанию SIGTERM). Более удобный htop входит в стандартную установку Ubuntu Server; если его нет (например, в минимальной установке), поставьте его командой sudo apt install htop.

Сигналы: просьба и принуждение

Завершают процесс отправкой сигнала. Главные:

Сигнал № Смысл
SIGTERM 15 «пожалуйста, завершись»; процесс успевает сохранить данные. Сигнал по умолчанию у kill
SIGKILL 9 немедленное завершение; процесс не может его перехватить или игнорировать
SIGINT 2 то, что посылает Ctrl+C
SIGHUP 1 «обрыв терминала»; по традиции служба перечитывает по нему настройки

Приблизительное соответствие в Windows: taskkill /F — это SIGKILL, а вежливая остановка (SIGTERM) ближе к кнопке «Остановить» в оснастке «Службы».

# 1432 - PID из примера выше; подставьте свой
kill 1432
kill -9 1432
pgrep -a example-app
pkill -x example-app

pgrep -a показывает процессы по имени с полной командной строкой, pkill -x отправляет сигнал всем процессам с точно таким именем (killall из пакета psmisc делает то же). Сначала посмотрите pgrep: под шаблон может попасть лишнее.

Warning

Начинайте с kill без -9 и дайте процессу несколько секунд. SIGKILL не даёт программе ни закрыть файлы, ни дописать данные на диск. Если процесс — служба systemd, завершайте её через systemctl stop: убитую сигналом службу systemd может перезапустить сам, в зависимости от настройки Restart= (см. ниже).

Приоритет процесса задаёт значение nice от -20 (самый важный) до 19 (самый уступчивый). nice -n 10 команда запускает команду с пониженным приоритетом, renice меняет приоритет запущенного процесса; повышать приоритет может только root.

systemd: службы

Юниты и цели

systemd — первый процесс системы и менеджер служб. Он описывает всё, чем управляет, в виде юнитов (units): .service — служба, .timer — таймер, .socket, .mount и другие типы. Цель (.target) — группа юнитов и точка синхронизации при загрузке, замена старых уровней запуска. multi-user.target — обычный многопользовательский режим без графики.

Файлы юнитов, установленные пакетами, лежат в /usr/lib/systemd/system, ваши собственные — в /etc/systemd/system. Если файл с одним именем есть в обоих местах, побеждает /etc.

systemctl

Расширение .service можно не писать. Команды изменения состояния выполняются с sudo:

Задача Команда
Состояние службы и последние строки журнала systemctl status имя
Запустить / остановить sudo systemctl start имя, sudo systemctl stop имя
Перезапустить (остановить и запустить) sudo systemctl restart имя
Перечитать настройки службы без остановки sudo systemctl reload имя
Включить автозапуск при загрузке sudo systemctl enable имя
Включить и сразу запустить sudo systemctl enable --now имя
Выключить автозапуск sudo systemctl disable имя
Запущена ли / включена ли systemctl is-active имя, systemctl is-enabled имя
Список упавших служб systemctl --failed

enable и start — разные действия: первое только настраивает автозапуск (создаёт ссылки по указанию раздела [Install]), второе запускает прямо сейчас. Это то же различие, что между «Тип запуска» и кнопкой «Запустить» в оснастке «Службы». reload перечитывает конфигурацию самой программы (например, настройки веб-сервера) и не затрагивает файл юнита.

Warning

Не останавливайте и не отключайте службы ssh и сетевые службы, пока подключены удалённо: вернуться можно будет только через консоль сервера. Перед остановкой любой службы убедитесь, что от неё ничто не зависит.

Пример вывода systemctl status для службы из этой статьи:

● demo.service - Demo worker
     Loaded: loaded (/etc/systemd/system/demo.service; enabled; preset: enabled)
     Active: active (running) since Wed 2026-10-28 14:02:11 UTC; 20s ago
   Main PID: 2301 (worker.sh)
      Tasks: 2 (limit: 4557)
     Memory: 1.1M
        CPU: 12ms
     CGroup: /system.slice/demo.service
             ├─2301 /bin/bash /opt/demo/worker.sh
             └─2318 sleep 30

Oct 28 14:02:11 lnx1 systemd[1]: Started demo.service - Demo worker.
Oct 28 14:02:11 lnx1 worker.sh[2301]: heartbeat 14:02:11

Что здесь важно: цвет точки слева (зелёная — активна, красный крестик — сбой); Loaded — откуда прочитан юнит и включён ли автозапуск; Active — состояние: active (running), inactive (dead) или failed; CGroup — группа процессов, которую systemd создаёт для службы и по которой отслеживает все её процессы; в конце — последние строки журнала этой службы. Если служба упала, начните с systemctl status имя, затем откройте журнал.

Своя служба: пример

Сделаем службу, которая раз в 30 секунд пишет строку в журнал. Сначала скрипт и системная учётная запись без входа (подробнее о пользователях — в статье про права доступа):

sudo useradd --system --no-create-home --shell /usr/sbin/nologin demo
sudo mkdir -p /opt/demo
sudo tee /opt/demo/worker.sh > /dev/null <<'EOF'
#!/bin/bash
while true; do
  echo "heartbeat $(date +%T)"
  sleep 30
done
EOF
sudo chmod 755 /opt/demo/worker.sh

Конструкция <<'EOF' передаёт tee все строки до слова EOF как есть. То же можно сделать проще: откройте файл командой sudo nano /opt/demo/worker.sh и вставьте строки скрипта.

Затем файл /etc/systemd/system/demo.service (создайте его через sudo nano):

[Unit]
Description=Demo worker

[Service]
Type=exec
User=demo
ExecStart=/opt/demo/worker.sh
Restart=on-failure
RestartSec=5
NoNewPrivileges=yes
PrivateTmp=yes

[Install]
WantedBy=multi-user.target

В файле три раздела:

  • [Unit] — описание и порядок. Description — короткое название без точки в конце (systemd показывает его в сообщениях); After= и Before= задают порядок запуска, а Wants= и Requires= — зависимости от других юнитов.
  • [Service] — как запускать (директивы разобраны ниже).
  • [Install] — что делает enable: WantedBy=multi-user.target включает службу в обычную загрузку.
Директива Что делает
Type=exec считает службу запущенной, когда бинарный файл действительно выполнен: systemctl start сообщит об ошибке, если файла нет или пользователя demo не существует. При Type=simple (значение по умолчанию) start в этих случаях сообщит об успехе
User= от чьего имени работать (по умолчанию root)
ExecStart= команда запуска, с абсолютным путём
Restart=on-failure перезапуск при ненулевом коде завершения, аварийной гибели от сигнала или тайм-ауте; по документации, рекомендуемый вариант для долгоживущих служб
RestartSec= пауза перед перезапуском (по умолчанию 100 мс)
NoNewPrivileges=yes, PrivateTmp=yes запрет получать новые привилегии; собственный /tmp у процесса

Всё, что служба пишет в стандартный вывод, попадает в журнал: так systemd настроен по умолчанию. Проверим файл и запустим службу:

sudo systemd-analyze verify /etc/systemd/system/demo.service
sudo systemctl daemon-reload
sudo systemctl enable --now demo
systemctl status demo

daemon-reload заставляет systemd заново прочитать файлы юнитов; выполняйте его после ручного создания или правки файла. Не путайте его с reload. systemd-analyze verify ловит опечатки в директивах и отсутствующие команды. Чтобы увидеть работу Restart=, завершите главный процесс принудительно и через пять секунд снова посмотрите статус. Эта команда посылает сигнал только главному процессу службы:

sudo systemctl kill --signal=SIGKILL --kill-whom=main demo
systemctl status demo

Правка чужих служб: drop-in

Файлы в /usr/lib/systemd/system принадлежат пакетам, и править их напрямую не стоит. Для своих изменений есть drop-in (файл-дополнение к юниту): sudo systemctl edit имя откроет редактор, а результат сохранится в /etc/systemd/system/имя.service.d/override.conf. Достаточно указать только изменяемые директивы:

[Service]
RestartSec=10

После сохранения systemd перечитает настройки сам. systemctl cat имя покажет исходный файл вместе со всеми drop-in. Для таймеров работает так же: Ubuntu описывает правку apt-daily.timer именно этим способом.

Журналы

journalctl

journald собирает сообщения служб (всё, что они пишут в стандартный вывод и ошибки), ядра и системы в двоичный журнал, который читается командой journalctl. Это аналог Просмотра событий. Пользователь вне групп adm и systemd-journal видит только свой журнал, а чтобы читать системный, нужны sudo или членство в одной из этих групп (проверьте командой id).

sudo journalctl -u demo -n 50 --no-pager
sudo journalctl -u demo -f
sudo journalctl -b
sudo journalctl -b -1
sudo journalctl --since "1 hour ago" -p err
sudo journalctl --since "2026-10-28 03:00" --until "2026-10-28 04:00"
sudo journalctl -k
sudo journalctl -g "timeout"
  • -u имя — сообщения одной службы; -n 50 — последние 50 записей; -f — следить за новыми (Ctrl+C — выход);
  • -b — текущая загрузка, -b -1 — предыдущая; --list-boots покажет все;
  • --since и --until принимают дату и время, слова yesterday, today и относительные значения вроде "1 hour ago" или -1h;
  • -p err — только ошибки и более важные записи (уровни от emerg до debug);
  • -k — только сообщения ядра, -g — поиск по тексту, -x — добавляет пояснения к известным сообщениям.

Пример вывода:

Oct 28 14:02:11 lnx1 systemd[1]: Started demo.service - Demo worker.
Oct 28 14:02:11 lnx1 worker.sh[2301]: heartbeat 14:02:11
Oct 28 14:02:41 lnx1 worker.sh[2301]: heartbeat 14:02:41

Когда закончите опыты со службой и журналом, уберите её: sudo systemctl disable --now demo, затем sudo rm /etc/systemd/system/demo.service, sudo systemctl daemon-reload, sudo userdel demo и sudo rm -r /opt/demo.

Постоянное хранение и размер

В 24.04 по умолчанию действует Storage=auto: журнал пишется на диск, если существует каталог /var/log/journal. На новой установке Ubuntu его создаёт установочный скрипт пакета systemd, поэтому журнал обычно сохраняется между перезагрузками. В образе или контейнере каталога может не быть, и тогда журнал хранится в памяти (/run/log/journal) и пропадает после перезагрузки. Проверьте: ls -d /var/log/journal и (после хотя бы одной перезагрузки) journalctl --list-boots. В документации systemd 259 (26.04) по умолчанию указано persistent. Включить хранение явно можно файлом /etc/systemd/journald.conf.d/50-persistent.conf:

[Journal]
Storage=persistent

Каталог journald.conf.d создайте командой sudo mkdir -p /etc/systemd/journald.conf.d, а после правки перезапустите службу: sudo systemctl restart systemd-journald. Размер ограничивает SystemMaxUse=: по умолчанию журнал занимает не более 10% файловой системы, но не больше 4 ГБ. Сколько он занимает сейчас, покажет journalctl --disk-usage; освободить место можно командой sudo journalctl --vacuum-size=500M (или --vacuum-time=2weeks).

Warning

--vacuum-* безвозвратно удаляет старые архивы журнала. Не очищайте журнал, пока расследуете инцидент: именно старые записи часто нужны.

/var/log и logrotate

Классические текстовые журналы лежат в /var/log: syslog — общий, auth.log — входы и sudo, kern.log — ядро; у программ есть свои файлы и подкаталоги (например, у nginx, см. статью про веб-сервер). Читать их можно привычными less, tail -f и grep. Это аналог журналов «Система» и «Безопасность» в Просмотре событий. Если какого-то из этих файлов нет, значит, служба rsyslog, которая их пишет, не установлена: те же сообщения доступны через journalctl.

Чтобы файлы не росли бесконечно, их ротирует logrotate: обычно раз в сутки он переименовывает, сжимает и удаляет старые копии по правилам из /etc/logrotate.conf и подключаемых из него файлов. Проверить правила, ничего не меняя, можно командой sudo logrotate -d /etc/logrotate.conf.

Расписания

cron

cron — демон, который раз в минуту проверяет таблицы заданий и запускает то, что подошло по времени. У каждого пользователя своя таблица (crontab), задания выполняются от его имени. В Ubuntu Server это пакет cron (классический Vixie cron с дополнениями Debian); cronie и systemd-cron из universe ставятся вместо него. Если страница crontab(5) на сайте manpages.ubuntu.com описывает другой демон, ориентируйтесь на man 5 crontab на самом сервере.

crontab -e
crontab -l
sudo crontab -e

crontab -e открывает вашу таблицу в редакторе, -l показывает, sudo crontab -e правит таблицу root. Опция -r удаляет всю таблицу без вопросов (-ri спросит подтверждение). Системные задания лежат в /etc/crontab и /etc/cron.d/ (там перед командой указывают ещё и пользователя), а скрипты из /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly и /etc/cron.monthly запускаются автоматически. Их запускает run-parts: файл должен быть исполняемым (chmod +x), принадлежать root и не быть доступным на запись группе и остальным, а имя может состоять только из латинских букв, цифр, _ и -. Файл backup.sh (с точкой) молча пропускается; назовите его backup.

Строка задания состоит из пяти полей времени и команды:

Поле Значения
минута 0–59
час 0–23
день месяца 1–31
месяц 1–12 или имя (jan)
день недели 0–7 (0 и 7 — воскресенье) или имя (mon)

(В man-странице crontab(5) для 24.04 диапазоны указаны как 0–31 и 0–12: это неточность описания, нижняя граница равна 1.)

В поле допустимы * (любое значение), список через запятую, диапазон 1-5 и шаг */15. Примеры:

# m h dom mon dow  command
30 3 * * *     /usr/local/bin/backup.sh
*/15 * * * *   /usr/local/bin/check.sh
0 22 * * 1-5   /usr/local/bin/weekday-job.sh
5 4 * * sun    /usr/local/bin/weekly.sh

Эти четыре задания запускаются в 03:30 каждый день, каждые 15 минут, в 22:00 по будням и в 04:05 по воскресеньям. Если ограничены и день месяца, и день недели, задание сработает при совпадении любого из них, а не обоих.

Ловушки cron, из-за которых «руками работает, а по расписанию нет»:

  • Скудное окружение. cron автоматически задаёт SHELL (это /bin/sh), LOGNAME и HOME. PATH в Ubuntu наследуется от самого демона, но настроек вашего профиля (~/.profile, ~/.bashrc) там нет. Используйте полные пути к командам, а при необходимости задайте PATH= строкой в самой таблице.
  • Символ %. В команде он означает перевод строки; пишите \%: tar czf /backup/etc-$(date +\%F).tgz /etc (tar czf упаковывает каталог в архив .tgz, date +%F выдаёт дату вида 2026-10-28).
  • Куда уходит вывод. Всё, что команда напечатала, cron пытается отправить владельцу таблицы письмом (адрес можно задать MAILTO=, пустое значение отключает письма). Без почтового клиента вывод может пропасть, поэтому перенаправляйте его в файл: команда >> /var/log/my-job.log 2>&1.
  • Комментарии допустимы только на отдельных строках: после команды # станет частью команды.

Сообщения о запусках cron пишет в системный журнал: ищите их командой grep CRON /var/log/syslog или journalctl -u cron. Для разового отложенного запуска есть команда at (пакет at из universe по умолчанию не установлен: sudo apt install at): at 02:00, дальше команды и Ctrl+D; очередь — atq.

Таймеры systemd

Таймер — это пара юнитов: файл .timer определяет когда, одноимённый .service — что. Сделаем ежедневный отчёт о диске. Служба /etc/systemd/system/disk-report.service:

[Unit]
Description=Disk usage report

[Service]
Type=oneshot
ExecStart=/usr/bin/df -h /

Таймер /etc/systemd/system/disk-report.timer:

[Unit]
Description=Daily disk usage report

[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
RandomizedDelaySec=5min

[Install]
WantedBy=timers.target

Type=oneshot означает «выполнить и завершиться»; путь /usr/bin/df подтвердите командой command -v df.

В [Timer]: OnCalendar= — календарное выражение (*-*-* 03:30:00 — каждый день в 03:30), Persistent=true — если сервер был выключен в это время, догнать пропущенный запуск при включении, RandomizedDelaySec= — случайная задержка, чтобы много серверов не стартовали одновременно. По умолчанию таймер может сработать с опозданием до минуты (AccuracySec=). WantedBy=timers.target подключает таймер к загрузке.

Выражение удобно проверять заранее: systemd-analyze calendar '*-*-* 03:30:00' печатает его нормальную форму и ближайший запуск (пример вывода):

  Original form: *-*-* 03:30:00
Normalized form: *-*-* 03:30:00
    Next elapse: Thu 2026-10-29 03:30:00 UTC
       From now: 13h left

Другие формы: daily, weekly (понедельник 00:00), Mon..Fri 08:00, *:0/15 (каждые 15 минут). Таймеры от момента загрузки задают OnBootSec=5min, от последнего запуска службы — OnUnitActiveSec=1h.

sudo systemctl daemon-reload
sudo systemctl enable --now disk-report.timer
systemctl list-timers
sudo systemctl start disk-report.service
sudo journalctl -u disk-report.service

systemctl list-timers показывает для каждого таймера колонки NEXT, LEFT, LAST, PASSED, UNIT и ACTIVATES. Запустить службу вручную можно командой start, а результат смотреть в журнале: вывод df окажется там.

Уберите учебные таймер и службу, чтобы сервер не запускал их каждую ночь: sudo systemctl disable --now disk-report.timer, затем sudo rm /etc/systemd/system/disk-report.service /etc/systemd/system/disk-report.timer и sudo systemctl daemon-reload.

cron или таймер

cron Таймер systemd
Расписание пять полей OnCalendar=, а также от загрузки и от прошлого запуска
Где логи syslog и письма журнал: journalctl -u имя
Выключенный в нужное время сервер запуск не наверстывается Persistent=true догонит
Окружение скудное, настраивается вручную как у службы: User=, Environment= и другие параметры
Сложность одна строка два файла

Пропущенные запуски заданий из crontab cron не наверстывает; для /etc/cron.daily и соседних каталогов это делает пакет anacron, но на Ubuntu Server его по умолчанию нет.

Для простого «запускать скрипт раз в ночь» хватает cron. Если нужны журнал запусков, зависимости от других служб или догон пропущенных запусков, берите таймер. Планировщику заданий Windows соответствуют оба инструмента.

Типичные ошибки и недоразумения

  • kill -9 по привычке. Сначала kill, и только потом -9: SIGKILL не даёт процессу корректно завершиться.
  • Убили процесс службы, а он вернулся. Это работает Restart=. Службу останавливают командой systemctl stop.
  • Правка файла юнита без daemon-reload. Изменения не подхватываются, пока systemd не перечитает файлы. Через systemctl edit перечитывание происходит само.
  • enable принимают за запуск. enable только настраивает автозапуск; запускает start (или enable --now).
  • Путаница reload, restart и daemon-reload. Первое перечитывает настройки программы, второе перезапускает её, третье перечитывает файлы юнитов systemd.
  • Служба «стартует успешно» и сразу падает. При Type=simple неверный путь или несуществующий пользователь не дают ошибки на start; смотрите systemctl status и journalctl -u.
  • Задание cron не работает. Проверьте полные пути, символы %, перенаправление вывода и записи в grep CRON /var/log/syslog.
  • crontab -r вместо crontab -e. Одна буква стирает всю таблицу без подтверждения; для страховки используйте crontab -ri и храните таблицы в резервной копии.
  • Журнал «пропал» после перезагрузки. В образе или контейнере без каталога /var/log/journal (режим Storage=auto) журнал хранится в памяти.
  • Чтение журнала без sudo. Пользователь вне групп adm и systemd-journal видит только свои записи и думает, что служба молчит.

Проверьте себя

  1. Вы завершили процесс службы командой kill -9, но через несколько секунд он снова работает. Почему и как остановить службу насовсем? Службу перезапускает systemd по настройке Restart=. Останавливать её нужно командой sudo systemctl stop имя, а не сигналом; SIGKILL (9) к тому же не даёт процессу корректно завершиться.
  2. Вы создали файл /etc/systemd/system/demo.service. Что нужно выполнить, чтобы служба запустилась и стартовала при загрузке? sudo systemctl daemon-reload, затем sudo systemctl enable --now demo: первое перечитывает юниты, второе включает автозапуск и запускает службу.
  3. Как посмотреть ошибки службы demo за последний час? sudo journalctl -u demo --since "1 hour ago" -p err.
  4. Что означает запись */15 * * * * в crontab и куда по умолчанию уходит вывод задания? Запуск каждые 15 минут. Вывод cron пытается отправить владельцу таблицы письмом, поэтому его лучше перенаправить в файл.
  5. Какое преимущество у таймера systemd перед cron, если сервер ночью бывает выключен? Persistent=true запустит пропущенное задание при включении; cron пропущенные запуски не наверстывает.

Что дальше

Источники

Ещё по теме «Linux»