signal=USR1 и signal=USR2 (status=10/USR1) в systemd
Пользовательские сигналы не значат ничего заранее: их смысл задаёт сама программа. Пока обработчик не установлен, поведение по умолчанию — завершение процесса, поэтому попытка «мягко перечитать настройки» сигналом, которого программа не знает, просто убивает службу. Номер в записи журнала зависит от архитектуры: на обычном сервере USR1 — это 10, а USR2 — 12, на некоторых других архитектурах числа другие, поэтому искать в журнале надёжнее по имени сигнала.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Строка перезагрузки шлёт сигнал, которого программа не знает
Описание службы часто собирают копированием из соседнего проекта вместе со строкой посылки сигнала. Команда перезагрузки после этого работает как команда остановки, причём с пометкой неудачи.
-
Сигнал шлёт стороннее расписание по имени процесса
Правила поворота файлов и самодельные скрипты рассылают сигнал по имени, а под имя попадают все запущенные копии, включая чужие и служебные.
-
Смысл сигнала взят у другой программы
У популярного веб-сервера USR1 переоткрывает файлы журнала, а USR2 меняет исполняемый файл на ходу. Эти правила переносят на службы, которые ничего подобного не умеют.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Какие сигналы служба получает при перезагрузке настроек и при остановке.
systemctl show ИМЯ.service -p ExecReload -p KillSignal -p RestartKillSignalКогда служба погибала от пользовательского сигнала и чем это кончалось.
journalctl -u ИМЯ.service --no-pager | grep -E "signal=USR[12]|Failed with result"Номера сигналов на этой архитектуре: по ним читаются записи вида status=10/USR1.
kill -l | head -4Решение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Описание службы часто собирают копированием из соседнего проекта вместе со строкой посылки сигнала. Команда перезагрузки после этого работает как команда остановки, причём с пометкой неудачи.
- Как проверить
-
Посмотрите, что назначено на перезагрузку, и сверьте с документацией самой программы.
systemctl show ИМЯ.service -p ExecReload journalctl -u ИМЯ.service --no-pager | grep -E "signal=USR[12]" | tail -3
- Как исправить
-
Замените посылку сигнала на родную команду перезагрузки программы, а если перезагрузки настроек у неё нет — уберите
ExecReload=вовсе и перезапускайте службу целиком.
- Почему происходит
- Правила поворота файлов и самодельные скрипты рассылают сигнал по имени, а под имя попадают все запущенные копии, включая чужие и служебные.
- Как проверить
-
Поищите посылку сигнала в правилах поворота журналов и расписаниях.
grep -rn "USR[12]" /etc/logrotate.d/ /etc/cron.d/ /etc/cron.*/ 2>/dev/null | head
- Как исправить
-
Шлите сигнал главному процессу конкретной службы через
systemctl kill --signal=, а не по имени: так он не достанется однофамильцам.systemctl kill --signal=USR1 ИМЯ.service
- Почему происходит
- У популярного веб-сервера USR1 переоткрывает файлы журнала, а USR2 меняет исполняемый файл на ходу. Эти правила переносят на службы, которые ничего подобного не умеют.
- Как проверить
-
Проверьте на копии, что программа делает с сигналом, вместо того чтобы проверять на рабочей службе.
systemd-run --unit=usr-test /путь/к/программе systemctl kill --signal=USR1 usr-test.service; systemctl status usr-test.service --no-pager | head -5
- Как исправить
- Сверяйтесь с документацией самой программы: перечень понимаемых сигналов у каждой свой, и общего правила для пользовательских сигналов не существует.
Пример вывода
Служба убита сигналом USR1, посланным вручную главному процессу. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
$ systemd-run --unit=usr1-test /bin/sleep 300
$ kill -USR1 $(systemctl show usr1-test -p MainPID --value)
systemd[1]: usr1-test.service: Main process exited, code=killed, status=10/USR1
systemd[1]: usr1-test.service: Failed with result 'signal'.
× usr1-test.service - /bin/sleep 300
Active: failed (Result: signal) since Mon 2026-09-21 04:43:52 CEST; 2s ago
Process: 270204 ExecStart=/bin/sleep 300 (code=killed, signal=USR1)
Связанные ошибки
- signal=HUP (status=1/HUP) в systemd Процесс службы завершён сигналом HUP. Обычно это перезагрузка настроек, которую программа поняла как команду выйти.
- signal=TERM (status=15/TERM) в systemd Процесс службы завершён сигналом TERM. Когда это нормальная остановка, а когда признак проблемы.
- Failed with result 'signal' Состояние signal: процесс службы завершён сигналом без сохранения дампа. Как узнать, каким сигналом и от кого.
- nginx reload не применяет изменения Перезагрузка nginx прошла, а изменения не действуют: правка не в том файле, файл не включён, кеш, старые рабочие процессы.
- signal=ABRT (status=6/ABRT) в systemd Процесс службы завершён сигналом ABRT: программа сама прервала работу после внутренней проверки. Где искать причину.
- signal=BUS (status=7/BUS) в systemd Процесс службы завершён сигналом BUS: ошибка доступа к памяти, часто из-за усечённого файла в отображении или заполненного диска.
- signal=FPE (status=8/FPE) в systemd Процесс службы завершён сигналом FPE: арифметическая ошибка, чаще всего деление на ноль в целочисленной арифметике.
- signal=ILL (status=4/ILL) в systemd Процесс службы завершён сигналом ILL: недопустимая инструкция процессора. Обычно сборка не под этот процессор.
Где встречается чаще всего
Источники
-
signal(7), Linux man-pages
Действие по умолчанию для USR1 и USR2 — завершение процесса; номера сигналов различаются по архитектурам (10 и 12 на обычном сервере, 30 и 31 или 16 и 17 на других). -
systemd.service(5)
ExecReload= — команда перезагрузки настроек; KillSignal= — сигнал остановки. -
Проверено на этой машине: systemd 255 (255.4-1ubuntu8.17), Ubuntu 24.04
Воспроизведено на этой машине: временной службе послан USR1, в журнале появилось «Main process exited, code=killed, status=10/USR1» и результат «signal». Номера сигналов сверены с `kill -l` и таблицей в man 7 signal. Строка `ExecReload=/bin/kill -USR1 $MAINPID` встретилась тут же, в unit-файле установленной панели.