Как написать задачу Upstart, которая гарантированно запустится?только один разпосле каждого запуска, но также гарантированно завершится до того, как начнется выполнение хотя бы одного из двух других заданий. Я не хочу изменять файлы инициализации Upstart для этих двух других заданий, поскольку они мне не принадлежат. Перезапуск любого из этих двух других заданий не должен приводить к повторному запуску желаемой задачи.
Ситуация такова, что требуемая задача должна внести некоторые изменения в некоторые файлы в локальной файловой системе, которые потребуются обоим другим заданиям.
Я новичок в Upstart и нахожу, что кривая обучения оказалась более крутой, чем я ожидал, поэтому я хочу получить образование попочемуРезультат работы решения будет столь же ценным, как и само решение.
решение1
Я считаю, что у меня есть ответ на мой собственный вопрос, который используетЧастичное решение от CameronNemoиОтвет Марка Расселана связанный, но несколько иной вопрос.
Требуется два файла конфигурации Upstart. Первый — это задание, которое запускается сразу после того, как становится доступной локальная файловая система, выполняет требуемые изменения файлов в качестве сценария предварительного запуска, а затем бездействует в рабочем состоянии вечно:
# modify-files - Single-execution file modification job
start on local-filesystems
console log
pre-start script
echo "$(date --rfc-3339=ns) $(hostname) $UPSTART_JOB"
exec /path/to/your/script
end script
Второй файл конфигурации — это задача Upstart, которая задерживает запуск всех других заданий, которые могут зависеть от файлов, которые мы пытаемся изменить. Он создает один экземпляр себя на каждое зависимое задание:
# modify-files-wait - Helper task for modify-files
start on (starting jobA or jobB)
stop on (started modify-files or stopped modify-files)
instance $JOB
console log
normal exit 0 2
task
script
echo "$(date --rfc-3339=ns) $(hostname) $UPSTART_JOB ($UPSTART_INSTANCE)"
status modify-files | grep -q "start/running" && exit 0
start modify-files || true
sleep infinity
end script
Upstart убьет все экземпляры, которые modify-files-wait
когда-либо modify-files
простаивали в состоянии выполнения. Эта normal exit
строка учитывает возможность быть убитым во время бесконечного сна. Нам нужна строка, task
чтобы заблокировать jobA и joB до тех пор, пока не будет достигнуто состояние остановки. Какой бы экземпляр ни запустился первым, он запустится modify-files
, если он еще не был запущен.
Поскольку modify-files
он никогда не достигает состояния остановки, он никогда не будет запущен снова, независимо от перезапуска задания A или задания B.
Похоже, это решение работает, но я приветствую любую критику или улучшения.
решение2
Вы можете определить простую задачу, которая запускается при наступлении выбранного вами события, запускает ваш скрипт и в конце генерирует событие для запуска двух других задач.
Например:
# mainJob -
#
# This service emit myEvent to run firstJob
description "emit myEvent to run firstJob"
start on runlevel [2345]
task
console log
script
echo "(startTask) $UPSTART_JOB -- $UPSTART_EVENTS"
exec /path/to/your/script
initctl emit -n myEvent
end script
Чтобы не изменять скрипт upstart двух других заданий, вам следуетпереопределять файлыкоторые позволяют вам изменять способ запуска и остановки задания путем изменения условий запуска и остановки.
Следуя своим примерам, я создал firstJob.conf
вот такой простой пример:
# firstJob -
#
# This service print environment variable
description "print environment variable"
start on runlevel [2345]
stop on runlevel [016]
task
console log
script
if [ "$RUNLEVEL" = "0" -o "$RUNLEVEL" = "1" -o "$RUNLEVEL" = "6" ]; then
exec echo "(stopTask) $UPSTART_JOB -- $UPSTART_EVENTS"
else
exec echo "(startTask) $UPSTART_JOB -- $UPSTART_EVENTS"
fi
end script
А затем я переопределяю условие запуска, создавая файл переопределения:
echo "start on myEvent" > /etc/init/firstJob.override
Так что firstJob
начнём с myEvent
созданного mainJob
и остановимся наrunlevel [016]
Я протестировал эти задания на Ubuntu 12.04 и после перезагрузки обнаружил /var/log/upstart/firstJob.log
:
(startTask) firstJob -- myEvent
Вам следует проверить, требуются ли для запуска «двух других заданий» определенные условия события, и убедиться, что они mainJob
запускаются при этих событиях.
решение3
start on starting jobA or starting jobB
instance $JOB
pre-start exec /path/to/script
Начальный бит не позволяет заданиям двигаться дальше по своему жизненному циклу, пока данное задание не будет завершено.
Бит экземпляра нужен для того, чтобы оба начальных события (для jobA и jobB) были заблокированы, а не только одно, как было бы в случае отсутствия строфы экземпляра.
Использование предварительного запуска exec/script (вместо обычного exec/script) позволяет после завершения выполнения скрипта/выполняемой команды по-прежнему считать задание выполняющимся, тогда как при использовании традиционного exec/script задание считается остановленным при завершении exec/script.
Использование task как раз и заставит задание запуститься дважды (например, если имеющиеся у вас задания перезапускаются), поэтому мы его опускаем.