Qual è la differenza tra set, export ed env e quando dovrei usarli?


112

Ogni tanto elencherò uno script bash e mi sembra che ci siano alcuni modi per impostare una variabile:

key=value
env key=value
export key=value

Quando ti trovi all'interno di uno script o di un singolo comando (ad esempio, spesso creerò una catena con un launcher Wine per impostare il giusto prefisso Wine), questi sembrano essere completamente intercambiabili, ma sicuramente non può essere il caso.

Qual è la differenza tra questi tre metodi e puoi darmi un esempio di quando vorrei specificatamente usare ciascuno di essi?

Sicuramente correlato a Qual è la differenza tra `VAR = ...` e `export VAR = ...`? ma voglio sapere come si envadatta anche a questo, e alcuni esempi che mostrano i vantaggi di ciascuno sarebbero anche belli :)


5
Si noti che export key=valueè una sintassi estesa e non deve essere utilizzata negli script portatili (ad es #! /bin/sh.).
Simon Richter,

Risposte:


110

Consideriamo un esempio specifico. Il grepcomando utilizza una variabile di ambiente chiamata GREP_OPTIONSper impostare le opzioni predefinite.

Adesso. Dato che il file test.txtcontiene le seguenti righe:

line one
line two

l'esecuzione del comando grep one test.txtrestituirà

line one

Se esegui grep con l' -vopzione, restituirà le righe non corrispondenti, quindi l'output sarà

line two

Proveremo ora a impostare l'opzione con una variabile ambientale.

  1. Le variabili di ambiente impostate senza exportnon verranno ereditate nell'ambiente dei comandi che si stanno chiamando.

    GREP_OPTIONS='-v'
    grep one test.txt

    Il risultato:

    line one

    Ovviamente, l'opzione -vnon è stata passata a grep.

    Si desidera utilizzare questo modulo quando si imposta una variabile da utilizzare solo per la shell, ad esempio for i in * ; donon si desidera esportare $i.

  2. Tuttavia, la variabile viene passata all'ambiente di quella particolare riga di comando, quindi puoi farlo

    GREP_OPTIONS='-v' grep one test.txt

    che restituirà il previsto

    line two

    Si utilizza questo modulo per modificare temporaneamente l'ambiente di questa particolare istanza del programma avviato.

  3. L'esportazione di una variabile provoca l'ereditarietà della variabile:

    export GREP_OPTIONS='-v'
    grep one test.txt

    ritorna ora

    line two

    Questo è il modo più comune di impostare variabili per l'uso di processi avviati successivamente in una shell

  4. Tutto questo è stato fatto in bash. exportè un built-in bash; VAR=whateverè la sintassi bash. env, d'altra parte, è un programma in sé. Quando envviene chiamato, accadono le seguenti cose:

    1. Il comando envviene eseguito come nuovo processo
    2. env modifica l'ambiente e
    3. chiama il comando fornito come argomento. Il envprocesso è sostituito dal commandprocesso.

    Esempio:

    env GREP_OPTIONS='-v' grep one test.txt

    Questo comando avvierà due nuovi processi: (i) env e (ii) grep (in realtà, il secondo processo sostituirà il primo). Dal punto di vista del grepprocesso, il risultato è esattamente lo stesso della corsa

    GREP_OPTIONS='-v' grep one test.txt

    Tuttavia, puoi usare questo idioma se sei al di fuori di bash o non vuoi lanciare un'altra shell (ad esempio, quando usi la exec()famiglia di funzioni anziché la system()chiamata).

Nota aggiuntiva su #!/usr/bin/env

Questo è anche il motivo per cui il linguaggio #!/usr/bin/env interpreterè usato piuttosto che #!/usr/bin/interpreter. envnon richiede un percorso completo per un programma, perché usa la execvp()funzione che cerca attraverso la PATHvariabile proprio come fa una shell, e quindi si sostituisce con l'esecuzione del comando. Pertanto, può essere utilizzato per scoprire dove un interprete (come perl o python) "si siede" sul percorso.

Significa anche che modificando il percorso corrente puoi influenzare quale variante di python verrà chiamata. Ciò rende possibile quanto segue:

echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre

invece di lanciare Calibre, si tradurrà in

I am an evil interpreter!

Perché GREP_OPTIONS = '- v' grep one test.txt funziona? Ho pensato che fosse necessario un punto e virgola dopo '-v' (ma l'ho provato e in effetti funziona.)
Joe,

2
Perché con un punto e virgola, viene interpretato come due comandi bash separati; la prima imposta la variabile (senza esportarla) e la seconda inizia con un ambiente che non ha esportata la variabile. Senza il punto e virgola, tuttavia, questo è un comando (grep), preceduto dall'impostazione di un ambiente locale.
Gennaio

Ma da dove envprovengono tutte le variabili ? Voglio dire, quando apri una nuova shell hai sempre alcune variabili. Quindi alcuni programmi devono averli modificati export, giusto?
Pithikos,

1
Le variabili di ambiente di @Pithikos sono impostate "approvvigionamento di un ambiente". Per impostazione predefinita, bash genererà un bashrc a livello di sistema (o profile.d o bash_profile). Quindi genera il tuo utente ~ / .bashrc (e / o ~ / .bash_profile). Ognuno di questi file può contenere comandi bash per generare altri script, quindi alla fine puoi avere variabili d'ambiente provenienti da ogni parte.
Eric

5
Che dire set var=blah?
CMCDragonkai,
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.