
Я видел много менеджеров процессов, которые пытались это сделать. Я понимал, что для завершения процесса следует использовать только SIGTERM. Процессу может потребоваться неизвестное количество времени для очистки за собой; на медленной системе это может занять несколько минут. Я всегда думал, что единственным решением было набраться терпения и подождать, пока программа очистится и завершит работу корректно. Если процесс не перехватывает SIGTERM, то это ошибка, и о ней следует сообщить разработчику программного обеспечения.
Я видел, что популярные инструменты, такие как Docker, также пытаются сделать это:
Использование: остановка докера [ПАРАМЕТРЫ] КОНТЕЙНЕР [КОНТЕЙНЕР...]
Остановить работающий контейнер (отправить SIGTERM, а затем SIGKILL по истечении льготного периода)
Это плохая практика? Мне также интересно, как работает процедура завершения работы в системе инициализации в стиле SystemV. Я просмотрел несколько man-страниц и некоторые другие вопросы, но не могу найти точного ответа. Я предполагаю, что каждая служба инициализации (терминология?) видит изменение в уровне выполнения и выполняет соответствующую функцию «остановки», определенную в сценарии инициализации. Делает ли это по одному, гарантируя, что каждая служба завершается правильно? Что происходит с процессами, не обработанными сценариями инициализации? Я видел, что в некоторых вопросах смутно упоминается период отсрочки, используемый перед тем, как подать на них сигнал SIGKILL, но я надеялся, что кто-нибудь сможет объяснить или хотя бы указать мне правильное направление. :)
Если кто-то может помочь мне узнать больше о том, как это работает с systemd, я был бы рад исследовать и узнать больше. Я посмотрел man-страницы, но и здесь не нашел ничего определенного.
решение1
Вы можете либо получить свой пирог, либо съесть его. Программа хочет иметь столько времени, сколько ей нужно (или хочется), чтобы отреагировать на SIGTERM. Система (менеджер программ) хочет иметь возможность завершить работу. Если система ждет вечно, это позволяет программе перехватить завершение работы системы, никогда не отвечая (либо потому, что программа вредоносна, либо потому, что она глючит).
В обычной последовательности выключения каждый демон завершается с помощью сценария инициализации (назовите его сценарием выключения, если хотите), предоставленного автором или упаковщиком демона. В зависимости от демона сценарий инициализации может просто отправить ему сигнал или выполнить более контролируемое выключение (например, записав в сокет). Сценарий инициализации может ждать, пока демон не сообщит, что он успешно завершил работу, или может принудительно завершить его. Сценарии инициализации запускаются как root (они могут вызываться su
для выполнения части своей задачи как менее привилегированный пользователь); предполагается, что они будут кооперативными, поэтому им разрешено оставлять систему зависшей навсегда.
После того, как скрипты init завершат свою работу, все службы должны быть остановлены. Любой оставшийся процесс должен быть либо неважным, либо вести себя неправильно. Поэтому на этом этапе оставшимся процессам приказано завершить работу (SIGTERM), и после льготного периода (дающего им последний шанс завершить работу корректно) система должна отключиться, чтобы все оставшиеся процессы были принудительно завершены (SIGKILL).
Думайте о скриптах init как об обычной процедуре ареста — предъявите ордера, выкрикните предупреждение и т. д. Законопослушный демон должен отключиться в этот момент, хотя у демонов есть адвокаты (скрипты init), которые могут откладывать процедуру так долго, как им хочется. После завершения обычного процесса оставшиеся демоны считаются враждебными. Система делает предупредительный выстрел (SIGTERM), а затем после задержки стреляет в SIGKILL.