Как убить процесс через терминал
Что проверяют
Базовую работу с Linux и понимание сигналов, а не только команду kill -9. Для Go-разработчика следом почти всегда спрашивают про graceful shutdown: какой сигнал получит сервис при остановке контейнера и как его корректно обработать.
Как отвечать
Сначала найти процесс, потом послать нужный сигнал:
- поиск:
pgrep -f myappвместоps aux | grep, по портуss -ltnpилиlsof -i :8080; kill PID: без флага отправляетSIGTERM(15), просьбу завершиться. Процесс может перехватить сигнал, закрыть соединения и выйти сам;kill -9 PID(SIGKILL): ядро снимает процесс сразу, перехватить или проигнорировать сигнал нельзя. Никакой код завершения не выполнится;kill -INT PID(SIGINT): то же, что Ctrl+C в терминале;- по имени:
pkill myappилиkillall myapp, осторожно с похожими именами.
Правильный порядок: SIGTERM, пауза на завершение и только потом SIGKILL. Так же устроены docker stop (10 секунд по умолчанию) и Kubernetes (terminationGracePeriodSeconds, по умолчанию 30).
Для Go добавьте две вещи. Без обработчика SIGINT и SIGTERM просто завершают программу, поэтому сервис ловит их через signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM) и вызывает Shutdown(ctx) у http.Server, чтобы дождаться текущих запросов. А kill -QUIT PID завершает Go-программу с дампом стеков горутин: полезно, когда сервис завис и непонятно где.
Где спотыкаются
Сразу бьют kill -9. Сервис не успевает закрыть соединения и дописать данные. Причём и SIGTERM без обработчика не выполнит в Go ни одного defer, так что обработчик нужен в любом случае.
Пытаются убить зомби-процесс. Он уже завершён и ждёт, пока родитель заберёт код выхода через wait, сигналы на него не действуют, разбираться нужно с родителем.
Удивляются, что процесс не реагирует даже на SIGKILL. Так бывает в состоянии D, непрерываемом ожидании ввода-вывода (часто это зависший NFS или диск): процесс завершится, когда вернётся системный вызов.