Инструкция

Процессы в Linux: ps, top, htop, kill, сигналы и nice

Обновлено: · Skillaria.Top

Процессы в Linux смотрят командой ps aux (разовый снимок), top и htop (обновляемый список с нагрузкой). Завершают процесс командой kill PID, которая по умолчанию шлёт вежливый SIGTERM; kill -9 (SIGKILL) нужен только если процесс не реагирует. Приоритет задают nice при запуске и renice для уже работающего процесса, в диапазоне от -20 до 19.

Любая запущенная программа в Linux — это процесс с собственным номером PID, владельцем, состоянием и приоритетом. Посмотреть процессы можно командами ps, top и htop, завершить — командой kill, а изменить их приоритет — через nice и renice. Ниже разберём, как читать вывод этих команд, какие сигналы когда отправлять и почему kill -9 не должен быть первым рефлексом.

Что такое процесс и PID

Процесс — это программа в момент выполнения: код, память, открытые файлы и набор атрибутов. Ядро выдаёт каждому процессу уникальный идентификатор PID, а также запоминает PPID — номер родителя, который его запустил. Самый первый процесс в системе с PID 1 — обычно systemd, он и становится «предком» всех остальных.

Новый процесс появляется в два шага. Сначала родитель вызывает fork() и получает свою копию, затем копия вызывает execve() и заменяет свой код кодом новой программы. Когда вы набираете в терминале ls, bash делает именно это и ждёт завершения потомка через wait().

$ echo $$          # PID текущей оболочки
4182
$ ps -o pid,ppid,cmd -p $$
    PID    PPID CMD
   4182    4170 -bash

Как посмотреть процессы командой ps

ps делает разовый снимок: показывает процессы ровно на момент запуска и завершается. Без аргументов он выводит только процессы текущего терминала, поэтому на практике почти всегда используют один из двух вариантов.

$ ps aux | head -5
USER       PID %CPU %MEM    VSZ   RSS TTY   STAT START   TIME COMMAND
root         1  0.0  0.3 168540 12780 ?     Ss   09:12   0:03 /sbin/init
root         2  0.0  0.0      0     0 ?     S    09:12   0:00 [kthreadd]
www-data  1532  1.2  2.1 412308 86420 ?     S    09:15   1:47 php-fpm: pool www
postgres  1610  0.4  3.8 221004 154312 ?    Ss   09:15   0:31 postgres: checkpointer

Здесь a — процессы всех пользователей, u — подробный формат с владельцем, x — включая процессы без терминала (демоны). Альтернативный синтаксис в стиле System V — ps -ef: он показывает PPID, что удобно, когда нужно понять, кто кого запустил.

КолонкаЧто означает
PIDидентификатор процесса
%CPU, %MEMдоля процессора и физической памяти
VSZвиртуальная память в КБ (включая не загруженное в RAM)
RSSреально занятая физическая память в КБ
STATсостояние процесса (R, S, D, Z, T) и флаги
TIMEсуммарное процессорное время, а не время работы

Полезные приёмы с ps

# топ-10 по памяти
ps aux --sort=-%mem | head -11

# топ-10 по процессору
ps aux --sort=-%cpu | head -11

# свои колонки
ps -eo pid,ppid,user,ni,stat,etime,cmd

# дерево процессов
ps -ef --forest
pstree -p

# найти PID по имени
pgrep -a nginx
pidof nginx

Классическая ошибка — искать процесс через ps aux | grep nginx и получить в выводе сам grep. Используйте pgrep или трюк grep [n]ginx, который не совпадает с собственной командной строкой.

Состояния процессов: R, S, D, Z, T

Буква в колонке STAT — не мусор, а реальное состояние процесса. От неё зависит, как интерпретировать нагрузку и поможет ли вообще kill.

КодСостояниеЧто значит на практике
RRunningвыполняется или стоит в очереди на CPU
SInterruptible sleepждёт события (сеть, ввод, таймер); обычное состояние большинства процессов
DUninterruptible sleepждёт ввода-вывода внутри ядра, сигналы не доставляются
ZZombieзавершился, но родитель не забрал код выхода
TStoppedприостановлен сигналом SIGSTOP или Ctrl+Z

Дополнительные символы после буквы тоже полезны: s — лидер сессии, + — процесс переднего плана в терминале, < — повышенный приоритет, N — пониженный, l — многопоточный.

Процесс в состоянии D

Процесс в D находится внутри системного вызова и ждёт, например, ответа от диска или зависшего NFS. Ему не доставляется ни один сигнал, даже SIGKILL. Поэтому kill -9 тут бесполезен: нужно искать причину ожидания — смотреть iostat, dmesg, состояние сетевого хранилища.

Зомби-процессы

