Как создать однократно выполняемое задание Upstart, которое гарантированно завершится до начала двух других заданий?

Как создать однократно выполняемое задание Upstart, которое гарантированно завершится до начала двух других заданий?

Как написать задачу 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 как раз и заставит задание запуститься дважды (например, если имеющиеся у вас задания перезапускаются), поэтому мы его опускаем.

Связанный контент