Каждая запущенная программа — процесс с числовым идентификатором PID. Управляют процессами через сигналы: kill вопреки имени не «убивает», а посылает уведомление, и от номера сигнала зависит, может ли процесс отреагировать по-своему или будет снят ядром без разговоров. Эта разница — между kill и kill -9 — решает, успеет ли сервер дописать данные перед остановкой.
TERM даёт шанс завершиться. KILL — нет
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; проверить себя быстро можно скилл-тестом. Рядом в справочнике: конвейеры и перенаправление — как устроены потоки, через которые процессы общаются.