Зомби уже мёртв: он не тратит CPU и память, а занимает только строчку в таблице процессов. Убить его нельзя — он и так завершён. Исчезнет он, когда родитель вызовет wait() или когда сам родитель завершится и зомби «усыновит» PID 1.

# найти зомби и их родителей
ps -eo pid,ppid,stat,cmd | awk '$3 ~ /Z/'

Единичный зомби безвреден. Если их сотни и число растёт, ошибка в родительской программе: её нужно исправить или перезапустить.

top: процессы и нагрузка в реальном времени

top показывает тот же список, но обновляет его каждые несколько секунд и выводит сводку по системе. Это первая команда, которую запускают, когда «сервер тормозит».

top - 14:21:07 up 12 days,  3:02,  2 users,  load average: 1.84, 1.20, 0.95
Tasks: 213 total,   2 running, 211 sleeping,   0 stopped,   0 zombie
%Cpu(s): 23.1 us,  4.2 sy,  0.0 ni, 70.3 id,  1.9 wa,  0.0 hi,  0.5 si,  0.0 st
MiB Mem :   7821.4 total,    412.6 free,   3105.8 used,   4303.0 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   4398.2 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   1532 www-data  20   0  412308  86420  14212 R  38.2   1.1   1:47.31 php-fpm
   1610 postgres  20   0  221004 154312 148900 S   6.0   1.9   0:31.08 postgres

В строке %Cpu(s) важнее всего: us — пользовательский код, sy — ядро, id — простой, wa — ожидание диска. Высокий wa при свободном процессоре — верный признак, что узкое место в вводе-выводе.

Горячие клавиши top

КлавишаДействие
P / Mсортировка по CPU / по памяти
1показать каждое ядро отдельно
cполная командная строка
uфильтр по пользователю
kотправить сигнал процессу
rизменить nice процесса
Hпоказать потоки
qвыход

Для скриптов и логов пригодится пакетный режим: top -b -n 1 | head -20 выведет один снимок без интерактива. Следить за конкретным процессом — top -p 1532.

Load Average — это очередь, а не процент

Три числа load average — средняя длина очереди за 1, 5 и 15 минут. В Linux туда попадают процессы в состояниях R и D, а обычный сон S — нет. Сравнивать LA нужно с числом ядер (nproc): на 4 ядрах значение 4 — полная загрузка, а 12 — очередь втрое больше возможностей.

Если LA высокий, а процессор простаивает, ищите процессы в D: ps -eo stat,pid,cmd | grep '^D'. Почти всегда это медленный диск или сетевое хранилище.

htop: удобная замена top

htop показывает то же самое, но с цветными индикаторами по ядрам, прокруткой, поддержкой мыши и деревом процессов. Обычно его надо установить: sudo apt install htop или sudo dnf install htop.

  • F3 или / — поиск процесса по имени;
  • F4 — фильтр, оставляющий только совпадения;
  • F5 или t — дерево «родитель — потомки»;
  • F6 — выбор колонки сортировки;
  • F7 / F8 — уменьшить или увеличить nice;
  • F9 — меню сигналов для выбранного процесса;
  • Space — отметить несколько процессов для массового действия.

На серверах без возможности что-то ставить достаточно top: все ключевые операции в нём тоже есть.

Как завершить процесс: kill и сигналы

Команда kill не «убивает», а отправляет процессу сигнал. Что произойдёт дальше, зависит от сигнала и от того, как программа его обрабатывает.

СигналНомерНазначение
SIGHUP1обрыв терминала; многие демоны перечитывают конфиг
SIGINT2прерывание, то же, что Ctrl+C
SIGKILL9принудительное завершение ядром, перехватить нельзя
SIGTERM15просьба завершиться аккуратно; по умолчанию у kill
SIGSTOP19приостановить, перехватить нельзя
SIGCONT18продолжить приостановленный процесс
SIGTSTP20приостановка с терминала, Ctrl+Z

Номера указаны для x86 и ARM; полный список выводит kill -l. Писать сигнал по имени надёжнее, чем по номеру.

kill 1532              # SIGTERM
kill -TERM 1532        # то же явно
kill -HUP $(pidof nginx)   # перечитать конфигурацию
kill -STOP 1532; kill -CONT 1532
kill -0 1532 && echo "процесс жив"

Сигнал 0 ничего не отправляет, а только проверяет, существует ли процесс и есть ли у вас право ему писать, — удобно в скриптах.

Почему не стоит начинать с kill -9

SIGTERM даёт программе шанс закрыть файлы, сбросить буферы, удалить lock-файлы и корректно завершить транзакции. SIGKILL обрывает всё мгновенно: недописанные данные теряются, временные файлы остаются, а база данных при следующем старте может уйти в восстановление.

Правильная последовательность такая:

  1. Отправить kill PID (SIGTERM).
  2. Подождать 5–30 секунд, проверяя kill -0 PID.
  3. Только если процесс жив и не в состоянии D — kill -9 PID.

