Good

Процеси та systemd

Процеси в Linux

Що таке процес?

Процес — це запущена програма з власним адресним простором, ресурсами та станом.

flowchart TB
    systemd[systemd<br/>PID 1]
    sshd[sshd]
    session[sshd session]
    bash[bash]
    vim[vim]
    nginx[nginx master]
    worker1[nginx worker]
    worker2[nginx worker]
    dockerd[dockerd]
    containerd[containerd]

    systemd --> sshd
    systemd --> nginx
    systemd --> dockerd
    sshd --> session
    session --> bash
    bash --> vim
    nginx --> worker1
    nginx --> worker2
    dockerd --> containerd

    style systemd fill:#ef4444,color:#fff
    style nginx fill:#22c55e,color:#fff
    style dockerd fill:#3b82f6,color:#fff

Кожен процес має:
- PID (Process ID)
- PPID (Parent Process ID)
- UID/GID (User/Group)
- Стан (Running, Sleeping, Zombie...)
- Пріоритет (nice value)

Стани процесів

stateDiagram-v2
    [*] --> Created: fork()
    Created --> Running: scheduled
    Running --> Sleeping: wait I/O
    Sleeping --> Running: I/O complete
    Running --> Stopped: SIGSTOP/Ctrl+Z
    Stopped --> Running: SIGCONT
    Running --> Zombie: exit()
    Zombie --> [*]: parent wait()

    note right of Running: R - виконується на CPU
    note right of Sleeping: S - чекає на I/O
    note right of Zombie: Z - завершений,<br/>чекає на батька
Стан Код Опис
Running R Виконується на CPU
Sleeping S Чекає на I/O або подію
Disk sleep D Неперервний сон (I/O)
Zombie Z Завершений, чекає на батька
Stopped T Зупинений (Ctrl+Z)
Idle I 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

flowchart LR
    subgraph SIGTERM ["✅ SIGTERM (15) — рекомендований"]
        T1[Сигнал] --> T2[Процес отримує]
        T2 --> T3[Зберігає дані]
        T3 --> T4[Закриває з'єднання]
        T4 --> T5[Коректний вихід]
    end

    subgraph SIGKILL ["⚠️ SIGKILL (9) — крайній захід"]
        K1[Сигнал] --> K2[Ядро вбиває]
        K2 --> K3[❌ Втрата даних]
        K2 --> K4[❌ Ресурси не звільнені]
    end

    style T5 fill:#22c55e,color:#fff
    style K3 fill:#ef4444,color:#fff
    style K4 fill:#ef4444,color:#fff

Правильний порядок:
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

Архітектура

flowchart TB
    subgraph Systemd ["systemd"]
        subgraph Tools ["Інструменти"]
            systemctl[systemctl<br/>управління сервісами]
            journalctl[journalctl<br/>логи]
            hostnamectl[hostnamectl]
            timedatectl[timedatectl]
        end

        subgraph Units ["Unit Types"]
            service[.service<br/>демони]
            socket[.socket<br/>socket activation]
            target[.target<br/>групи units]
            timer[.timer<br/>scheduled tasks]
            mount[.mount<br/>монтування]
        end
    end

    systemctl --> service
    systemctl --> socket
    systemctl --> target
    systemctl --> timer
    journalctl -.->|читає логи| service

    style systemctl fill:#3b82f6,color:#fff
    style journalctl fill:#22c55e,color:#fff
    style service fill:#f59e0b,color:#000

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  # Перезавантажити конфіг

Див. також

Шлях: getting-started/processes-systemd.md

UMTC Wiki © 2026 | Ukrainian Military Tactical Communications