Qual è la differenza tra il comando
$ env FOO=bar baz
e
$ FOO=bar baz
Che effetto envha?
Qual è la differenza tra il comando
$ env FOO=bar baz
e
$ FOO=bar baz
Che effetto envha?
Risposte:
Sono funzionalmente equivalenti.
La differenza principale è che env FOO=bar bazcomporta l'invocazione di un processo intermedio tra la shell e baz, dove come con FOO=bar bazla 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=barin 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 execil comando che gli è stato passato, come ad esempio:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
Se lo esegui come myscript FOO=bar baz, execverrà generato un errore poiché exec FOO=bar baznon è valido.
Invece lo chiami come myscript env FOO=bar bazviene eseguito come exec env FOO=bar bazed è perfettamente valido.
FOO=bar exec baz, quindi non è necessario envnel tuo ultimo punto.
execqualcosa, usa il tuo ambiente attuale?
sudo FOO=bar bazpassare le variabili d'ambiente senza necessità env.
FOO=barla sceneggiatura. Se FOOnon è 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 bazsia un eseguibile e non un built-in della shell.
Se la shell non è compatibile con POSIX, ad esempio csho tcshla sintassi
FOO=bar baz
non funziona e non esiste una sintassi della shell equivalente. Per quelle shell, il envcomando è l'unico modo per sovrascrivere o iniettare variabili di ambiente per un singolo comando.
Se bazè un built-in della shell, diciamo fcper esempio, allora envnon darà gli stessi risultati, perché envsta eseguendo un nuovo processo invece di essere eseguito direttamente dalla shell dei comandi. Inoltre, non v'è fceseguibile, esso può essere eseguito solo come integrato nella shell causa del modo in cui interagisce con le shell, e così envfarà mai lavoro che incorpori una simile fc.
Inoltre, envoffre l' -iopzione, che consente di avviare un comando in un ambiente vuoto con solo un set specificato di variabili di ambiente. Quindi envpuò essere molto utile per avviare processi in ambienti sanificati, ad esempio
env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz
tcshusavo 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 envte 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 $PATHricerca di file eseguibili nelle righe shebang (perché envconsidera la $PATHricerca 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/perlo in /usr/local/bin/perlo 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 envalla 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' -iopzione elimina l'ambiente esistente. Le VAR=valueopzioni successive impostano le variabili d'ambiente che voglio impostare; il nome del programma è in $ONINITe tutti gli argomenti della riga di comando vengono passati alla lettera con "$@".
Il ${IXH:+INFORMIXSQLHOSTS="$IXH"}costrutto solo passa INFORMIXSQLHOSTS="$IXH"per envse $IXHè impostato su un valore non vuoto.