Ho letto qui che lo scopo di export
in una shell è rendere la variabile disponibile ai sottoprocessi avviati dalla shell.
Tuttavia, ho anche letto qui e qui che "I processi ereditano il loro ambiente dal genitore (il processo che li ha avviati)."
Se questo è il caso, perché abbiamo bisogno di export
? Cosa mi sto perdendo?
Le variabili della shell non fanno parte dell'ambiente per impostazione predefinita? Qual è la differenza?
Risposta accettata:
La tua ipotesi è che le variabili della shell siano nell'ambiente . Questo non è corretto. L'export
comando è ciò che definisce un nome nell'ambiente. Quindi:
a=1 b=2
export b
risulta nella shell corrente sapendo che $a
si espande a 1 e $b
a 2, ma i sottoprocessi non sapranno nulla di a
perché non fa parte dell'ambiente (anche nella shell corrente).
Alcuni strumenti utili:
set
:Utile per visualizzare i parametri della shell corrente, esportati o menoset -k
:imposta argomenti assegnati nell'ambiente. Consideraf() { set -k; env; }; f a=1
set -a
:dice alla shell di inserire qualsiasi nome che viene impostato nell'ambiente. Come mettereexport
prima di ogni incarico. Utile per.env
file, come inset -a; . .env; set +a
.export
:dice alla shell di inserire un nome nell'ambiente. Esportazione e assegnazione sono due operazioni completamente diverse.env
:Come comando esterno,env
posso solo parlarti degli ereditati ambiente, quindi, è utile per il controllo di integrità.env -i
:Utile per ripulire l'ambiente prima di avviare un processo secondario.
Alternative a export
:
name=val command
# L'assegnazione prima del comando esporta quel nome nel comando.declare/local -x name
# Esporta il nome, particolarmente utile nelle funzioni di shell quando si desidera evitare di esporre il nome a scopi esterni.set -a
# Esporta ogni compito successivo.
Motivazione
Allora perché le shell devono avere le proprie variabili e un ambiente diverso? Sono sicuro che ci sono alcune ragioni storiche, ma penso che la ragione principale sia lo scopo. L'ambiente è per i sottoprocessi, ma ci sono molte operazioni che puoi fare nella shell senza biforcare un sottoprocesso. Supponiamo di eseguire il loop:
for i in {0..50}; do
somecommand
done
Perché sprecare memoria per somecommand
includendo i
, rendendo il suo ambiente più grande di quanto dovrebbe essere? E se il nome della variabile che hai scelto nella shell significasse qualcosa di non previsto per il programma? (I miei preferiti personali includono DEBUG
e VERBOSE
. Questi nomi sono usati ovunque e raramente spazi dei nomi in modo adeguato.)
Cos'è l'ambiente se non la shell?
A volte per capire il comportamento di Unix devi guardare le syscalls, l'API di base per interagire con il kernel e il sistema operativo. Qui, stiamo esaminando l'exec
famiglia di chiamate, che è ciò che usa la shell quando crea un sottoprocesso. Ecco una citazione dalla manpage per exec(3)
(sottolineatura mia):
Il execle()
e execvpe()
le funzioni consentono al chiamante di specificare l'ambiente del programma eseguito tramite l'argomento envp. L'argomento envp è una matrice di puntatori a stringhe con terminazione null e deve essere terminato da un puntatore NULL. Le altre funzioni prendono l'ambiente per la nuova immagine di processo dalla variabile esterna environ nel processo di chiamata.
Quindi scrivendo export somename
nella shell sarebbe equivalente a copiare il nome nel dizionario globale environ
in C. Ma assegnando somename
senza esportarlo sarebbe come assegnarlo in C, senza copiarlo nell'environ
variabile.