Was ist der Unterschied zwischen dem Befehl
$ env FOO=bar baz
und
$ FOO=bar baz
Welchen Effekt hat env
das?
Was ist der Unterschied zwischen dem Befehl
$ env FOO=bar baz
und
$ FOO=bar baz
Welchen Effekt hat env
das?
Antworten:
Sie sind funktional gleichwertig.
Der Hauptunterschied besteht darin, dass env FOO=bar baz
ein zwischengeschalteter Prozess zwischen der Shell und aufgerufen wird baz
, der wie bei FOO=bar baz
der Shell direkt aufgerufen wird baz
.
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:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
Wenn Sie es ausführen myscript FOO=bar baz
, exec
wird ein exec FOO=bar baz
ungültiger Fehler ausgegeben.
Stattdessen nennst du es als myscript env FOO=bar baz
was ausgeführt wird als exec env FOO=bar baz
und ist vollkommen gültig.
FOO=bar exec baz
aber, also brauchst du env
in deinem letzten Punkt nicht.
exec
etwas tun, nutzt es Ihre aktuelle Umgebung?
sudo FOO=bar baz
Umgebungsvariablen übergeben, ohne dass dies erforderlich ist env
.
FOO=bar
das Skript einfügen möchte . Wenn dies FOO
nicht immer der bar
Fall ist, möchte ich es nicht hart codieren und stattdessen weitergeben.
exec
, wie z FOO=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 Syntax
FOO=bar baz
funktioniert 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 sie fc
zum Beispiel dann env
nicht die gleichen Ergebnisse liefern, weil env
ein neues Verfahren ausgeführt wird, anstatt dass sie direkt von dem Kommando - Shell ausgeführt werden . Darüber hinaus gibt es keine fc
ausführbare Datei, kann es nur als Shell - builtin ausgeführt werden , da der Weg , um es mit dem Shell - Umgebung interagiert, und so env
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. Dies env
kann beispielsweise beim Starten von Prozessen in hygienisierten Umgebungen sehr nützlich sein
env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz
tcsh
habe, würde ich schreiben (setenv FOO bar; baz)
, um die entsprechende Funktion zu erhalten.
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 env
Sie immer noch keine Umgebungsvariablenzeichenfolge übergeben können, die kein a enthält =
(nicht, dass Sie das auch tun möchten).
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 Datei env
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,
#!/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/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.
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 es env
am Ende eines Skripts aus, das eine Reihe von Variablen auf die richtigen Werte setzt:
env -i HOME="$IXD" \
INFORMIXDIR="$IXD" \
INFORMIXSERVER="$IXS" \
${IXC:+INFORMIXCONCSMCFG="$IXC"} \
${IXH:+INFORMIXSQLHOSTS="$IXH"} \
IFX_LISTEN_TIMEOUT=3 \
ONCONFIG="onconfig.$IXS" \
PATH="/bin:/usr/bin:$IXD/bin" \
SHELL=/bin/ksh \
TZ=UTC0 \
$ONINIT "$@"
Die -i
Option zappt die vorhandene Umgebung. Die nachfolgenden VAR=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 übergeben INFORMIXSQLHOSTS="$IXH"
, env
wenn $IXH
ein nicht leerer Wert festgelegt ist.