2012-09-26 10 views
8

Wir haben eine benutzerdefinierte C++ - Daemon-Anwendung, die einmal gabelt. Deshalb haben wir uns auf Ubuntu 12.04 tun dies in unserem Upstart-Skript, und es funktioniert perfekt:Wie setze ich die Umgebungsvariable im Vorstart im Upstart Script?

expect fork 
exec /path/to/the/app 

aber jetzt müssen wir in einem Argument zu unserer App zu übergeben, die die Anzahl der CPUs auf dem Computer enthält, auf dem es Läufe:

cat /proc/cpuinfo | grep processor | wc -l 

unser erster Versuch war:

expect fork 
exec /path/to/the/app -t `cat /proc/cpuinfo | grep processor | wc -l` 

Während, dass unser App mit dem richtigen -t Wert beginnt, Upstart den falschen pid Wert verfolgt, gehe davon aus ich, weil jene Katze , grep & wc befiehlt alle Startprozesse in exec vor unserer App.

Ich habe das auch versucht, und sogar es funktioniert nicht, ich denke, weil die Einstellung einer env var einen Prozess ausführt? Upstart verfolgt noch die falsche pid:

expect fork 
script 
    NUM_CORES=32 
    /path/to/the/app -t $NUM_CORES 
end script 

Ich habe auch dies in einer env Strophe versuchte dabei aber anscheinend Befehle diejenigen nicht laufen:

env num_cores=`cat /proc/cpuinfo | grep processor | wc -l` 

auch versucht, dies in vor dem Start zu tun, aber env vars dort eingestellt hat keine Werte in der exec Strophe:

pre-start 
    NUM_CORES=32 
end script 

Jede Idee, wie man diese richtig eingestellt NUM_CORES, und immer noch Upstart die richtige pid für unsere App, die Gabeln einmal zu verfolgen?

Antwort

16

Es ist peinlich. Die empfohlene Methode besteht darin, in der Zeilengruppe vor dem Start eine env-Datei zu schreiben und sie dann in der Skriptzeilengruppe anzugeben. Es ist lächerlich, ich weiß.

expect fork 

pre-start script 
    exec >"/tmp/$UPSTART_JOB" 
    echo "NUM_CORES=$(cat /proc/cpuinfo | grep processor | wc -l)" 
end script 

script 
    . "/tmp/$UPSTART_JOB" 
    /path/to/app -t "$NUM_CORES" 
end script 

post-start script 
    rm -f "/tmp/$UPSTART_JOB" 
end script 

Ich verwende die exec Linie in der Pre-Start, weil ich in der Regel mehrere env Variablen haben, und ich will nicht die Umleitung Code wiederholen.

Dies funktioniert nur, weil die '. 'Befehl ist ein eingebauter Bindestrich und somit wird kein Prozess erzeugt.

+0

super nützlich! Eine Sache: Ich denke, Sie müssen immer noch "exec/path/to/app" innerhalb des Skriptblocks verwenden, wenn Sie das vorher für das Pid-Tracking benötigten. Nachdem ich "exec" hinzugefügt hatte, funktionierte das wunderbar für mich. –

+0

@ CodyA.Ray, das vollständig von dem Verzweigungsverhalten des Dienstes abhängt, der gestartet wird. In unserem Fall war 'expect daemon' möglicherweise angemessen. – mpm

0

würde ich

export NUM_CORES 

nachdem sie einen Wert in "script" zuweisen hinzuzufügen. Ich erinnere mich, dass ein/bin/sh, der mit einer Nicht-Bash-Shell verknüpft ist, Skripte ausführen könnte, sodass ich nur Bash-Konstrukte vermeiden würde.

Re: unter Verwendung der Zeilengruppe "env" übergibt es Werte buchstäblich und verarbeitet sie nicht mit Shell-Konventionen.

2

Nach zram-config Emporkömmling config:

script 
    NUM_CORES=$(grep -c ^processor /proc/cpuinfo | sed 's/^0$/1/') 
    /path/to/the/app -t $NUM_CORES 
end script 
+0

Das Problem dabei ist, dass '$()' einen Kindprozeß abzweigt (und dann verursacht die Pipe einen anderen Fork), was das Fork-Tracking verwirren kann.Wenn Sie mehr als zweimal vor Ihrem eigentlichen Daemon forken, kann der ältere Emporkömmling den Daemon-Prozess nicht verfolgen und der Respawn funktioniert dann nicht richtig. Dies funktioniert für zram-config, weil das nur einmal ausgeführt wird und kein Respawn benötigt wird, aber es ist nicht universal. :) Deshalb ist @ mpm's Antwort notwendig. – dannysauer