Как определить, умер ли долго выполняющийся процесс?

Я работаю над демоном, который взаимодействует с несколькими процессами. Демон не может постоянно следить за процессами, но он должен быть в состоянии правильно определить, умирает ли процесс, чтобы высвободить пугающие ресурсы, которые он для него хранит.

Процессы могут взаимодействовать с демоном, передавая ему некоторую информацию при запуске, но не наоборот. Таким образом, демон не может просто запросить у процесса его личность.

Простейшей формой было бы использование только их PID. Но в конечном итоге другой процесс может быть назначен тому же самому PID без уведомления моего инструмента.

Лучшим подходом было бы использование PID плюс время запуска процесса. Новый процесс с тем же PID будет иметь другое время запуска. Но я не мог найти способ, как получить время запуска процесса в формате POSIX. Использование ps или просмотр /proc/<pid>/stat кажется недостаточно переносимым.

Более сложная идея, которая кажется совместимой с POSIX, будет заключаться в следующем:

  • Каждый процесс создает временный файл.
  • Блокирует его с помощью flock
  • Сообщает моему демону: «Моя личность связана с этим файлом».
  • В любое время демон может проверить временный файл. Если он заблокирован, процесс активен. Если это не так, процесс мертв.

Но это кажется излишне сложным.

Есть ли лучший или стандартный способ?

Изменить: демон должен иметь возможность возобновить работу после перезапуска, поэтому невозможно поддерживать постоянное соединение для каждого процесса.


person Petr    schedule 25.11.2013    source источник


Ответы (3)


Но я не смог найти способ получить время запуска процесса в формате POSIX.

Попробуйте описатель стандартного формата "etime": LC_ALL=C ps -eo etime= $PIDS

Честно говоря, я бы, вероятно, построил свою собственную таблицу живых процессов, а не полагался на таблицу процессов и прошедшее время. По сути, это ваш подход к блокировке файлов, хотя я бы, вероятно, собрал все файлы блокировки вместе в известном месте и назвал их по PID, например, /var/run/my-app/8819.lock. На самом деле, это может быть даже модернизировано для долго выполняющихся процессов, поскольку файловые блокировки на файловых дескрипторах могут быть унаследованы через exec().

(Конечно, если бы длительные процессы, о которых я заботился, имели общего родителя, то я бы предпочел запросить общего родителя, который может быть надежным авторитетом в отношении того, какие процессы выполняются, а какие нет.)

person pilcrow    schedule 25.11.2013

Стандартный способ излишне сложен. Это жизнь в POSIX-совместимой среде...

person Alexander    schedule 25.11.2013

Существуют и другие методы, отличные от файла, и они имеют различные преимущества/компромиссы - для этого также подойдет большинство "стандартных" механизмов IPC - сокет, канал, очередь сообщений, общая память... В основном выберите один механизм, который позволяет вашему приложению объявить демону, что он запущен (и, возможно, что он завершает работу, для упорядоченного завершения работы). В промежутках он может отправлять периодические сообщения «Я все еще здесь», и демон может заметить, когда он не получает их, или демон может периодически опрашивать или что-то в этом роде... Есть довольно много способов добиться того, что вы хотите, но, не зная больше о точной архитектуре, которую вы пытаетесь достичь, трудно указать на "один лучший способ"...

person twalberg    schedule 25.11.2013
comment
Проблема в том, что демон должен иметь возможность возобновить работу после перезагрузки. Это означает, что он не может просто обнаружить смерть процесса, потеряв соединение с сокетом или что-то в этом роде. Требование от процессов периодического обновления соединения с демоном может сработать, хотя это усложнит процессы. Я ищу что-то, что ядро ​​​​управляет за меня, а демон просто проверяет это (например, время запуска процесса). - person Petr; 25.11.2013
comment
@PetrPudlák Да, ну, каждое дополнительное требование, скорее всего, сделает решение немного сложнее ... Это вполне нормально. - person twalberg; 25.11.2013