Wenn man in der Lage sein will, Webanwendungen in der Entwicklung und in der Produktion effektiv zu verwalten, muss man die Umgebungsvariablen verstehen.

Das war nicht immer der Fall. Noch vor ein paar Jahren hat kaum jemand seine Rails-Apps mit Umgebungsvariablen konfiguriert. Aber dann kam Heroku.

Heroku führte Entwickler in den 12-Faktoren-App-Ansatz ein. In ihrem 12-Factor-App-Manifest legen sie viele ihrer Best Practices für die Erstellung von Anwendungen dar, die einfach zu implementieren sind. Der Abschnitt über Umgebungsvariablen war besonders einflussreich.

Die Zwölf-Faktoren-App speichert die Konfiguration in Umgebungsvariablen (oft abgekürzt als env vars oder env). Umgebungsvariablen lassen sich leicht zwischen Deployments ändern, ohne dass der Code geändert werden muss; im Gegensatz zu Konfigurationsdateien ist die Wahrscheinlichkeit gering, dass sie versehentlich in das Code-Repository eingecheckt werden; und im Gegensatz zu benutzerdefinierten Konfigurationsdateien oder anderen Konfigurationsmechanismen wie den Java-Systemeigenschaften sind sie ein sprach- und betriebssystemunabhängiger Standard.

Mehr Rubyisten als je zuvor verwenden Umgebungsvariablen. Aber oft auf eine Art und Weise, die mit der Ladung zu tun hat. Wir benutzen diese Dinge, ohne wirklich zu verstehen, wie sie funktionieren.

Dieser Beitrag wird dir zeigen, wie Umgebungsvariablen wirklich funktionieren – und vielleicht noch wichtiger, wie sie NICHT funktionieren. Wir werden auch einige der gängigsten Möglichkeiten zur Verwaltung von Umgebungsvariablen in Ihren Rails-Anwendungen untersuchen. Fangen wir an!

HINWEIS: Sie können hier über die Sicherung von Umgebungsvariablen lesen.

Jeder Prozess hat seinen eigenen Satz von Umgebungsvariablen

Jedes Programm, das Sie auf Ihrem Server ausführen, hat mindestens einen Prozess. Dieser Prozess erhält einen eigenen Satz von Umgebungsvariablen. Sobald er sie hat, kann nichts außerhalb des Prozesses sie ändern.

Ein verständlicher Fehler, den Anfänger machen, ist zu denken, dass Umgebungsvariablen irgendwie serverweit sind. Dienste wie Heroku erwecken den Anschein, als sei das Setzen von Umgebungsvariablen das Äquivalent zum Bearbeiten einer Konfigurationsdatei auf der Festplatte. Aber Umgebungsvariablen sind nicht wie Konfigurationsdateien.

Jedes Programm, das Sie auf Ihrem Server ausführen, erhält seinen eigenen Satz von Umgebungsvariablen, sobald Sie es starten.

Jeder Prozess hat seine eigene Umgebung. Jeder Prozess hat seine eigene Umgebung.

Umgebungsvariablen sterben mit ihrem Prozess

Haben Sie jemals eine Umgebungsvariable gesetzt, neu gebootet und festgestellt, dass sie verschwunden war? Da Umgebungsvariablen zu Prozessen gehören, bedeutet das, dass Ihre Umgebungsvariable verschwindet, sobald der Prozess beendet wird.

Sie können dies sehen, indem Sie eine Umgebungsvariable in einer IRB-Sitzung setzen, diese schließen und versuchen, in einer zweiten IRB-Sitzung auf die Variable zuzugreifen.

Wenn ein Prozess herunterfährt, gehen seine Umgebungsvariablen verloren Wenn ein Prozess herunterfährt, gehen seine Umgebungsvariablen verloren

Dies ist das gleiche Prinzip, das dazu führt, dass Umgebungsvariablen verloren gehen, wenn Ihr Server neu startet oder wenn Sie Ihre Shell verlassen. Wenn Sie wollen, dass sie über mehrere Sitzungen hinweg bestehen bleiben, müssen Sie sie in einer Art Konfigurationsdatei wie .bashrc speichern.

Ein Prozess erhält seine Umgebungsvariablen von seinem Elternteil

Jeder Prozess hat einen Elternteil. Das liegt daran, dass jedes Programm von einem anderen Programm gestartet werden muss.

