Was ist der Unterschied zwischen set, export und env und wann soll ich welche verwenden?

112

Ab und zu starte ich ein Bash-Skript, und es gibt einige Möglichkeiten, eine Variable zu setzen:

key=value
env key=value
export key=value

Wenn Sie sich in einem Skript oder einem einzelnen Befehl befinden (zum Beispiel werde ich häufig eine Variable mit einem Wine-Launcher verketten, um das richtige Wine-Präfix festzulegen), sind diese offenbar vollständig austauschbar, aber das kann sicherlich nicht der Fall sein.

Was ist der Unterschied zwischen diesen drei Methoden und können Sie mir ein Beispiel geben, wann ich jede einzelne speziell verwenden möchte?

Definitiv verwandt mit Was ist der Unterschied zwischen "VAR = ..." und "export VAR = ..."? aber ich möchte wissen, wie das auch dazu envpasst, und einige Beispiele, die die Vorteile von jedem zeigen, wären auch schön :)

Oli
quelle
5
Beachten Sie, dass dies export key=valueeine erweiterte Syntax ist und nicht in portablen Skripten verwendet werden sollte #! /bin/sh.
Simon Richter

Antworten:

110

Betrachten wir ein konkretes Beispiel. Der grepBefehl verwendet eine Umgebungsvariable, die aufgerufen wird GREP_OPTIONS, um Standardoptionen festzulegen.

Jetzt. Vorausgesetzt, die Datei test.txtenthält die folgenden Zeilen:

line one
line two

Ausführen des Befehls grep one test.txtwird zurückkehren

line one

Wenn Sie grep mit der -vOption ausführen , werden die nicht übereinstimmenden Zeilen zurückgegeben, sodass die Ausgabe erfolgt

line two

Wir werden nun versuchen, die Option mit einer Umgebungsvariablen zu setzen.

  1. Umgebungsvariablen, die ohne festgelegt wurden, exportwerden nicht in die Umgebung der von Ihnen aufgerufenen Befehle übernommen.

    GREP_OPTIONS='-v'
    grep one test.txt

    Das Ergebnis:

    line one

    Offensichtlich wurde die Option -vnicht übernommen grep.

    Sie möchten dieses Formular verwenden, wenn Sie eine Variable nur für die Shell festlegen, die Sie beispielsweise for i in * ; donicht exportieren möchten $i.

  2. Die Variable wird jedoch an die Umgebung dieser bestimmten Befehlszeile übergeben, sodass Sie dies tun können

    GREP_OPTIONS='-v' grep one test.txt

    welches das erwartete zurückbringt

    line two

    Sie verwenden dieses Formular, um die Umgebung dieser bestimmten Instanz des gestarteten Programms vorübergehend zu ändern.

  3. Durch das Exportieren einer Variablen wird die Variable vererbt:

    export GREP_OPTIONS='-v'
    grep one test.txt

    kehrt jetzt zurück

    line two

    Dies ist die gebräuchlichste Methode, um Variablen für die Verwendung später gestarteter Prozesse in einer Shell festzulegen

  4. Dies wurde alles in Bash gemacht. exportist ein bash builtin; VAR=whateverist Bash-Syntax. envAndererseits ist es ein Programm für sich. Wenn envaufgerufen wird, passieren folgende Dinge:

    1. Der Befehl envwird als neuer Prozess ausgeführt
    2. env ändert die Umgebung und
    3. Ruft den Befehl auf, der als Argument angegeben wurde. Der envProzess wird durch den commandProzess ersetzt.

    Beispiel:

    env GREP_OPTIONS='-v' grep one test.txt

    Dieser Befehl startet zwei neue Prozesse: (i) env und (ii) grep (tatsächlich ersetzt der zweite Prozess den ersten). Aus Sicht des grepProzesses ist das Ergebnis genau das gleiche wie beim Ausführen

    GREP_OPTIONS='-v' grep one test.txt

    Sie können dieses Idiom jedoch verwenden, wenn Sie sich außerhalb von bash befinden oder keine andere Shell starten möchten (z. B. wenn Sie die exec()Funktionsfamilie anstelle des system()Aufrufs verwenden).

Zusätzlicher Hinweis auf #!/usr/bin/env

Dies ist auch der Grund, warum das Idiom nicht #!/usr/bin/env interpreterverwendet wird #!/usr/bin/interpreter. envkeinen vollständigen Pfad zu einem Programm benötigen, weil es die verwendeten execvp()Funktion , die durch den sucht PATHVariable gerade wie ein Shell tut, und dann ersetzt sich durch den Befehl ausführen. Auf diese Weise kann herausgefunden werden, wo ein Interpreter (wie Perl oder Python) auf dem Pfad "sitzt".

Dies bedeutet auch, dass Sie durch Ändern des aktuellen Pfads beeinflussen können, welche Python-Variante aufgerufen wird. Dies ermöglicht Folgendes:

echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre

Anstatt Calibre zu starten, führt dies zu

I am an evil interpreter!
Januar
quelle
Warum funktioniert GREP_OPTIONS = '- v' grep one test.txt? Ich dachte, es bräuchte ein Semikolon nach '-v' (aber ich habe es versucht und es funktioniert tatsächlich.)
Joe
2
Weil es mit einem Semikolon als zwei separate Bash-Befehle interpretiert wird; Das erste setzt die Variable (ohne sie zu exportieren) und das zweite beginnt mit einer Umgebung, in der die Variable nicht exportiert wurde. Ohne das Semikolon ist dies jedoch ein Befehl (grep), dem das Festlegen einer lokalen Umgebung vorausgeht.
Januar
Woher kommen aber alle Variablen env? Ich meine, wenn Sie eine neue Shell öffnen, haben Sie immer ein paar Variablen. Einige Programme müssen diese also exportbearbeitet haben , oder?
Pithikos
1
@Pithikos-Umgebungsvariablen werden durch "Beschaffung einer Umgebung" festgelegt. Standardmäßig gibt bash einen systemweiten bashrc (oder profile.d oder bash_profile) aus. Dann wird Ihr Benutzer ~ / .bashrc (und / oder ~ / .bash_profile) als Quelle verwendet. Jede dieser Dateien kann Bash-Befehle enthalten, um andere Skripte zu erstellen, sodass Sie letztendlich Umgebungsvariablen haben können, die von überall her kommen.
Eric
5
Was ist set var=blah?
CMCDragonkai