Umgebungsvariable wird beim Start mit Upstart (Ubuntu) nicht von der App erfasst

7

Wie wird eine neue Umgebungsvariable systemweit erfasst, ohne den Server neu zu starten?

Da es sich um einen Ubuntu 11.x-Server handelt, verwende ich Upstart, um Prozesse zu starten / neu zu starten.

Ich habe / etc / environment eine neue Umgebungsvariable hinzugefügt, die von einem der Prozesse meiner App erfasst werden muss.

Wenn ich den Prozess direkt von meiner Shell aus starte, wird die Variable abgerufen und alles ist in Ordnung (ich habe bereits / etc / environment für meine Sitzung bezogen). Wenn ich den Prozess jedoch mit seinem Upstart-Dienstnamen starte / neu starte, wird die Variable nicht angezeigt.

 sudo start app-name

Ich bin mir ziemlich sicher, dass beim Neustart des Servers die neue Variable übernommen wird, aber ich möchte versuchen, dies zu vermeiden. Ich habe einige andere Live-Prozesse darauf ausgeführt, die ich nach Möglichkeit vermeiden möchte, zu unterbrechen.

Geuis
quelle

Antworten:

3

Diese Frage scheint viele Unterfragen zum Umgang mit Umgebungsvariablen in einem Upstart-Skript zu enthalten. Daher dachte ich, ich würde ein paar Dinge teilen, die ich tue, um meine Umgebung für Upstart und Cron zu handhaben und zu testen.

Das Erste, was Sie über Upstart und dergleichen wissen sollten, ist, dass es nicht dieselbe Umgebung wie Ihr aktives Terminal hat. So etwas wie:

$ export FOO=bar
$ start upstart-name

funktioniert nicht, da upstart-namedas FOOgerade in die aktuelle Shell exportierte nicht angezeigt wird, da Upstart in einer sauberen Umgebung ausgeführt wird.

Sie können die saubere Umgebung, in der Upstart (und Cron) ausgeführt werden, mit dieser praktischen Methode nachahmen, die ich vor vielen Monden aus einer anderen Antwort herausgeschnitten habe:

# makes the current shell have an environment like cron or upstart
# http://stackoverflow.com/a/2546509/5006
function cronenv() {
  cron_env+="HOME=$HOME\n"
  cron_env+="LOGNAME=$LOGNAME\n"
  cron_env+="PATH=/usr/bin:/bin\n"
  cron_env+="SHELL=/bin/sh\n"
  cron_env+="PWD=$PWD\n"

  if [[ -n $LC_ALL ]]; then
    cron_env+="LC_ALL=$LC_ALL\n"
  fi

  env - `echo -e $cron_env` /bin/sh
}

Geben Sie das einfach in Ihr .bash_profileoder ähnliches ein und Sie können Befehle so ausführen, wie Upstart sie ausführen würde:

$ cronenv
$ some/big/command --to --run --as --upstart

Lassen Sie uns nun tatsächlich eine gemeinsam genutzte Umgebung auf unserer Box einrichten. Dazu fügen wir unsere Umgebungsvariablen ein /etc/profile.d/environ.sh

# /etc/profile.d/environ.sh
export FOO=bar

und dann das in unserem Upstart-Skript beschaffen:

script
  # source our common environment file
  . /etc/profile.d/environ.sh
  exec some/big/command --to --run --as --upstart
end script

Jetzt können wir unsere Umgebung auf jeder Shell und jedem Upstart-Skript "sehen", aus dem unsere gemeinsame Datei stammt (standardmäßig bezieht ssh unter Ubuntu alles von /etc/profile.d). Yay!

Jaymon
quelle
2

Fügen Sie die Zeilengruppe env in Ihre Jobbeschreibungsdatei ein.

http://upstart.ubuntu.com/wiki/Stanzas#env

env PIDFILE=/var/run/myprocess.pid

Oder Wasauchimmer. Es ist alles in der Dokumentation.

Tom O'Connor
quelle
Danke, ich kann das total zum Laufen bringen. Ich würde gerne noch weiter gehen und es global und dauerhaft machen. Ich setze eine Variable, mit der mehrere Prozesse bestimmen können, ob sie sich in einer Entwicklungs- oder Produktionsumgebung befinden. Die conf-Datei funktioniert vorerst, da ich auf einem Mac entwickle, aber irgendwann wird eine Integrationsumgebung mit Ubuntu ausgeführt, und auf jedem Server werden mehrere separate App-Prozesse ausgeführt. Es wäre für sie alle bequem, sich nicht auf die Confs zu verlassen.
Geuis
Was? Sie möchten Upstart verwenden. Gut. Sie müssen Dinge in der Konfiguration des Upstarts angeben, damit dieser weiß, wie die Prozesse gestartet werden. Entweder das, oder Sie erstellen ein Wrapper-Skript, das Umgebungsvariablen festlegt und exportiert (chaotisch). Oder ändern Sie das Standard-Bash-Profil, damit sie immer festgelegt und exportiert werden (wahnsinnig chaotisch).
Tom O'Connor
Der richtige Weg, dies zu tun, besteht darin, Puppet zum Verwalten Ihrer verschiedenen Umgebungen zu verwenden. Anschließend kann Puppet die verschiedenen Konfigurationsdateien auf vielen Servern ohne großen Aufwand verwalten.
Tom O'Connor
Tom, ich habe ein seltsames Problem. Mit env kann ich keine benutzerdefinierten Umgebungsvariablen festlegen. Wenn ich systemdefinierte Variablen einstelle, werden diese von der App gelesen. Aber meine eigenen sind es nicht. Zum Beispiel setze ich in der conf ohne Anführungszeichen "env DISPLAY = foo" und DISPLAY wird mit dem Wert foo aufgenommen. Aber wenn ich "env TESTENV = foo" setze, wird die Variable TESTENV nicht einmal erkannt.
Geuis
1
Ich werde rc.local nach ein bisschen Schlaf ausprobieren. Danke für die Setgid-Tipps. Ich habe auch über Sudo gezögert, aber genau das tun die meisten Beispiele, die ich gesehen habe, und es funktioniert. Für meine vorhandenen Apps funktioniert es schon eine Weile ziemlich zuverlässig, aber ich werde in Ihren Link schauen und sehen, wie es sicherer gemacht werden kann. Ich schätze Ihre Hilfe heute Abend sehr und hoffe, dass ich den Rest herausfinden kann.
Geuis
1

Ich hatte das gleiche Problem. Mein Startskript funktionierte gut über die Befehlszeile, aber nicht über das Startskript.

Ich musste mein . /home/username/.bashrcin meinem Upstart-Skript einfach als Quelle verwenden , damit es mit allen richtigen Umgebungsvariablen funktioniert.

script

  cd /home/me
  . /home/me/.bashrc

  ~/www/app/bin/server.production
end script
chovy
quelle
Dies funktioniert bei mir nicht (Ubuntu Server 14.04.1). Ich erhalte keine Fehlermeldung, wenn ich /home/<user>/.bashrc innerhalb des Upstart-Skripts beschaffe, aber die env-Variablen bleiben beim nächsten Befehl (der App / dem Dienst, der gestartet wird) nicht erhalten.
Odigity