Wenn Sie Ihre Bash-Shell benutzen, um vim zu starten, dann ist die Shell das Elternteil von vim. Wenn Ihre Rails-Anwendung imagemagick verwendet, um ein Bild zu identifizieren, dann ist das Elternteil des identify Programms Ihre Rails-Anwendung.

Kindprozesse erben Umgebungsvariablen von ihrem ElternteilKindprozesse erben Umgebungsvariablen von ihrem Elternteil

Im folgenden Beispiel setze ich den Wert der Umgebungsvariablen $MARCO in meinem IRB-Prozess. Dann verwende ich Backticks, um die Shell zu starten und den Wert dieser Variable auszugeben.

Da IRB der Elternprozess der Shell ist, die ich gerade erstellt habe, erhält er eine Kopie der Umgebungsvariablen $MARCO.

In Ruby gesetzte Umgebungsvariablen werden an Kindprozesse vererbtIn Ruby gesetzte Umgebungsvariablen werden an Kindprozesse vererbt

Eltern können die an ihre Kinder gesendeten Umgebungsvariablen anpassen

Standardmäßig erhält ein Kind Kopien aller Umgebungsvariablen, die sein Elternteil hat. Aber die Eltern haben die Kontrolle darüber.

Auf der Kommandozeile kann man das Programm env benutzen. Und in der Bash gibt es eine spezielle Syntax, um Umgebungsvariablen auf dem Kind zu setzen, ohne sie auf dem Elternteil zu setzen.

Verwenden Sie den env-Befehl, um Umgebungsvariablen für ein Kind zu setzen, ohne sie auf dem Elternteil zu setzenVerwenden Sie den env-Befehl, um Umgebungsvariablen für ein Kind zu setzen, ohne sie auf dem Elternteil zu setzen

Wenn Sie aus Ruby heraus shellen, können Sie auch benutzerdefinierte Umgebungsvariablen für den Kindprozess bereitstellen, ohne Ihren ENV-Hash zu vermüllen. Benutze einfach die folgende Syntax mit der system Methode:

Wie man benutzerdefinierte Umgebungsvariablen an Rubys Systemmethode übergibtWie man benutzerdefinierte Umgebungsvariablen an Rubys Systemmethode übergibt

Kinder können die Umgebungsvariablen ihrer Eltern nicht setzen

Da Kinder nur Kopien der Umgebungsvariablen ihrer Eltern erhalten, haben Änderungen, die vom Kind vorgenommen werden, keine Auswirkungen auf das Elternteil.

Umgebungsvariablen werden "per Wert" und nicht "per Referenz" übergebenUmgebungsvariablen werden „per Wert“ und nicht „per Referenz“ übergeben

Hier verwenden wir die Back-Tick-Syntax, um eine Umgebungsvariable zu setzen. Während die Variable für das Kind gesetzt wird, gelangt der neue Wert nicht zum Elternteil.

Kindprozesse können die Umgebungsvariablen ihrer Eltern nicht ändernKindprozesse können die Umgebungsvariablen ihrer Eltern nicht ändern

Änderungen an der Umgebung werden nicht zwischen laufenden Prozessen synchronisiert

Im folgenden Beispiel lasse ich zwei Kopien von IRB nebeneinander laufen. Das Hinzufügen einer Variable zur Umgebung der einen IRB-Sitzung hat keine Auswirkung auf die andere IRB-Sitzung.

Das Hinzufügen einer Umgebungsvariable zu einem Prozess ändert sie nicht für andere ProzesseDas Hinzufügen einer Umgebungsvariable zu einem Prozess ändert sie nicht für andere Prozesse

Die Shell ist nur eine Benutzeroberfläche für das System der Umgebungsvariablen.

Das System selbst ist Teil des Betriebssystemkerns. Das bedeutet, dass die Shell keine magische Macht über die Umgebungsvariablen hat. Sie muss die gleichen Regeln befolgen wie jedes andere Programm, das Sie ausführen.

Umgebungsvariablen sind NICHT dasselbe wie Shellvariablen

Eines der größten Missverständnisse entsteht dadurch, dass Shells ihre eigenen „lokalen“ Shellvariablensysteme anbieten. Die Syntax für die Verwendung lokaler Variablen ist oft die gleiche wie die für Umgebungsvariablen. Und Anfänger verwechseln die beiden oft.

