как мне заставить процесс перезагрузить себя в Linux?

У меня есть служба, скажем, foo, написанная на C++, которая работает от имени пользователя root. Есть обычный скрипт, /etc/init.d/foo start|stop|restart.

В определенное время foo нужно перезагрузить себя. Обычно после завершения обновления. Но делать такие вещи, как:

system("/etc/init.d/foo restart")

не работает, поскольку, как только перезагрузка убивает foo, очевидно, что вызов system() также уничтожается, а сценарий перезагрузки никогда не выполняется до конца.

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

Спасибо!


person Stéphane    schedule 09.03.2009    source источник


Ответы (9)


Вы уже рассматривали семью exec[*]? Вот один -- execve.

person dirkgently    schedule 09.03.2009
comment
Спасибо. Другой трюк, который мне пришлось исследовать, заключался в вызове fcntl() для установки FD_CLOEXEC на прослушивающем порте сервера. В противном случае приложение exec'd() унаследовало бы исходный сокет и вызвало бы у меня огорчение. - person Stéphane; 28.04.2009

Вы можете поместить его в inittab и позволить init беспокоиться о перезапуске процесса, когда он по какой-либо причине завершается. Это также позаботится об автоматических перезапусках, если ваш процесс произойдет сбой или вызов assert() или иное неожиданное завершение.

Затем, чтобы обработать ваш вариант использования, процесс просто завершится.

person Ori Pessach    schedule 09.03.2009

как насчет fork(), за которым следует exec()?

person Eric Petroelje    schedule 09.03.2009
comment
В этом случае не нужно разветвляться, просто exec(). - person Juliano; 10.03.2009

Рассмотрите возможность реализации

/etc/init.d/foo reload

для вашего демона (довольно стандартно, судя по grep моей коробки Debian).

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

Если процесс знает, что ему нужно перезагрузиться, он может просто подать сигнал сам себе.

Если вам действительно нужно перезагрузиться, чтобы получить новые библиотеки, используйте exec*()

person timday    schedule 09.03.2009

Объединив два ответа, используйте fork-exec.

person Adam Rosenfield    schedule 09.03.2009

Чтобы добавить к тому, что уже сказал Ори, некоторые дистрибутивы Linux все еще используют initab, но Ubuntu и, возможно, другие перешли на /etc/event.d. Вы помещаете туда файл (копируете и редактируете один из существующих), затем запускаете демон с помощью «sudo start ssh_tunnel» или как там называется ваш файл.

Затем, когда вам понадобится перезапустить его, вы можете просто убить его сигналом, и система перезапустит его. Или он может сам решить, что пришло время перезапуститься, вызвав "exit(0);" или что-то еще.

person Paul Tomblin    schedule 09.03.2009

exec*() сам по себе в исходной командной строке должен помочь. Вы, вероятно, можете опустить разветвление, потому что тогда у вас есть две запущенные копии, которые вам не нужны, а исходная копия должна выйти.

Но также посмотрите на inittab и event.d в зависимости от вашего дистрибутива, чтобы увидеть, будет ли он делать то, что вам нужно, лучше.

person Rob K    schedule 09.03.2009

Третьей возможностью, которую предложили Ори и Пол, было бы использование daemontools. Он более портативный, хотя и менее доступный. Вы создаете скрипт с именем /service/foo/run, и daemontools будет перезапускать ваш сервис всякий раз, когда он выходит.

http://cr.yp.to/daemontools.html

person bstpierre    schedule 10.03.2009

Посмотрите справочную страницу для inittab.

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

При правильной настройке все, что вам нужно сделать, это выйти, и система автоматически позаботится о перезапуске (возрождении) для вас.

person Martin York    schedule 09.03.2009