Se i processi ereditano l'ambiente del genitore, perché dobbiamo esportare?


72

Ho letto qui che lo scopo di exportin una shell è rendere la variabile disponibile per i sottoprocessi avviati dalla shell.

Tuttavia, ho anche letto qui e qui che "I processi ereditano il loro ambiente dai loro genitori (il processo che li ha avviati)".

In questo caso, perché ne abbiamo bisogno export? Cosa mi sto perdendo?

Le variabili shell non fanno parte dell'ambiente per impostazione predefinita? Qual è la differenza?

Risposte:


75

Il tuo presupposto è che le variabili shell siano nell'ambiente . Questo non è corretto Il exportcomando è ciò che definisce un nome nell'ambiente. Così:

a=1 b=2
export b

fa sì che la shell corrente sappia che si $aespande da 1 $ba 2, ma i sottoprocessi non ne sapranno nulla aperché non fanno parte dell'ambiente (anche nella shell corrente).

Alcuni strumenti utili:

  • set: Utile per visualizzare i parametri della shell corrente, esportati o meno
  • set -k: Imposta gli arg assegnati nell'ambiente. Tener conto dif() { set -k; env; }; f a=1
  • set -a: Indica alla shell di inserire qualsiasi nome impostato nell'ambiente. Come mettere exportprima di ogni incarico. Utile per i .envfile, come in set -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, envpuò solo parlarti dell'ambiente ereditato , quindi è utile per il controllo della sanità mentale.
  • env -i: Utile per cancellare l'ambiente prima di avviare un sottoprocesso.

Alternative a export:

  1. name=val command # L'assegnazione prima del comando esporta quel nome nel comando.
  2. declare/local -x name # Esporta il nome, particolarmente utile nelle funzioni della shell quando si desidera evitare di esporre il nome all'esterno dell'ambito.
  3. set -a # Esporta tutti i compiti seguenti.

3
set -kè così che si può usare cmd ENVVAR=valueal posto di ENVVAR=value cmd, che non funzionerà nel tuo esempio se non è set -kstato eseguito prima di invocare f. Inoltre, non molte shell lo supportano al giorno d'oggi e solo per compatibilità con la shell Bourne. Nella shell Bourne (o Korn), non funzionerebbe per le funzioni. E poiché influisce sull'analisi della shell, deve essere in vigore nel momento in cui la shell legge il codice che la utilizza lì.
Stéphane Chazelas il

1
Potresti anche menzionareset -a
Stéphane Chazelas il

24

C'è una differenza tra variabili shell e variabili d'ambiente. Se si definisce una variabile shell senza exportinserirla, questa non viene aggiunta all'ambiente dei processi e quindi non ereditata dai suoi figli.

Usando exportdici alla shell di aggiungere la variabile shell all'ambiente. Puoi testarlo usando printenv(che stampa solo il suo ambiente stdout, dato che è un processo figlio vedi l'effetto delle exportvariabili ing):

#!/bin/sh

MYVAR="my cool variable"

echo "Without export:"
printenv | grep MYVAR

echo "With export:"
export MYVAR
printenv | grep MYVAR

6

Una variabile, una volta esportata, fa parte dell'ambiente. PATHviene esportato nella shell stessa, mentre le variabili personalizzate possono essere esportate secondo necessità. Utilizzando un codice di installazione:

$ cat subshell.sh 
#!/usr/bin/env bash
declare | grep -e '^PATH=' -e '^foo='

Confrontare

$ cat test.sh 
#!/usr/bin/env bash
export PATH=/bin
export foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test.sh 
PATH=/bin
foo=bar
PATH=/bin
foo=bar

Con

$ cat test2.sh 
#!/usr/bin/env bash
PATH=/bin
foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test2.sh 
PATH=/bin
foo=bar
PATH=/bin

Poiché foonon viene esportato dalla shell e test2.shnon l'ha mai esportato, non faceva parte dell'ambiente subshell.shdell'ultima esecuzione.

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.