Wie schreibt man eine Upstart-Aufgabe, die garantiert ausgeführt wird?nur einmalnach jedem Start, wird aber auch garantiert bis zum Abschluss ausgeführt, bevor einer von mindestens zwei anderen Jobs gestartet wird. Ich möchte die Upstart-Init-Dateien für diese beiden anderen Jobs nicht ändern, da sie mir nicht gehören. Ein Neustart eines dieser beiden anderen Jobs sollte nicht dazu führen, dass die gewünschte Aufgabe erneut ausgeführt wird.
Die Situation ist, dass die gewünschte Aufgabe einige Änderungen an einigen Dateien im lokalen Dateisystem vornehmen muss, die beide anderen Jobs benötigen.
Ich bin völlig neu bei Upstart und finde, dass die Lernkurve steiler ist als erwartet, also eine Ausbildung überWarumDie Ergebnisse der Lösung werden genauso wertvoll sein wie die Lösung selbst.
Antwort1
Ich glaube, ich habe eine Antwort auf meine eigene Frage, dieCameronNemos TeillösungUndMark Russells Antwortauf eine verwandte, aber etwas andere Frage.
Es werden zwei Upstart-Konfigurationsdateien benötigt. Die erste ist ein Job, der startet, sobald das lokale Dateisystem verfügbar ist, die gewünschten Dateiänderungen als Pre-Start-Skript durchführt und dann für immer im laufenden Zustand im Leerlauf verbleibt:
# 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
Die zweite Konfigurationsdatei ist eine Upstart-Aufgabe, die den Start aller anderen Jobs verzögert, die möglicherweise von den Dateien abhängen, die wir ändern möchten. Sie erstellt eine Instanz von sich selbst pro abhängigem Job:
# 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 beendet alle Instanzen von , modify-files-wait
sobald modify-files
es im laufenden Zustand im Leerlauf ist. Diese normal exit
Zeile berücksichtigt die Möglichkeit, dass es während des unendlichen Schlafs beendet wird. Wir brauchen die task
Zeile, um jobA und joB zu blockieren, bis der gestoppte Zustand erreicht ist. Die Instanz, die zuerst ausgeführt wird, wird gestartet modify-files
, wenn sie nicht bereits gestartet wurde.
Da modify-files
der Stoppzustand nie erreicht wird, wird der Job nie erneut ausgeführt, unabhängig davon, ob JobA oder JobB neu gestartet werden.
Diese Lösung scheint zu funktionieren, aber ich freue mich über jede Kritik und Verbesserung.
Antwort2
Sie können einen einfachen Task-Job definieren, der bei einem Ereignis Ihrer Wahl startet, Ihr Skript ausführt und am Ende ein Ereignis ausgibt, um die anderen beiden Jobs zu starten.
Zum Beispiel:
# 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
Um das Upstart-Skript der anderen beiden Jobs nicht zu verändern, sollten SieOverride-DateienDamit können Sie die Art und Weise ändern, in der ein Job gestartet und gestoppt wird, indem Sie die Start- und Stoppbedingungen ändern.
Nach meinen Beispielen habe ich ein einfaches firstJob.conf
wie dieses erstellt:
# 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
Und dann überschreibe ich den Start unter der Bedingung, dass eine Override-Datei erstellt wird:
echo "start on myEvent" > /etc/init/firstJob.override
firstJob
Der Start ist „ myEvent
generiert von“ mainJob
und der Stopp ist „generiert von“ .runlevel [016]
Ich habe diese Jobs auf Lubuntu 12.04 getestet und nach dem Neustart Folgendes gefunden /var/log/upstart/firstJob.log
:
(startTask) firstJob -- myEvent
Sie sollten überprüfen, ob für den Start der „anderen beiden Jobs“ bestimmte Ereignisbedingungen erforderlich sind, und sicherstellen, dass sie mainJob
bei diesen Ereignissen gestartet werden.
Antwort3
start on starting jobA or starting jobB
instance $JOB
pre-start exec /path/to/script
Das Startbit verhindert, dass die Jobs in ihrem Lebenszyklus fortfahren, bis dieser Job abgeschlossen ist.
Das Instanzbit dient dazu, dass beide Startereignisse (für JobA und JobB) verhindert werden und nicht nur eines, wie dies der Fall wäre, wenn Sie keine Instanzstrophe hätten.
Die Verwendung eines vor dem Start ausgeführten Execs/Skripts (anstelle eines regulären Execs/Skripts) dient dazu, dass der Job nach Abschluss des Skripts/ausgeführten Befehls noch als ausgeführt betrachtet wird, während bei einem herkömmlichen Exec/Skript der Job als gestoppt betrachtet wird, wenn das Exec/Skript beendet wird.
Die Verwendung von „task“ würde genau dazu führen, dass der Job zweimal ausgeführt wird (z. B. wenn Ihre Jobs neu gestartet werden). Deshalb lassen wir es weg.