Ваше задание upstart необходимо настроить так, чтобы upstart точно знал, сколько раз оно разветвляется. И он может только разветвляться один или два раза, не более.
В Unix Land есть два ключевых системных вызова, которые облегчают запуск программ: fork
и exec
.
fork
копирует процесс, который его вызывает. Один процесс вызывает fork
, и он возвращает управление двум процессам. Каждый процесс должен определить, какой он (родительский или дочерний) из значения, возвращаемого fork (подробности см. На странице man).
exec
запускает новую программу, заменяя процесс, вызвавший exec
.
Когда вы просто запускаете команду в оболочке, из-под оболочки оболочка вызывает fork
, чтобы создать новый процесс с собственным идентификатором, и этот новый процесс (после некоторой настройки) немедленно вызывает exec
, чтобы запустить Команда, которую вы ввели. Именно так запускается большинство программ, будь то оболочка или ваш оконный менеджер или что-то еще.
См. Функцию system в C, которая также имеет варианты в большинстве языков сценариев.
Если вы думаете, что это неэффективно, вы, вероятно, правы. Это то, как это было сделано в Unix с давних времен, и, очевидно, никто не может изменить это. Одна из причин заключается в том, что существует множество вещей, которые не заменены на exec
, включая (иногда) открытые файлы и идентификаторы пользователя и группы процесса.
Другая причина заключается в том, что МНОГО усилий было потрачено на повышение эффективности fork
, и они на самом деле сделали это довольно хорошо - в современных Unix-системах (с помощью ЦП) fork
фактически копирует очень мало процесса. Я думаю, никто не хочет выбросить всю эту работу.
И, (пауза для эффекта) pid процессов.
Для демонстрации:
mslade@mickpc:~$ echo $$
3652
mslade@mickpc:~$ bash
mslade@mickpc:~$ echo $$
6545
mslade@mickpc:~$ exec bash
mslade@mickpc:~$ echo $$
6545
mslade@mickpc:~$ exit
exit
mslade@mickpc:~$ echo $$
3652
Большинство популярных языков имеют разновидности fork и exec, включая shell, C, perl, ruby и python. Но не Java.
Итак, учитывая все это, вам нужно сделать так, чтобы ваша работа выскочки работала так, чтобы она разветвлялась столько же раз, сколько думает выскочка.
Строка exec
в ruby-local-exec на самом деле хорошая вещь, она предотвращает форк. Также load
не запускает новый процесс, он просто загружает код в существующий интерпретатор ruby и запускает его.
Однако ваш сценарий оболочки разветвляется в этой строке:
$APP_ROOT/bin/unicorn -c $APP_ROOT/config/unicorn.rb -E production # >> /tmp/upstart.log 2>&1
, чтобы предотвратить это, вы можете просто изменить его на
exec $APP_ROOT/bin/unicorn -c $APP_ROOT/config/unicorn.rb -E production # >> /tmp/upstart.log 2>&1
Если вы сделаете это, единорог AFAICT вообще не должен разветвляться, и вам не нужно будет говорить выскочке, чтобы ожидать разветвления.