2012-08-23 12 views
29

ich mehrere Instanzen eines Arbeitnehmers in dieser Antwort, wie leite: Starting multiple upstart instances automaticallyNeustarten Upstart Instanz verarbeitet

Frage: Kann ich alle Instanzen auf einmal neu gestartet werden?

Zu meinen Arbeitern beginnen ich tun kann:

initctl my-Arbeiter

starten Was mir dann erlaubt, zu tun:

initctl Status Arbeiter N = 1 Arbeiter (1) Start/Betrieb, Prozess 551

initctl Status Arbeiter N = 2 Arbeiter (2) Start/Laufen, Prozess 552

Gibt es eine Möglichkeit, so etwas zu tun:

initctl my-Arbeiter neu starten

ich alle Instanzen in der Lage sein möchten, neu zu starten, ohne dass zu wissen, wie viele laufen.

Hier ist meine my-workers.conf

start on stopped cloud-init 
stop on shutdown 

env NUM_WORKERS=4 

script 
    for i in `seq 1 $NUM_WORKERS` 
    do 
     start worker N=$i 
    done 
end script 

Und worker.conf

stop on shutdown 

chdir /path/to/current 

respawn 

instance $N 

script 
    exec su -c "/home/worker/.rvm/bin/rvm-shell -c 'bundle exec rake work 2>&1 >> /var/log/worker-$N.log'" worker 
end script 

Antwort

35

In worker.conf Sie müssen nur diese Zeile ändern:

stop on shutdown 

An:

stop on stopping my-workers 

Und my-workers.conf ändern pre-start statt script zu verwenden:

pre-start script 
    for i in `seq 1 $NUM_WORKERS` 
    do 
    start worker N=$i 
    done 
end script 

Jetzt my-workers wird Zustand halten: Da die Arbeit in pre-start geschieht, der my-workers Hauptprozess nicht existieren und so wird nicht verlassen. stop on stopping my-workers bewirkt, dass die Arbeiter zu stoppen, wenn my-workers gestoppt wird. Dann wird es natürlich, wenn es wieder anläuft, die Arbeiter wieder starten.

(FYI, stop on shutdown tut nichts, da shutdown kein Systemereignis ist.man upstart-events für alle definierten Ereignisse), so sollten Sie auch stop on runlevel [06]

+4

nahm mich eine Weile, um zu verstehen, was du meinst, aber wenn ich es bekommen habe ... * Geist geblasen * – Evgeny

+0

@Evgeny hier gilt das gleiche, haha. Wenn du wie ich, und wahrscheinlich Evgeny, hast du nur 5 Minuten damit verbracht, zu verstehen, was hier los ist: im Grunde erstellt meine-workers.conf mehrere Upstart-Skripte und Exits, aber jede worker.conf hat jetzt die Zeile 'stop on stop my workers ' Wenn Sie also versuchen, den bereits beendeten My-Workers-Prozess zu stoppen, werden die Arbeiter immer noch darauf hören und sterben. Das "Neustarten" meiner Worker, obwohl es vorher noch nicht wirklich ausgeführt wurde, hat den Effekt, dass die Worker getötet (gestoppt) werden und das Vorstart-Skript (Start) erneut ausgeführt wird, wodurch sie erneut gestartet werden. – Mahn

+1

Es funktioniert, aber es ist ziemlich hackish. 'Service my-workers start' wird tatsächlich hängen. In der Upstart-Dokumentation heißt es: 'Alle Job-Dateien müssen entweder eine Exec- oder eine Skript-Zeilengruppe haben.' Vor-Start-Skript und Post-Stop-Skript - Es wird nicht erwartet, dass sie den Prozess starten, in der Tat können sie nicht. ' Vielleicht ist es besser, einfach einen anderen Job zum Stoppen oder Neustarten von Arbeitern zu erstellen. –

7

meiner Arbeiter ändern versuchte ich es mit dem Beispiel von oben und SpamapS beantworten, die ich erhielt:

init: my-workers pre-start process (22955) terminated with status 127 

In /var/log/upstart/my-workers.log fand ich das Problem:

/proc/self/fd/9: 6: /proc/self/fd/9: end: not found 

die end der for-Schleife in my-workers.conf schien falsche Syntax zu sein. I ersetzt

script 
    for i in `seq 1 $NUM_WORKERS` 
    do 
     start worker N=$i 
    done 
    end 
end script 

mit

script 
    for i in `seq 1 $NUM_WORKERS` 
    do 
    start worker N=$i 
    done 
end script 

und es funktionierte!

+1

Großartig, arbeitete für mich! –

1

Betrachten wir zum worker.conf ein weiteres Ereignis hinzu:

stop on shutdown or workers-stop 

Dann können Sie von der Kommandozeile aufrufen

sudo initctl emit workers-stop 

können Sie ähnliche Veranstaltung hinzufügen Arbeiter zu starten. Um das Neustarten aller Arbeiter zu erreichen, erstellen Sie eine Aufgabe, die Arbeiter ausgibt - Stopp und dann Arbeiter - Ereignisse starten.

0

Im Wesentlichen müssen Sie ein Verfahren haben, das viele stop und start Befehle für alle N=1, N=2 Kombination ausführt.

Ein einfacher Weg, dies zu tun ist ein paar Bash for Schleifen innerhalb einer exec script Zeilengruppe. Wenn die Prozesse jedoch einige Zeit zum Stoppen benötigen (z. B. weil sie an etwas arbeiten und sie annehmen, nachdem sie ihren aktuellen Job bearbeitet haben), ist dies ineffizient, da Sie warten müssen, bis das nächste Signal gesendet wird .

Deshalb baute ich einen Upstart-Skript, das sie parallel hält an https://github.com/elifesciences/builder-base-formula/blob/master/elife/config/etc-init-multiple-processes-parallel.conf

Das Skript von Salz kompiliert wird als Eingabe eine Karte von Prozessnamen, wie viele es sind. Hier ist ein Beispiel Ergebnis:

description "(Re)starts all instances, in parallel" 
# http://upstart.ubuntu.com/cookbook/#start-on 
start on (local-filesystems and net-device-up IFACE!=lo) 
task 
script 
    timeout=300 
    echo "--------" 

    echo "Current status of 5 elife-bot-worker processes" 
    echo "Now is" $(date -Iseconds) 
    for i in `seq 1 5` 
    do 
     status elife-bot-worker ID=$i || true 
    done 
    echo "Stopping asynchronously 5 elife-bot-worker processes" 
    echo "Now is" $(date -Iseconds) 
    for i in `seq 1 5` 
    do 
     (stop elife-bot-worker ID=$i &) || true 
    done 

    for i in `seq 1 5` 
    do 
     echo "Waiting for elife-bot-worker $i to stop" 
     echo "Now is" $(date -Iseconds) 
     counter=0 
     while true 
     do 
      if [ "$counter" -gt "$timeout" ] 
      then 
       echo "It shouldn't take more than $timeout seconds to kill all the elife-bot-worker processes" 
       exit 1 
      fi 
      status elife-bot-worker ID=$i 2>&1 | grep "Unknown instance" && break 
      sleep 1 
      counter=$((counter + 1)) 
     done 
    done 
    echo "Stopped all elife-bot-worker processes" 

    echo "Starting 5 elife-bot-worker processes" 
    for i in `seq 1 5` 
    do 
     start elife-bot-worker ID=$i 
    done 
    echo "Started 5 elife-bot-worker processes" 

end script