Perché bash analizza / esegue roba inserendo la variabile d'ambiente?


9

Il bug shellshock in bash funziona tramite variabili d'ambiente. Sinceramente sono rimasto sorpreso dal fatto che esista una caratteristica del genere:

"trasmissione delle definizioni delle funzioni tramite env vars"

Quindi questa domanda, sebbene forse non sia formulata perfettamente, è quella di chiedere un esempio o un caso in cui sarebbe necessario disporre di questa funzionalità?

Bonus. Anche altre shell zsh, dash ecc hanno questa funzione?


Utilizza le variabili env per trasmettere le definizioni delle funzioni. Cosa intendi con "Perché non mantiene semplicemente le variabili di ambiente disponibili / accessibili?" ?
Anthon,

@Anthon Grazie per il commento. Forse dovrei essere più chiaro e riformulare. Per quale motivo è necessario poter trasmettere le definizioni delle funzioni tramite env vars?
umanità e

1
Non sono sicuro al 100%, ma penso che questo sia il modo in cui GNU parallelottiene le definizioni delle funzioni distribuite se invoca più istanze bash. Se non fosse così, dovrebbe scrivere quelli in un file, che ogni istanza invocata legge e quindi devi affrontare problemi come quando quel file può essere rimosso.
Anthon,

2
questa discussione ha un po 'di storia. le funzioni esportate, tuttavia, sono pazze . se si desidera che una nuova shell erediti i comandi eseguibili della shell precedente, si .dotottiene lo stesso file della shell precedente. ecco come ha fatto - e questo ha senso - oppure dai alla nuova shell il file come input quando execing. una volta letto, una volta il file viene comunque memorizzato nella cache dal kernel.
Mikeserv,

@mikeserv Capisco bene che gran parte dello shellshock è legato a questa funzionalità che non è poi così essenziale?
umanità e

Risposte:


4

Quando uno script richiama un altro script, le variabili dello script principale possono essere esportate e quindi saranno visibili nello script figlio. Esportare funzioni è una generalizzazione ovvia: esportare la funzione dal genitore, renderla visibile nel figlio.

L'ambiente è l'unico modo conveniente in cui un processo può trasmettere dati arbitrari ai propri figli. I dati devono essere raggruppati in stringhe che non contengono byte null, il che non è una difficoltà per le funzioni della shell. Esistono altri metodi potenziali, come blocchi di memoria condivisa o file temporanei passati tramite descrittori di file, ma questi potrebbero causare problemi con programmi intermedi che non sanno cosa farne o li chiudono. I programmi prevedono di essere eseguiti in un ambiente che contiene variabili di cui non sono a conoscenza o che non si preoccupano, quindi non verranno sovrascritte o cancellate.

La scelta di usare il nome della funzione come nome della variabile d'ambiente è strana. Per prima cosa, significa che una variabile esportata si scontra con una funzione esportata con lo stesso nome.

Le funzioni esportate sono una vecchia funzionalità. Le funzioni furono aggiunte nella shell Bourne in SVR2 e le funzioni esportate nella shell Versione 8 furono rilasciate lo stesso anno (1984). In quella shell, variabili e funzioni utilizzavano lo stesso spazio dei nomi. Non so come funzionasse l'esportazione. La shell Heirloom si basa su una variante Bourne che ha funzioni ma non le esporta.

ATT ksh presumibilmente supporta le funzioni di esportazione, ma guardando la fonte o giocando con esso, non riesco a vedere che lo fa, a partire da ksh93u.

env -i /usr/bin/ksh -c 'f=variable; f () { echo function; }; typeset -fx f; /usr/bin/env; ksh -c f'
_=*25182*/usr/bin/env
PWD=/home/gilles
SHLVL=1
A__z="*SHLVL
ksh: f: not found

I cloni di dominio pubblico di Ksh (pdksh, mksh), dash e zsh non supportano le funzioni di esportazione.


1
grazie! Quindi, senza esportare le funzioni la funzionalità viene persa, ma ci sono alcune shell come dash, zsh e pdksh ecc. Che non dispongono di questa funzionalità, leggo bene?
umanità e

Ma quando esporto una funzione in bash, questa va in una variabile come BASH_FUNC_f%%=() { echo hi }. Perché bash analizzerebbe altre variabili d'ambiente? Perché dovrebbe anche analizzare BASH_FUNC_g%%quando chiamo solo f? (Apparentemente, pre-shellshock, la variabile d'ambiente è stata appena chiamata fo g- ma mi chiedo ancora perché gsarebbe stata analizzata se non avessi mai chiamato gnella mia sceneggiatura)
Metamorphic

@Met Deve esaminare tutte le variabili di ambiente per capire quali sono le definizioni delle funzioni. Potrebbe memorizzare questo fatto ed evitare di analizzare il codice di una funzione fino alla prima volta che è necessario, ma sarebbe una complessità aggiuntiva per un guadagno molto piccolo. È più semplice avere un solo tipo di funzione e non due ("funzione normale" e "funzione da una variabile d'ambiente che necessita di un po 'di analisi").
Gilles 'SO- smetti di essere malvagio' il

Non chiaro. Sto suggerendo che la cosa ovvia da fare sarebbe stata, quando eseguo qualcosa chiamato f, (1) controllare una funzione shell chiamata f, (2) controllare una variabile d'ambiente chiamata fe provare ad analizzarla, (3) controllare ogni PATHcomponente per un eseguibile chiamato f. In che modo l'analisi di ogni variabile d'ambiente come codice shell, all'avvio della shell, potrebbe sembrare un progetto meno complicato?
Metamorfico

@Metamorphic Stai suggerendo di aggiungere un altro passaggio che deve essere eseguito su ogni comando. Dovresti anche aggiungere un altro passaggio quando definisci o non definisci le funzioni (dopo unset -f foo, bash non deve più cercare una definizione di funzione foonell'ambiente), quando elenchi le funzioni (come gestisci declare -foltre a leggere tutte le variabili di ambiente?) e qualsiasi altra cosa non stia pensando. Il tuo design sembra più semplice perché ne hai lasciato la maggior parte. Al contrario, fare tutto all'avvio è un singolo pezzo di codice e dopo tutto funziona.
Gilles 'SO- smetti di essere malvagio' il
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.