Risposte:
export
rende la variabile disponibile per i sottoprocessi.
Questo è,
export name=value
significa che il nome della variabile è disponibile per qualsiasi processo eseguito da quel processo di shell. Se si desidera che un processo utilizzi questa variabile, utilizzare export
ed eseguire il processo da quella shell.
name=value
significa che l'ambito variabile è limitato alla shell e non è disponibile per nessun altro processo. Lo useresti per (diciamo) variabili di loop, variabili temporanee ecc.
È importante notare che l'esportazione di una variabile non la rende disponibile per i processi padre. Cioè, specificare ed esportare una variabile in un processo generato non la rende disponibile nel processo che l'ha lanciata.
name=value command
non rendere la variabile disponibile nel sub-processo command
.
Altri hanno risposto che l'esportazione rende la variabile disponibile per i subshells, e questo è corretto ma solo un effetto collaterale. Quando si esporta una variabile, questa viene inserita nell'ambiente della shell corrente (ovvero la shell chiama putenv(3)
o setenv(3)
).
L'ambiente di un processo è ereditato da exec, rendendo visibile la variabile in subshells.
Modifica (con una prospettiva di 5 anni): questa è una risposta sciocca. Lo scopo di "export" è di far sì che le variabili "si trovino nell'ambiente di comandi eseguiti successivamente", indipendentemente dal fatto che tali comandi siano subshells o sottoprocessi. Un'implementazione ingenua sarebbe semplicemente mettere la variabile nell'ambiente della shell, ma ciò renderebbe impossibile l'implementazione export -p
.
bash
, export effettivamente aggiunge la variabile all'ambiente della shell corrente, ma non è così dash
. Mi sembra che aggiungere la variabile all'ambiente della shell corrente sia il modo più semplice per implementare la semantica di export
, ma quel comportamento non è obbligatorio.
dash
abbia a che fare con questo. Il poster originale chiedeva specificamente bash
.
bash
ma si applica ugualmente a qualsiasi variante bourne-shell. Essere eccessivamente specifici e fornire risposte che si applicano solo a bash
è un grande male.
bash
è il jQuery della shell.
export makes the variable available to subshells, and that is correct
Questo è un uso molto confuso della terminologia. I sub-shell non devono export
ereditare le variabili. I sottoprocessi fanno.
È stato detto che non è necessario esportare in bash quando si generano subshells, mentre altri hanno affermato l'esatto contrario. E 'importante notare la differenza tra sottoshell (quelli che vengono creati ()
, ``
, $()
o loop) e sottoprocessi (processi che vengono richiamati in base al nome, ad esempio, un letterale bash
che appare nello script).
Ciò che è comune in questi due costrutti è che nessuno dei due può restituire le variabili alla shell genitore.
$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:
C'è un'altra fonte di confusione: alcuni pensano che i sottoprocessi "biforcati" siano quelli che non vedono variabili non esportate. Di solito fork () s è immediatamente seguito da exec () s, ed è per questo che sembra che fork () sia la cosa da cercare, mentre in realtà è exec (). È possibile eseguire i comandi senza fork () ing prima con il exec
comando e anche i processi avviati con questo metodo non avranno accesso alle variabili non esportate:
$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export
Nota che parent:
questa volta non vediamo la linea, perché abbiamo sostituito la shell genitore con il exec
comando, quindi non è rimasto nulla per eseguire quel comando.
&
) crea anche una subshell.
var=asdf bash -c 'echo $var'
o var=asdf exec bash -c 'echo $var'
? L'output è asdf
. La ;
fa differenza se posizionato dopo la definizione della variabile. Quale sarebbe la spiegazione? Sembra che i var
(senza alcuno ;
) rispetto ai sottoprocessi generati in qualche modo, a causa della shell di origine non abbiano nulla a che fare con esso. echo $var
non stampa nulla se eseguito sulla seconda riga. Ma uno allineato var=asdf bash -c 'echo $var'; echo $var
dà asdf\nasdf
.
export NAME=value
per impostazioni e variabili che hanno significato per un sottoprocesso.
NAME=value
per variabili temporanee o cicliche private al processo di shell corrente.
Più in dettaglio, export
contrassegna il nome della variabile nell'ambiente che viene copiato in un sottoprocesso e i relativi sottoprocessi al momento della creazione. Nessun nome o valore viene mai copiato dal sottoprocesso.
Un errore comune è quello di posizionare uno spazio attorno al segno uguale:
$ export FOO = "bar"
bash: export: `=': not a valid identifier
Solo la variabile esportata (B
) viene visualizzata dal sottoprocesso:
$ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
A is . B is Bob
Le modifiche al sottoprocesso non cambiano la shell principale:
$ export B="Bob"; echo 'B="Banana"' | bash; echo $B
Bob
Le variabili contrassegnate per l'esportazione hanno valori copiati quando viene creato il sottoprocesso:
$ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
[1] 3306
$ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash
Subprocess 1 has B=Bob
Subprocess 2 has B=Banana
[1]+ Done echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
Solo le variabili esportate diventano parte dell'ambiente ( man environ
):
$ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
BOB=Bob
Quindi, ora dovrebbe essere chiaro come il sole estivo! Grazie a Brain Agnew, alexp e William Prusell.
Va notato che è possibile esportare una variabile e successivamente modificare il valore. Il valore modificato della variabile sarà disponibile per i processi figlio. Una volta impostata l'esportazione per una variabile, è necessario eseguire la export -n <var>
rimozione della proprietà.
$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset
Come forse già saprai, UNIX consente ai processi di avere una serie di variabili d'ambiente, che sono coppie chiave / valore, sia chiave che valore sono stringhe. Il sistema operativo è responsabile del mantenimento separato di queste coppie per ciascun processo.
Il programma può accedere alle sue variabili di ambiente tramite questa API UNIX:
char *getenv(const char *name);
int setenv(const char *name, const char *value, int override);
int unsetenv(const char *name);
I processi ereditano anche le variabili di ambiente dai processi parent. Il sistema operativo è responsabile della creazione di una copia di tutti gli "aspetti" al momento della creazione del processo figlio.
Bash , tra le altre shell, è in grado di impostare le sue variabili di ambiente su richiesta dell'utente. Questo è ciò che export
esiste.
export
è un comando Bash per impostare la variabile di ambiente per Bash. Tutte le variabili impostate con questo comando sarebbero ereditate da tutti i processi che questo Bash creerebbe.
Altro su Ambiente in Bash
Un altro tipo di variabile in Bash è la variabile interna. Poiché Bash non è solo una shell interattiva, in realtà è un interprete di script, come qualsiasi altro interprete (ad esempio Python) è in grado di mantenere il proprio set di variabili. Va detto che Bash (a differenza di Python) supporta solo variabili stringa.
Notazione per la definizione delle variabili di Bash è name=value
. Queste variabili rimangono all'interno di Bash e non hanno nulla a che fare con le variabili di ambiente gestite dal sistema operativo.
Altre informazioni sui parametri della shell (comprese le variabili)
Vale anche la pena notare che, secondo il manuale di riferimento di Bash:
L'ambiente per qualsiasi comando o funzione semplice può essere temporaneamente aumentato aggiungendolo con assegnazioni di parametri, come descritto in Parametri Shell . Queste istruzioni di assegnazione influiscono solo sull'ambiente visto da quel comando.
Per riassumere:
export
viene utilizzato per impostare la variabile di ambiente nel sistema operativo. Questa variabile sarà disponibile per tutti i processi figlio creati dall'attuale processo Bash in seguito.La risposta accettata implica questo, ma vorrei rendere esplicita la connessione ai builtin della shell:
Come già accennato, export
renderà disponibile una variabile sia per la shell che per i bambini. Se nonexport
viene utilizzata, la variabile sarà disponibile solo nella shell e solo i builtin della shell potranno accedervi.
Questo è,
tango=3
env | grep tango # prints nothing, since env is a child process
set | grep tango # prints tango=3 - "type set" shows `set` is a shell builtin
Ecco un altro esempio:
VARTEST="value of VARTEST"
#export VARTEST="value of VARTEST"
sudo env | grep -i vartest
sudo echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"
sudo bash -c 'echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"'
Solo usando export VARTEST il valore di VARTEST è disponibile in sudo bash -c '...'!
Per ulteriori esempi vedere:
bash-hackers.org/wiki/doku.php/scripting/processtree
Due dei creatori di UNIX, Brian Kernighan e Rob Pike, lo spiegano nel loro libro "L'ambiente di programmazione UNIX". Google per il titolo e troverai facilmente una versione pdf.
Indirizzano le variabili della shell nella sezione 3.6 e si concentrano sull'uso del export
comando alla fine di quella sezione:
Quando si desidera rendere accessibile il valore di una variabile nelle sotto-shell, è necessario utilizzare il comando di esportazione della shell. (Potresti pensare al motivo per cui non c'è modo di esportare il valore di una variabile da una sotto-shell al suo genitore).
Solo per mostrare la differenza tra una variabile esportata nell'ambiente (env) e una variabile non esportata non nell'ambiente:
Se lo faccio:
$ MYNAME=Fred
$ export OURNAME=Jim
quindi solo $ OURNAME appare nell'ambiente. La variabile $ MYNAME non è nell'ambiente.
$ env | grep NAME
OURNAME=Jim
ma la variabile $ MYNAME esiste nella shell
$ echo $MYNAME
Fred
Per impostazione predefinita, le variabili create all'interno di uno script sono disponibili solo per la shell corrente; i processi figlio (sotto-shell) non avranno accesso ai valori che sono stati impostati o modificati. Consentire ai processi figlio di vedere i valori, richiede l'uso del comando export.
Sebbene non sia esplicitamente menzionato nella discussione, NON è necessario utilizzare l'esportazione quando si genera una subshell da dentro bash poiché tutte le variabili vengono copiate nel processo figlio.
export name=value
non è portatile. A seconda di cosa esattamente vuoi, provaname=value; export name
per una soluzione portatile.