如何編寫一個保證運行的 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
永遠不會達到停止狀態,因此無論 jobA 或 jobB 是否重新啟動,它都不會重新運行。
這個解決方案似乎有效,但我歡迎任何批評或改進。
答案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]
我在 lubuntu 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 時,作業將被視為正在運行。
使用任務正是使作業執行兩次的原因(例如,如果您重新啟動了作業),因此我們將其排除在外。