Wie erstelle ich einen Upstart-Job mit einmaliger Ausführung, der garantiert abgeschlossen wird, bevor zwei andere Jobs beginnen?

Wie erstelle ich einen Upstart-Job mit einmaliger Ausführung, der garantiert abgeschlossen wird, bevor zwei andere Jobs beginnen?

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-waitsobald modify-fileses im laufenden Zustand im Leerlauf ist. Diese normal exitZeile berücksichtigt die Möglichkeit, dass es während des unendlichen Schlafs beendet wird. Wir brauchen die taskZeile, 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-filesder 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.confwie 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

firstJobDer Start ist „ myEventgeneriert von“ mainJobund 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 mainJobbei 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.

verwandte Informationen