Aber lokale Variablen werden nicht in die Childs kopiert.

Umgebungsvariablen sind nicht dasselbe wie ShellvariablenUmgebungsvariablen sind nicht dasselbe wie Shellvariablen

Schauen wir uns ein Beispiel an. Zuerst setze ich eine lokale Shellvariable namens MARCO. Da es sich um eine lokale Variable handelt, wird sie nicht in einen Kindprozess kopiert. Wenn ich also versuche, sie über Ruby zu drucken, funktioniert das nicht.

Als nächstes verwende ich den Befehl export, um die lokale Variable in eine Umgebungsvariable umzuwandeln. Jetzt wird sie in jeden neuen Prozess kopiert, den diese Shell erstellt. Jetzt ist die Umgebungsvariable für Ruby verfügbar.

Lokale Variablen sind für untergeordnete Prozesse nicht verfügbar. Der Export wandelt die lokale Variable in eine Umgebungsvariable um. Lokale Variablen sind für untergeordnete Prozesse nicht verfügbar. Export konvertiert die lokale Variable in eine Umgebungsvariable.

Verwaltung von Umgebungsvariablen in der Praxis

Wie funktioniert das alles in der realen Welt? Lassen Sie uns ein Beispiel machen:

Angenommen, Sie haben zwei Rails-Anwendungen auf einem einzigen Computer laufen. Sie verwenden Honeybadger, um diese Anwendungen auf Ausnahmen zu überwachen. Aber Sie sind auf ein Problem gestoßen.

Sie möchten Ihren Honeybadger-API-Schlüssel in der Umgebungsvariablen $HONEYBADGER_API_KEY speichern. Aber Ihre beiden Anwendungen haben zwei verschiedene API-Schlüssel.

Wie kann eine Umgebungsvariable zwei verschiedene Werte haben?

Ich hoffe, Sie kennen jetzt die Antwort. Da Umgebungsvariablen prozessabhängig sind und meine beiden Rails-Anwendungen in verschiedenen Prozessen laufen, gibt es keinen Grund, warum sie nicht jeweils ihren eigenen Wert für $HONEYBADGER_API_KEY haben können.

Jetzt stellt sich nur noch die Frage, wie man das einrichtet. Glücklicherweise gibt es ein paar Gems, die das wirklich einfach machen.

Figaro

Wenn du das Figaro Gem in deiner Rails App installierst, werden alle Werte, die du in config/application.yml einträgst, beim Start in den ruby ENV Hash geladen.

Du installierst einfach das Gem:

# Gemfilegem "figaro"

Und fängst an, Elemente zu application.yml hinzuzufügen. Es ist sehr wichtig, dass du diese Datei zu deiner .gitignore hinzufügst, damit du nicht versehentlich deine Geheimnisse übergibst.

# config/application.ymlHONEYBADGER_API_KEY: 12345

Dotenv

Das dotenv gem ist Figaro sehr ähnlich, außer dass es Umgebungsvariablen von .env und verwendet kein YAML.

Installieren Sie einfach das Gem:

# Gemfilegem 'dotenv-rails'

Und fügen Sie Ihre Konfigurationswerte zu .env ein – und stellen Sie sicher, dass Sie die Datei mit git ignorieren, damit Sie sie nicht versehentlich auf github veröffentlichen.

HONEYBADGER_API_KEY=12345

Dann kannst du auf die Werte in deinem Ruby-ENV-Hash zugreifen

ENV

Du kannst auch Befehle in der Shell mit deinem vordefinierten Satz von env-Variablen wie folgt ausführen:

dotenv ./my_script.sh

Geheimnisse.yml?

Sorry. Secrets.yml – obwohl cool – setzt keine Umgebungsvariablen. Es ist also nicht wirklich ein Ersatz für Gems wie Figaro und dotenv.

Plain old Linux

Es ist auch möglich, eindeutige Sätze von Umgebungsvariablen pro Anwendung mit einfachen Linux-Befehlen zu pflegen. Ein Ansatz besteht darin, dass jede Anwendung, die auf Ihrem Server läuft, einem anderen Benutzer gehört. Sie können dann die .bashrc des Benutzers verwenden, um anwendungsspezifische Werte zu speichern.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.