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

Linux Автор: Среда и версия: Ubuntu 24.04, bash 5.2, procps-ng 4.0
содержание

Каждая запущенная программа — процесс с числовым идентификатором PID. Управляют процессами через сигналы: kill вопреки имени не «убивает», а посылает уведомление, и от номера сигнала зависит, может ли процесс отреагировать по-своему или будет снят ядром без разговоров. Эта разница — между kill и kill -9 — решает, успеет ли сервер дописать данные перед остановкой.

Linux / 01

TERM даёт шанс завершиться. KILL — нет

TERM даёт шанс завершиться. KILL — нет01 SIGTERM сигнал → обработчик → очистка → выход Процесс может перехватить сигнал и закончить работу. 02 SIGKILL сигнал → остановка Перехватить нельзя. Обработчик и очистка не выполнятся.01SIGTERMсигнал → обработчик→ очистка → выходПроцесс может перехватить сигнал изакончить работу.02SIGKILLсигнал → остановкаПерехватить нельзя. Обработчик и очисткане выполнятся.
kill PID даёт процессу шанс закончить дела, kill -9 — нет. Поэтому -9 — последний аргумент, а не первый.

Посмотреть процессы: ps и top

ps aux печатает все процессы системы: столбцы USER, PID, %CPU, %MEM, STAT и COMMAND. Список длинный, поэтому обычно его фильтруют конвейером ps aux | grep nginx или сразу спрашивают точечно:

sleep 300 &
demo_pid=$!
echo "PID процесса: $demo_pid"
ps -o pid,stat,cmd -p "$demo_pid"
PID процесса: 9
    PID STAT CMD
      9 S    sleep 300

В этом прогоне PID был 9; у тебя число будет другим. Не подставляй номера из чужого вывода в kill. Примеры ниже используют PID собственного запущенного sleep.

Здесь три вещи разом: & запускает команду в фоне, $! хранит PID последнего фонового процесса, а ps -p показывает состояние конкретного PID. STAT S — процесс спит в ожидании. Когда нужна живая картинка, а не снимок, запускают top (или его удобный аналог htop): интерактивная таблица, обновляется сама, выход по q.

kill: послать сигнал

Без номера kill посылает SIGTERM (15) — вежливую просьбу завершиться:

kill "$demo_pid"
wait "$demo_pid"
ps -o pid,stat,cmd -p "$demo_pid"
    PID STAT CMD

Процесс вышел, ps вернул пустую таблицу и код 1. Сигналов больше шестидесяти (kill -l покажет весь список), но в работе постоянно встречаются четыре: SIGTERM (15) — штатная остановка, SIGKILL (9) — принудительная, SIGINT (2) — то, что летит в процесс по Ctrl+C, SIGHUP (1) — «терминал закрылся», им же демоны часто перечитывают конфиги.

SIGTERM можно поймать — на этом строится graceful shutdown

Программа вправе назначить обработчик SIGTERM: дописать буфер, закрыть соединения, удалить временные файлы. В bash это делает trap:

trap "echo поймал SIGTERM, удаляю временные файлы; exit 0" TERM
sleep 300 & wait

Пошлём этому скрипту kill и увидим его последние слова:

поймал SIGTERM, удаляю временные файлы

Ровно так устроена остановка сервисов повсюду: systemd при systemctl stop и Docker при docker stop сначала шлют SIGTERM и дают время на уборку, и только по таймауту добивают SIGKILL’ом.

SIGKILL поймать нельзя

SIGKILL и SIGSTOP — два сигнала, которые нельзя ни перехватить, ни проигнорировать: они обрабатываются ядром, минуя процесс. Для безопасного знакомства запусти отдельный sleep и пошли сигнал именно ему:

sleep 300 &
kill_demo_pid=$!
kill -9 "$kill_demo_pid"
wait "$kill_demo_pid"

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

bash: line 7:    17 Killed                  bash -c "trap \"echo этого никто не увидит\" TERM; ..."

Обработчик не запустился — шелл лишь доложил, что процесс Killed. Отсюда правило: сначала kill, подождать, и только если процесс завис намертво — kill -9. Начинать с -9 — значит гарантированно лишить программу шанса сохранить данные.

Коды возврата: 128 + номер сигнала

Когда процесс завершён сигналом, Bash представляет его статус как 128 плюс номер сигнала. Если программа перехватила сигнал и завершилась сама, код задаёт она: обработчик с exit 0 выше вернёт 0.

sleep 100 &
kill $!
wait $!
echo "код возврата: $?"
код возврата: 143

143 = 128 + 15, то есть «завершён по SIGTERM». По той же арифметике читается 137 (128 + 9, убит SIGKILL — частый спутник нехватки памяти и OOM killer) и 130 (128 + 2, прерван по Ctrl+C). Эти числа то и дело встречаются в логах CI и Docker, и теперь они читаются как открытая книга.

Ошибки, на которых спотыкаются

kill -9 первым делом. SIGKILL нельзя перехватить, но отправка требует прав, а завершение может задержаться в состоянии D. Обработчик уборки не вызывается: недописанные файлы, незакрытые транзакции, осиротевшие lock-файлы. Сначала обычный kill.

Убийство по имени вслепую. pkill node снимет все процессы с node в имени — включая чужой редактор и соседний проект. Безопасный порядок: найти точный PID (pgrep -a node покажет и PID, и командную строку), убедиться глазами, убить конкретный PID.

Зомби пытаются убить kill -9. Процесс в состоянии Z уже мёртв — это запись в таблице процессов, которую не прочитал родитель. Сигналы ему бесполезны; исчезнет, когда родитель считает статус или сам завершится.

Путать PID с номером задания. kill 1 и kill %1 — разные вещи: первый шлёт сигнал процессу с PID 1 (в контейнере это главный процесс!), второй — первому фоновому заданию текущего шелла.

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

Как найти PID процесса по имени

pgrep -a nginx — печатает PID и полную команду каждого совпадения. Классика ps aux | grep nginx тоже работает, но ловит в выдачу сам grep; у pgrep этой проблемы нет.

Почему процесс не умирает после kill

Либо программа перехватила SIGTERM и медленно убирается, либо процесс завис в непрерываемом системном вызове (состояние D — обычно ожидание диска или сети). Первому случаю поможет подождать и повторить, второму не поможет даже kill -9: сигнал доставится только после выхода из вызова.

Что значит Killed в терминале

Процесс получил SIGKILL. Если ты его не посылал, главный подозреваемый — ядерный OOM killer, снимающий самые прожорливые процессы при нехватке памяти. Проверяется по dmesg | grep -i oom.

Чем SIGTERM отличается от SIGINT

Оба — просьбы завершиться, и оба перехватываемы. SIGINT прилетает с клавиатуры по Ctrl+C, SIGTERM посылают команды и системы управления сервисами. По умолчанию эффект одинаковый — разница в источнике.

Где потренироваться

Сигналы, коды возврата и zombie-процессы — из любимых тем собеседований по Linux; проверить себя быстро можно скилл-тестом. Рядом в справочнике: конвейеры и перенаправление — как устроены потоки, через которые процессы общаются.

Источники