Процеси та systemd¶
Процеси в Linux¶
Що таке процес?¶
Процес — це запущена програма з власним адресним простором, ресурсами та станом.
┌─────────────────────────────────────────────────────────────────┐
│ Ієрархія процесів │
│ │
│ systemd (PID 1) │
│ ├── sshd │
│ │ └── sshd (session) │
│ │ └── bash │
│ │ └── vim │
│ ├── nginx │
│ │ ├── nginx (worker) │
│ │ └── nginx (worker) │
│ └── dockerd │
│ └── containerd │
│ │
│ Кожен процес має: │
│ • PID (Process ID) │
│ • PPID (Parent Process ID) │
│ • UID/GID (User/Group) │
│ • Стан (Running, Sleeping, Zombie...) │
│ • Пріоритет (nice value) │
└─────────────────────────────────────────────────────────────────┘
Стани процесів¶
┌─────────────────────────────────────────────────────────────────┐
│ R (Running) — виконується на CPU │
│ S (Sleeping) — чекає на I/O або подію │
│ D (Disk sleep) — неперервний сон (I/O) │
│ Z (Zombie) — завершений, чекає на батька │
│ T (Stopped) — зупинений (Ctrl+Z або SIGSTOP) │
│ I (Idle) — kernel thread │
└─────────────────────────────────────────────────────────────────┘
Перегляд процесів¶
# Базовий список
ps aux
# a = всіх користувачів
# u = user-oriented format
# x = процеси без терміналу
# Ієрархія (дерево)
ps auxf
pstree
pstree -p # з PID
# Конкретний процес
ps aux | grep nginx
pgrep nginx
pgrep -l nginx # з іменами
# Детальна інформація
ps -p 1234 -o pid,ppid,cmd,stat,%cpu,%mem
# top / htop
top
htop # інтерактивний, рекомендовано
htop shortcuts¶
┌─────────────────────────────────────────────────────────────────┐
│ F1 - Help │
│ F2 - Setup │
│ F3 - Search │
│ F4 - Filter │
│ F5 - Tree view │
│ F6 - Sort by │
│ F7 - Nice - (зменшити пріоритет) │
│ F8 - Nice + (збільшити пріоритет) │
│ F9 - Kill │
│ F10 - Quit │
│ │
│ Space - Tag process │
│ U - Untag all │
│ k - Kill selected │
│ t - Tree view toggle │
└─────────────────────────────────────────────────────────────────┘
Сигнали¶
Основні сигнали¶
| Сигнал | Номер | Опис | Можна перехопити? |
|---|---|---|---|
| SIGHUP | 1 | Hangup (reload config) | Так |
| SIGINT | 2 | Interrupt (Ctrl+C) | Так |
| SIGQUIT | 3 | Quit (Ctrl+\) | Так |
| SIGKILL | 9 | Kill (примусово) | НІ |
| SIGTERM | 15 | Terminate (graceful) | Так |
| SIGSTOP | 19 | Stop (Ctrl+Z) | НІ |
| SIGCONT | 18 | Continue | Так |
| SIGUSR1 | 10 | User defined 1 | Так |
| SIGUSR2 | 12 | User defined 2 | Так |
Надсилання сигналів¶
# kill — не тільки для "вбивання"
kill PID # SIGTERM (15) — graceful
kill -9 PID # SIGKILL — force
kill -15 PID # SIGTERM
kill -HUP PID # SIGHUP — reload
kill -STOP PID # SIGSTOP — pause
kill -CONT PID # SIGCONT — resume
# killall — за іменем
killall nginx
killall -9 nginx
# pkill — за паттерном
pkill nginx
pkill -f "python script.py" # по командному рядку
pkill -u username # всі процеси користувача
# Список сигналів
kill -l
SIGTERM vs SIGKILL¶
┌─────────────────────────────────────────────────────────────────┐
│ SIGTERM (15) — рекомендований спосіб │
│ • Процес може перехопити сигнал │
│ • Зберегти дані │
│ • Закрити з'єднання │
│ • Завершитися коректно │
│ │
│ SIGKILL (9) — крайній захід │
│ • Ядро миттєво завершує процес │
│ • Процес НЕ МОЖЕ перехопити │
│ • Можлива втрата даних │
│ • Ресурси можуть не звільнитися │
│ │
│ Правильний порядок: │
│ 1. kill PID (SIGTERM) │
│ 2. Почекати кілька секунд │
│ 3. Якщо не завершився: kill -9 PID │
└─────────────────────────────────────────────────────────────────┘
Nice та пріоритети¶
# nice value: -20 (highest priority) to +19 (lowest)
# Тільки root може встановлювати негативні значення
# Запустити з низьким пріоритетом
nice -n 10 ./heavy_script.sh
# Змінити пріоритет запущеного процесу
renice -n 5 -p 1234
renice -n 10 -u username # всі процеси користувача
# Переглянути nice value
ps -o pid,ni,cmd -p 1234
Фонові процеси та jobs¶
# Запустити у фоні
./script.sh &
# Перенести в фон (Ctrl+Z, потім bg)
./script.sh
# Ctrl+Z
bg
# Переглянути jobs
jobs
# Повернути на передній план
fg %1
# Продовжити у фоні
bg %1
# Запустити процес, який переживе logout
nohup ./script.sh &
# Output в nohup.out
# Або з disown
./script.sh &
disown
# Краще використовувати tmux/screen для long-running tasks
systemd¶
Архітектура¶
┌─────────────────────────────────────────────────────────────────┐
│ systemd │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ systemctl — управління сервісами │ │
│ │ journalctl — перегляд логів │ │
│ │ hostnamectl — hostname │ │
│ │ timedatectl — час та timezone │ │
│ │ loginctl — сесії користувачів │ │
│ │ systemd-analyze — аналіз завантаження │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Unit Types: │
│ .service — сервіси (демони) │
│ .socket — socket activation │
│ .target — групи units (аналог runlevels) │
│ .timer — scheduled tasks (аналог cron) │
│ .mount — точки монтування │
│ .path — file system paths (inotify) │
│ .device — пристрої │
│ .slice — cgroups ієрархія │
└─────────────────────────────────────────────────────────────────┘
systemctl — основні команди¶
# Статус сервісу
systemctl status nginx
systemctl status nginx.service # повна назва
# Запустити/зупинити/перезапустити
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl reload nginx # перечитати конфіг без restart
# Увімкнути/вимкнути автозапуск
systemctl enable nginx
systemctl disable nginx
systemctl enable --now nginx # enable + start
# Перевірити чи enabled
systemctl is-enabled nginx
# Перевірити чи active
systemctl is-active nginx
# Список всіх сервісів
systemctl list-units --type=service
systemctl list-units --type=service --state=running
systemctl list-units --type=service --state=failed
# Список unit файлів
systemctl list-unit-files --type=service
# Показати залежності
systemctl list-dependencies nginx
# Перезавантажити конфігурацію systemd
systemctl daemon-reload
Unit файли¶
# Розташування:
# /lib/systemd/system/ — системні units (пакети)
# /etc/systemd/system/ — локальні/override units
# /run/systemd/system/ — runtime units
# Переглянути unit файл
systemctl cat nginx.service
# Редагувати unit (створює override)
systemctl edit nginx.service
# Редагувати повний unit файл
systemctl edit --full nginx.service
Структура .service файлу¶
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
Documentation=https://example.com/docs
After=network.target postgresql.service
Requires=postgresql.service
Wants=redis.service
[Service]
Type=simple
User=appuser
Group=appgroup
WorkingDirectory=/opt/myapp
Environment=NODE_ENV=production
EnvironmentFile=/etc/myapp/env
ExecStartPre=/opt/myapp/pre-start.sh
ExecStart=/opt/myapp/start.sh
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/opt/myapp/stop.sh
Restart=on-failure
RestartSec=5
TimeoutStartSec=30
TimeoutStopSec=30
# Security
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Секції Unit файлу¶
┌─────────────────────────────────────────────────────────────────┐
│ [Unit] — метадані та залежності │
│ Description= Опис сервісу │
│ After= Запустити після (ordering) │
│ Before= Запустити перед │
│ Requires= Обов'язкові залежності │
│ Wants= Бажані залежності (не критичні) │
│ Conflicts= Конфліктуючі units │
│ │
├─────────────────────────────────────────────────────────────────┤
│ [Service] — як запускати сервіс │
│ Type= simple|forking|oneshot|notify|dbus │
│ ExecStart= Команда запуску │
│ ExecStop= Команда зупинки │
│ ExecReload= Команда reload │
│ Restart= no|always|on-success|on-failure|on-abnormal │
│ RestartSec= Затримка перед restart │
│ User=/Group= Від якого користувача запускати │
│ Environment= Змінні оточення │
│ WorkingDirectory= Робоча директорія │
│ │
├─────────────────────────────────────────────────────────────────┤
│ [Install] — як встановлювати (enable) │
│ WantedBy= До якого target прив'язати │
│ RequiredBy= Обов'язково для target │
│ Alias= Альтернативні імена │
└─────────────────────────────────────────────────────────────────┘
Service Types¶
# Type=simple (default)
# Процес запускається напряму, PID=main process
# Type=forking
# Процес форкається, батько завершується
# Потрібно вказати PIDFile=
# Type=oneshot
# Короткий процес, завершується після виконання
# RemainAfterExit=yes щоб вважався active
# Type=notify
# Процес сповіщає systemd про готовність через sd_notify()
# Type=dbus
# Процес реєструється на D-Bus
Приклад: власний сервіс¶
# /etc/systemd/system/myapi.service
[Unit]
Description=My REST API
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/api
ExecStart=/usr/bin/python3 app.py
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
# Застосувати
systemctl daemon-reload
systemctl enable --now myapi
systemctl status myapi
journalctl — системні логи¶
# Всі логи
journalctl
# Логи конкретного сервісу
journalctl -u nginx
journalctl -u nginx.service
# Follow (як tail -f)
journalctl -f
journalctl -fu nginx
# Останні N рядків
journalctl -n 100
journalctl -n 50 -u nginx
# За часом
journalctl --since "2026-01-17 10:00"
journalctl --since "1 hour ago"
journalctl --since today
journalctl --since yesterday --until today
# За пріоритетом (0-7)
journalctl -p err # error і вище
journalctl -p warning # warning і вище
# emerg=0, alert=1, crit=2, err=3, warning=4, notice=5, info=6, debug=7
# Kernel messages
journalctl -k
journalctl --dmesg
# Цього завантаження
journalctl -b
journalctl -b -1 # попереднього завантаження
# JSON output
journalctl -o json-pretty
# Disk usage
journalctl --disk-usage
# Очистити старі логи
journalctl --vacuum-time=7d # старші 7 днів
journalctl --vacuum-size=500M # обмежити до 500MB
Налаштування journald¶
# /etc/systemd/journald.conf
[Journal]
Storage=persistent # auto, volatile, persistent, none
Compress=yes
SystemMaxUse=500M # максимальний розмір
SystemMaxFileSize=50M # максимальний розмір одного файлу
MaxRetentionSec=1month # зберігати місяць
MaxFileSec=1day # ротація щодня
Targets (Runlevels)¶
# Targets замінили runlevels
# Поширені targets:
# poweroff.target — halt (runlevel 0)
# rescue.target — single user (runlevel 1)
# multi-user.target — multi-user, no GUI (runlevel 3)
# graphical.target — multi-user, GUI (runlevel 5)
# reboot.target — reboot (runlevel 6)
# Поточний target
systemctl get-default
# Змінити default target
systemctl set-default multi-user.target
# Перейти до target зараз
systemctl isolate rescue.target
systemctl isolate multi-user.target
Timers (замість cron)¶
Створення timer¶
# /etc/systemd/system/backup.service
[Unit]
Description=Daily backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily
[Timer]
OnCalendar=daily # або конкретний час
# OnCalendar=*-*-* 02:00:00
# OnCalendar=Mon *-*-* 09:00:00
Persistent=true # запустити пропущені
[Install]
WantedBy=timers.target
# Увімкнути timer
systemctl enable --now backup.timer
# Список timers
systemctl list-timers
# Статус
systemctl status backup.timer
OnCalendar синтаксис¶
# Формат: DayOfWeek Year-Month-Day Hour:Minute:Second
minutely → *-*-* *:*:00
hourly → *-*-* *:00:00
daily → *-*-* 00:00:00
weekly → Mon *-*-* 00:00:00
monthly → *-*-01 00:00:00
yearly → *-01-01 00:00:00
# Приклади:
*-*-* 02:00:00 # Кожного дня о 2:00
Mon,Fri *-*-* 10:00:00 # Пн та Пт о 10:00
*-*-* *:00,30:00 # Кожні 30 хвилин
*-*-1,15 00:00:00 # 1-го та 15-го числа
# Перевірити синтаксис
systemd-analyze calendar "Mon *-*-* 10:00"
Аналіз завантаження¶
# Час завантаження
systemd-analyze
# Детально по units
systemd-analyze blame
# Критичний шлях
systemd-analyze critical-chain
# Візуалізація (SVG)
systemd-analyze plot > boot.svg
# Перевірити unit файл
systemd-analyze verify /etc/systemd/system/myapp.service
Troubleshooting systemd¶
# Сервіс не запускається
systemctl status myapp.service
journalctl -u myapp.service -n 50 --no-pager
# Перевірити синтаксис unit файлу
systemd-analyze verify myapp.service
# Перезавантажити конфігурацію
systemctl daemon-reload
# Скинути failed state
systemctl reset-failed
# Залежності
systemctl list-dependencies myapp.service
systemctl list-dependencies --reverse myapp.service
# Що блокує shutdown
systemd-analyze blame
systemctl list-jobs
Типові проблеми та рішення¶
| Проблема | Причина | Рішення |
|---|---|---|
| Service failed | Помилка в ExecStart | journalctl -u service |
| Start timeout | Процес не запускається | Перевірити Type=, збільшити TimeoutStartSec |
| Zombie processes | Батько не обробляє SIGCHLD | Виправити код або використати init |
| High load | Runaway process | top/htop, kill, перевірити логіку |
| Changes not applied | Не виконано daemon-reload | systemctl daemon-reload |
| Service restarts | Restart=always | Перевірити exit code, логи |
Підсумок¶
Управління процесами:
ps aux # Список процесів
htop # Інтерактивний моніторинг
kill -15 PID # Graceful termination
kill -9 PID # Force kill (крайній захід)
systemd:
systemctl status service # Статус
systemctl start/stop # Запуск/зупинка
systemctl enable # Автозапуск
journalctl -u service # Логи
systemctl daemon-reload # Перезавантажити конфіг
Див. також¶
- Linux основи — базові команди
- Файлові системи — диски та монтування
- Networking в Linux — мережа
Шлях: getting-started/processes-systemd.md