Per env o non per env


32

Qual è la differenza tra il comando

$ env FOO=bar baz

e

$ FOO=bar baz

Che effetto envha?


4
Sorta di una domanda secondaria, ma come si chiama la funzione stessa quando si imposta una variabile di ambiente per un singolo sottocomando del genere? Ho sempre avuto difficoltà a trovare informazioni su questo perché non so come si chiama.
John Cromartie,

1
@JohnCromartie, dovresti fare una domanda.
cjm,

1
Per bash, è documentato qui: gnu.org/software/bash/manual/…
glenn jackman

2
@JohnCromartie È un componente opzionale di ogni comando shell, quindi è nella sezione "Comandi semplici" della maggior parte dei manuali di shell. Per POSIX, sarebbe qui . glenn ha già collegato per te la sezione analoga del manuale di bash.
jw013,

L'impostazione di una variabile che non esiste tramite un'assegnazione crea una variabile di shell. Impostandolo tramite ENV o esportando la variabile, la variabile viene spinta nell'ambiente di esecuzione della shell. La modifica del valore di una variabile esistente aggiornerà il valore dell'ambiente di esecuzione se ne esiste uno, altrimenti lo cambierà nelle variabili interne della shell.
Johan,

Risposte:


26

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.


1
Puoi farlo FOO=bar exec baz, quindi non è necessario envnel tuo ultimo punto.
Stéphane Chazelas,

Quando fai execqualcosa, usa il tuo ambiente attuale?
Glenn Jackman,

1
Idem @StephaneChazelas, e puoi anche sudo FOO=bar bazpassare le variabili d'ambiente senza necessità env.
Mike Miller,

1
@StephaneChazelas che funziona solo se voglio inserire FOO=barla sceneggiatura. Se FOOnon è sempre bar, non voglio codificarlo e invece passarlo.
Patrick,

@glennjackman sì, purché le variabili vengano esportate o passate prima di exec, come FOO=bar exec baz.
Patrick,

14

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

Quando tcshusavo scrivevo (setenv FOO bar; baz)per ottenere la funzione equivalente.
Barmar,

6

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).


2

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.


2

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.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.