Eine Art Nebenfrage, aber wie heißt das Feature selbst, wenn Sie eine Umgebungsvariable für einen einzelnen Unterbefehl wie diesen festlegen? Es fiel mir immer schwer, Informationen darüber zu finden, weil ich nicht weiß, wie sie heißen.
John Cromartie
1
@ JohnCromartie, das solltest du als Frage stellen.
@JohnCromartie Dies ist eine optionale Komponente jedes Shell-Befehls. Sie befindet sich daher in den meisten Shell-Handbüchern im Abschnitt "Einfache Befehle". Für POSIX wäre das hier . glenn hat den analogen abschnitt aus dem bash-handbuch schon für dich verlinkt.
jw013
Wenn Sie eine Variable festlegen, die nicht über eine Zuweisung vorhanden ist, wird eine Shell-Variable erstellt. Durch das Festlegen über ENV oder das Exportieren der Variablen wird die Variable in die Ausführungsumgebung der Shell verschoben. Wenn Sie den Wert einer vorhandenen Variablen ändern, wird der Wert der Ausführungsumgebung aktualisiert, sofern vorhanden. Andernfalls ändern Sie ihn in den internen Shell-Variablen.
Johan
Antworten:
26
Sie sind funktional gleichwertig.
Der Hauptunterschied besteht darin, dass env FOO=bar bazein zwischengeschalteter Prozess zwischen der Shell und aufgerufen wird baz, der wie bei FOO=bar bazder Shell direkt aufgerufen wird baz.
Also in dieser Hinsicht FOO=bar bazbevorzugt.
Die einzigen Situationen, env FOO=barin denen ich mich befinde, sind Situationen, in denen ich einen Befehl an einen anderen Befehl übergeben muss.
Nehmen wir als konkretes Beispiel an, ich habe ein Wrapper-Skript, das einige Änderungen an der Umgebung vornimmt und dann execden Befehl aufruft, der an das Skript übergeben wurde, wie zum Beispiel:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
Wenn Sie es ausführen myscript FOO=bar baz, execwird ein exec FOO=bar bazungültiger Fehler ausgegeben.
Stattdessen nennst du es als myscript env FOO=bar bazwas ausgeführt wird als exec env FOO=bar bazund ist vollkommen gültig.
Das kannst du FOO=bar exec bazaber, also brauchst du envin deinem letzten Punkt nicht.
Stéphane Chazelas
Wenn Sie execetwas tun, nutzt es Ihre aktuelle Umgebung?
Glenn Jackman
1
Das Gleiche gilt für @StephaneChazelas, und Sie können auch sudo FOO=bar bazUmgebungsvariablen übergeben, ohne dass dies erforderlich ist env.
Mike Miller
1
@StephaneChazelas, das funktioniert nur, wenn ich FOO=bardas Skript einfügen möchte . Wenn dies FOOnicht immer der barFall ist, möchte ich es nicht hart codieren und stattdessen weitergeben.
Patrick,
@glennjackman tut es ja, solange die Variablen exportiert oder vor dem übergeben werden exec, wie z FOO=bar exec baz.
Patrick
14
In diesem speziellen Beispiel gibt es keinen effektiven Unterschied, vorausgesetzt, Ihre Shell ist eine POSIX-kompatible Shell, und vorausgesetzt, es bazhandelt sich um eine ausführbare Datei und nicht um eine eingebaute Shell.
Wenn Ihre Shell beispielsweise keine POSIX-kompatible Shell ist cshodertcsh die Syntax
FOO=bar baz
funktioniert nicht und es gibt keine äquivalente Shell-Syntax. Für diese Shells ist der envBefehl die einzige Möglichkeit, Umgebungsvariablen für einen einzelnen Befehl zu überschreiben oder einzufügen.
Wenn bazeine Shell - builtin ist, sagen sie fczum Beispiel dann envnicht die gleichen Ergebnisse liefern, weil envein neues Verfahren ausgeführt wird, anstatt dass sie direkt von dem Kommando - Shell ausgeführt werden . Darüber hinaus gibt es keine fcausführbare Datei, kann es nur als Shell - builtin ausgeführt werden , da der Weg , um es mit dem Shell - Umgebung interagiert, und so envwird nie Arbeit mit einem builtin wiefc .
Darüber hinaus envbietet die -iOption, die Sie einen Befehl in einer leeren Umgebung mit nur einer bestimmten Gruppe von Umgebungsvariablen starten kann. Dies envkann beispielsweise beim Starten von Prozessen in hygienisierten Umgebungen sehr nützlich sein
Wenn ich verwendet tcshhabe, würde ich schreiben (setenv FOO bar; baz), um die entsprechende Funktion zu erhalten.
Barmar
6
Zusätzlich zu dem, was bereits gesagt wurde
VAR=value cmd args > redirs
Da es sich um eine Shell-Funktion (Bourne / POSIX) handelt, ist der Name der Umgebungsvariablen, an die Sie übergeben, beschränkt cmd. Sie müssen gültige Shell-Variablennamen sein und dürfen keine schreibgeschützten oder speziellen Variablen für die Shell sein.
Zum Beispiel können Sie nicht tun:
1=foo cmd
Oder
+++=bar cmd
bash erlaubt dir nicht:
SHELLOPTS=xtrace cmd
Während Sie tun können:
env 1=foo cmd
env +++=bar cmd
env '=baz' cmd
(nicht, dass Sie das wollen oder wollen sollten). Oder:
env SHELLOPTS=xtrace cmd
(Ich muss das manchmal tun).
Beachten Sie, dass envSie immer noch keine Umgebungsvariablenzeichenfolge übergeben können, die kein a enthält =(nicht, dass Sie das auch tun möchten).
Eine Verwendung von envist, die $PATHSuche nach ausführbaren Dateien in Shebang-Zeilen zuzulassen (da dies bei der Suche nach der ausführbaren Datei envberücksichtigt wird $PATH). Dies ist nützlich, wenn sich die ausführbare Datei, die Sie aufrufen möchten, möglicherweise an verschiedenen Stellen auf verschiedenen Computern befindet. Beispielsweise,
#!/usr/bin/env perl
in der ersten Zeile eines Skripts mit ausführbaren Bit gesetzt wird dieses Skript mit Perl ausführen , egal , ob es installiert ist /usr/bin/perloder in /usr/local/bin/perloder in einem ganz anderen Ort, solange das Verzeichnis in dem Pfad.
Natürlich bringt diese Pfadsuche ein zusätzliches Risiko mit sich, aber dann ist das Risiko nicht größer, als wenn Sie es explizit geschrieben hätten perl yourscript.pl, wodurch auch Perl im Suchpfad nachgeschlagen wird.
Ein anderes Mal, wenn enves wirklich nützlich ist, möchten Sie die Umgebung vollständig steuern. Ich führe ein Serverprogramm aus (Informix, falls Sie es nicht erraten können), dessen Umgebung ich vollständig steuern möchte. Ich führe es envam Ende eines Skripts aus, das eine Reihe von Variablen auf die richtigen Werte setzt:
Die -iOption zappt die vorhandene Umgebung. Die nachfolgenden VAR=valueOptionen legen die Umgebungsvariablen fest, die ich festlegen möchte. Der Name des Programms ist in $ONINITund alle Befehlszeilenargumente werden wörtlich mit übergeben "$@".
Das ${IXH:+INFORMIXSQLHOSTS="$IXH"}Konstrukt wird nur übergeben INFORMIXSQLHOSTS="$IXH", envwenn $IXHein nicht leerer Wert festgelegt ist.
Antworten:
Sie sind funktional gleichwertig.
Der Hauptunterschied besteht darin, dass
env FOO=bar baz
ein zwischengeschalteter Prozess zwischen der Shell und aufgerufen wirdbaz
, der wie beiFOO=bar baz
der Shell direkt aufgerufen wirdbaz
.Also in dieser Hinsicht
FOO=bar baz
bevorzugt.Die einzigen Situationen,
env FOO=bar
in denen ich mich befinde, sind Situationen, in denen ich einen Befehl an einen anderen Befehl übergeben muss.Nehmen wir als konkretes Beispiel an, ich habe ein Wrapper-Skript, das einige Änderungen an der Umgebung vornimmt und dann
exec
den Befehl aufruft, der an das Skript übergeben wurde, wie zum Beispiel:Wenn Sie es ausführen
myscript FOO=bar baz
,exec
wird einexec FOO=bar baz
ungültiger Fehler ausgegeben.Stattdessen nennst du es als
myscript env FOO=bar baz
was ausgeführt wird alsexec env FOO=bar baz
und ist vollkommen gültig.quelle
FOO=bar exec baz
aber, also brauchst duenv
in deinem letzten Punkt nicht.exec
etwas tun, nutzt es Ihre aktuelle Umgebung?sudo FOO=bar baz
Umgebungsvariablen übergeben, ohne dass dies erforderlich istenv
.FOO=bar
das Skript einfügen möchte . Wenn diesFOO
nicht immer derbar
Fall ist, möchte ich es nicht hart codieren und stattdessen weitergeben.exec
, wie zFOO=bar exec baz
.In diesem speziellen Beispiel gibt es keinen effektiven Unterschied, vorausgesetzt, Ihre Shell ist eine POSIX-kompatible Shell, und vorausgesetzt, es
baz
handelt sich um eine ausführbare Datei und nicht um eine eingebaute Shell.Wenn Ihre Shell beispielsweise keine POSIX-kompatible Shell ist
csh
odertcsh
die Syntaxfunktioniert nicht und es gibt keine äquivalente Shell-Syntax. Für diese Shells ist der
env
Befehl die einzige Möglichkeit, Umgebungsvariablen für einen einzelnen Befehl zu überschreiben oder einzufügen.Wenn
baz
eine Shell - builtin ist, sagen siefc
zum Beispiel dannenv
nicht die gleichen Ergebnisse liefern, weilenv
ein neues Verfahren ausgeführt wird, anstatt dass sie direkt von dem Kommando - Shell ausgeführt werden . Darüber hinaus gibt es keinefc
ausführbare Datei, kann es nur als Shell - builtin ausgeführt werden , da der Weg , um es mit dem Shell - Umgebung interagiert, und soenv
wird nie Arbeit mit einem builtin wiefc
.Darüber hinaus
env
bietet die-i
Option, die Sie einen Befehl in einer leeren Umgebung mit nur einer bestimmten Gruppe von Umgebungsvariablen starten kann. Diesenv
kann beispielsweise beim Starten von Prozessen in hygienisierten Umgebungen sehr nützlich seinquelle
tcsh
habe, würde ich schreiben(setenv FOO bar; baz)
, um die entsprechende Funktion zu erhalten.Zusätzlich zu dem, was bereits gesagt wurde
Da es sich um eine Shell-Funktion (Bourne / POSIX) handelt, ist der Name der Umgebungsvariablen, an die Sie übergeben, beschränkt
cmd
. Sie müssen gültige Shell-Variablennamen sein und dürfen keine schreibgeschützten oder speziellen Variablen für die Shell sein.Zum Beispiel können Sie nicht tun:
Oder
bash
erlaubt dir nicht:Während Sie tun können:
(nicht, dass Sie das wollen oder wollen sollten). Oder:
(Ich muss das manchmal tun).
Beachten Sie, dass
env
Sie immer noch keine Umgebungsvariablenzeichenfolge übergeben können, die kein a enthält=
(nicht, dass Sie das auch tun möchten).quelle
Eine Verwendung von
env
ist, die$PATH
Suche nach ausführbaren Dateien in Shebang-Zeilen zuzulassen (da dies bei der Suche nach der ausführbaren Dateienv
berücksichtigt wird$PATH
). Dies ist nützlich, wenn sich die ausführbare Datei, die Sie aufrufen möchten, möglicherweise an verschiedenen Stellen auf verschiedenen Computern befindet. Beispielsweise,in der ersten Zeile eines Skripts mit ausführbaren Bit gesetzt wird dieses Skript mit Perl ausführen , egal , ob es installiert ist
/usr/bin/perl
oder in/usr/local/bin/perl
oder in einem ganz anderen Ort, solange das Verzeichnis in dem Pfad.Natürlich bringt diese Pfadsuche ein zusätzliches Risiko mit sich, aber dann ist das Risiko nicht größer, als wenn Sie es explizit geschrieben hätten
perl yourscript.pl
, wodurch auch Perl im Suchpfad nachgeschlagen wird.quelle
Ein anderes Mal, wenn
env
es wirklich nützlich ist, möchten Sie die Umgebung vollständig steuern. Ich führe ein Serverprogramm aus (Informix, falls Sie es nicht erraten können), dessen Umgebung ich vollständig steuern möchte. Ich führe esenv
am Ende eines Skripts aus, das eine Reihe von Variablen auf die richtigen Werte setzt:Die
-i
Option zappt die vorhandene Umgebung. Die nachfolgendenVAR=value
Optionen legen die Umgebungsvariablen fest, die ich festlegen möchte. Der Name des Programms ist in$ONINIT
und alle Befehlszeilenargumente werden wörtlich mit übergeben"$@"
.Das
${IXH:+INFORMIXSQLHOSTS="$IXH"}
Konstrukt wird nur übergebenINFORMIXSQLHOSTS="$IXH"
,env
wenn$IXH
ein nicht leerer Wert festgelegt ist.quelle