Qual è la differenza tra il comando
$ env FOO=bar baz
e
$ FOO=bar baz
Che effetto env
ha?
Qual è la differenza tra il comando
$ env FOO=bar baz
e
$ FOO=bar baz
Che effetto env
ha?
Risposte:
Sono funzionalmente equivalenti.
La differenza principale è che env FOO=bar baz
comporta l'invocazione di un processo intermedio tra la shell e baz
, dove come con FOO=bar baz
la shell, invoca direttamente baz
.
Quindi a tal proposito, FOO=bar baz
è preferito.
Le uniche situazioni in cui mi trovo a utilizzare sono quelle env FOO=bar
in cui devo passare un comando a un altro comando.
Ad esempio, supponiamo che io abbia uno script wrapper che esegue alcune modifiche dell'ambiente, quindi richiama exec
il comando che gli è stato passato, come ad esempio:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
Se lo esegui come myscript FOO=bar baz
, exec
verrà generato un errore poiché exec FOO=bar baz
non è valido.
Invece lo chiami come myscript env FOO=bar baz
viene eseguito come exec env FOO=bar baz
ed è perfettamente valido.
FOO=bar exec baz
, quindi non è necessario env
nel tuo ultimo punto.
exec
qualcosa, usa il tuo ambiente attuale?
sudo FOO=bar baz
passare le variabili d'ambiente senza necessità env
.
FOO=bar
la sceneggiatura. Se FOO
non è sempre bar
, non voglio codificarlo e invece passarlo.
exec
, come FOO=bar exec baz
.
In questo esempio particolare, non vi è alcuna differenza effettiva, supponendo che la shell sia una shell compatibile con POSIX, e supponendo che baz
sia un eseguibile e non un built-in della shell.
Se la shell non è compatibile con POSIX, ad esempio csh
o tcsh
la sintassi
FOO=bar baz
non funziona e non esiste una sintassi della shell equivalente. Per quelle shell, il env
comando è l'unico modo per sovrascrivere o iniettare variabili di ambiente per un singolo comando.
Se baz
è un built-in della shell, diciamo fc
per esempio, allora env
non darà gli stessi risultati, perché env
sta eseguendo un nuovo processo invece di essere eseguito direttamente dalla shell dei comandi. Inoltre, non v'è fc
eseguibile, esso può essere eseguito solo come integrato nella shell causa del modo in cui interagisce con le shell, e così env
farà mai lavoro che incorpori una simile fc
.
Inoltre, env
offre l' -i
opzione, che consente di avviare un comando in un ambiente vuoto con solo un set specificato di variabili di ambiente. Quindi env
può essere molto utile per avviare processi in ambienti sanificati, ad esempio
env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz
tcsh
usavo scrivevo (setenv FOO bar; baz)
per ottenere la funzione equivalente.
Oltre a quanto è già stato detto
VAR=value cmd args > redirs
essendo una funzione shell (Bourne / POSIX), sei limitato nel nome delle variabili d'ambiente a cui passi cmd
. Devono essere nomi di variabili shell validi e non devono essere variabili di sola lettura o variabili speciali per la shell.
Ad esempio, non puoi fare:
1=foo cmd
O
+++=bar cmd
bash
non ti consente di fare:
SHELLOPTS=xtrace cmd
Mentre puoi fare:
env 1=foo cmd
env +++=bar cmd
env '=baz' cmd
(non che tu voglia o debba volerlo fare). O:
env SHELLOPTS=xtrace cmd
(A volte ho bisogno di farlo).
Tieni presente che con env
te non puoi ancora passare una stringa di variabile di ambiente che non contiene un =
(non che tu voglia farlo neanche).
Un uso env
è quello di consentire la $PATH
ricerca di file eseguibili nelle righe shebang (perché env
considera la $PATH
ricerca del file eseguibile). Ciò è utile se l'eseguibile che si desidera richiamare potrebbe trovarsi in luoghi diversi su macchine diverse. Per esempio,
#!/usr/bin/env perl
nella prima riga di uno script con set di bit eseguibili eseguirà questo script con Perl indipendentemente dal fatto che sia installato in /usr/bin/perl
o in /usr/local/bin/perl
o in una posizione completamente diversa, purché la directory sia nel percorso.
Ovviamente la ricerca di un percorso comporta un rischio aggiuntivo, ma il rischio non è maggiore di quello scritto in modo esplicito perl yourscript.pl
, che cerca anche perl nel percorso di ricerca.
Un'altra volta in cui env
è davvero utile è se si desidera controllare completamente l'ambiente. Eseguo un programma server (Informix, nel caso tu non riesca a indovinare) il cui ambiente voglio controllare completamente. Lo eseguo usando env
alla fine di uno script che imposta un gruppo di variabili sui valori corretti:
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 "$@"
L' -i
opzione elimina l'ambiente esistente. Le VAR=value
opzioni successive impostano le variabili d'ambiente che voglio impostare; il nome del programma è in $ONINIT
e tutti gli argomenti della riga di comando vengono passati alla lettera con "$@"
.
Il ${IXH:+INFORMIXSQLHOSTS="$IXH"}
costrutto solo passa INFORMIXSQLHOSTS="$IXH"
per env
se $IXH
è impostato su un valore non vuoto.