Для сервисов под systemd лучше вообще не трогать PID вручную: systemctl stop сам отправит SIGTERM, выждет таймаут и добьёт SIGKILL.

pkill и killall: по имени

pkill -f "python worker.py"   # по полной командной строке
pkill -u alice                 # все процессы пользователя
killall -TERM node             # все процессы с именем node
pgrep -l -f worker             # сначала проверьте, что попадёт под шаблон

Перед массовым pkill всегда запускайте pgrep с тем же шаблоном: -f совпадает с любой частью командной строки и легко зацепит лишнее.

Отправлять сигналы можно только своим процессам; чужие требуют sudo. Ошибка Operation not permitted означает именно это.

Приоритет процессов: nice и renice

Значение nice подсказывает планировщику, кому уступать процессор. Диапазон — от -20 (самый высокий приоритет) до 19 (уступает всем), по умолчанию 0. В top оно видно в колонке NI, а PR — производный внутренний приоритет.

# запустить тяжёлую задачу с пониженным приоритетом
nice -n 10 tar czf backup.tar.gz /var/www

# понизить приоритет работающего процесса
renice -n 15 -p 1532

# повысить (только root)
sudo renice -n -5 -p 1610

# все процессы пользователя
sudo renice -n 10 -u alice

Обычный пользователь может только понижать приоритет своих процессов, отрицательные значения доступны лишь root. Важно понимать предел nice: он влияет только на CPU. Если задача тормозит систему диском, используйте ionice -c3 команда — класс idle, который получает диск, лишь когда тот никому не нужен.

Фоновые процессы и задания оболочки

Команду можно запустить в фоне, добавив &, или приостановить через Ctrl+Z. Оболочка ведёт список заданий, которыми управляют встроенные команды.

$ long_task &
[1] 5120
$ jobs
[1]+  Running    long_task &
$ fg %1        # вернуть на передний план
^Z             # приостановить (SIGTSTP)
$ bg %1        # продолжить в фоне

При закрытии терминала оболочка шлёт заданиям SIGHUP, и они завершаются. Чтобы процесс пережил выход, запускайте его через nohup команда &, отвязывайте командой disown или используйте tmux. Для постоянной работы правильнее оформить его как сервис systemd.

Типичные сценарии диагностики

Кто съел процессор

top -o %CPU            # или P внутри top
ps -eo pid,user,%cpu,etime,cmd --sort=-%cpu | head

Если процесс жрёт CPU без пользы, сначала понизьте ему приоритет через renice — это безопасно и даёт время разобраться.

Кто занял порт

sudo ss -ltnp | grep :8080
sudo lsof -i :8080

В выводе будет PID, а дальше по нему в /proc/PID/ можно найти исполняемый файл (exe), рабочий каталог (cwd) и аргументы (cmdline).

Процесс неожиданно исчез

Частая причина — OOM Killer, который убивает процессы при нехватке памяти. Проверка: dmesg -T | grep -i oom или journalctl -k | grep -i "killed process".

Итог

Для работы с процессами в Linux хватает небольшого набора команд: ps aux для снимка, top и htop для наблюдения, kill с правильным сигналом для завершения и nice/renice для приоритетов. Читайте состояние процесса прежде чем действовать: зомби и процессы в D сигналами не лечатся. И начинайте с SIGTERM, оставляя kill -9 на крайний случай. Процессы, память, Load Average и системные вызовы подробно разобраны на практике в курсе по Linux.

Частые вопросы

Чем ps aux отличается от ps -ef?

Это два синтаксиса одной команды: aux — BSD-стиль с колонками %CPU, %MEM и STAT, -ef — стиль System V с колонкой PPID. Набор процессов в обоих случаях один и тот же — все процессы системы.

Как узнать, сколько процессов запущено в системе?

Проще всего посмотреть строку Tasks в top или выполнить ps -e --no-headers | wc -l. Число потоков покажет ps -eLf --no-headers | wc -l.

Почему процесс не завершается даже после kill -9?

Либо он в состоянии D и ждёт ввода-вывода в ядре, либо это зомби, который уже завершён. В первом случае ищите проблему с диском или сетевым хранилищем, во втором — исправляйте или перезапускайте родителя.

Что будет, если убить процесс с PID 1?

Ядро защищает init: обычные сигналы, включая SIGKILL от пользователя, ему не доставляются, если он их не обрабатывает. Если же init всё-таки завершится, система уйдёт в kernel panic.

Как ограничить процессу использование памяти?

Для сервиса systemd задайте MemoryMax= в unit-файле, для разового запуска — systemd-run --scope -p MemoryMax=500M команда. Это работает через cgroups и надёжнее старого ulimit -v.

Разберите тему на видео

Эта тема подробно разобрана с практикой в курсе «Linux: с нуля до уверенного администрирования».

Перейти к курсу