GNU/Linux >> Linux Esercitazione >  >> Linux

Le parentesi mettono davvero il comando in una subshell?

Da quello che ho letto, mettere un comando tra parentesi dovrebbe eseguirlo in una subshell, simile all'esecuzione di uno script. Se questo è vero, come fa a vedere la variabile x se x non è esportata?

x=1

Esecuzione di (echo $x) sulla riga di comando risulta 1

Esecuzione di echo $x in uno script non risulta nulla, come previsto

Risposta accettata:

Una subshell inizia come una copia quasi identica del processo della shell originale. Sotto il cofano, la shell chiama il fork chiamata di sistema, che crea un nuovo processo il cui codice e memoria sono copie. Quando viene creata la subshell, ci sono pochissime differenze tra essa e il suo genitore. In particolare, hanno le stesse variabili. Anche il $$ la variabile speciale mantiene lo stesso valore nelle subshell:è l'ID del processo della shell originale. Allo stesso modo $PPID è il PID del genitore della shell originale.

Alcune shell cambiano alcune variabili nella subshell. Bash imposta BASHPID al PID del processo shell, che cambia nelle subshell. Bash, zsh e mksh organizzano $RANDOM per produrre valori diversi nel genitore e nella subshell. Ma a parte casi speciali incorporati come questi, tutte le variabili hanno lo stesso valore nella subshell come nella shell originale, lo stesso stato di esportazione, lo stesso stato di sola lettura, ecc. Tutte le definizioni delle funzioni, le definizioni degli alias, le opzioni della shell e anche altre impostazioni vengono ereditate.

Una sottoshell creata da (…) ha gli stessi descrittori di file del suo creatore. Alcuni altri mezzi per creare subshell modificano alcuni descrittori di file prima di eseguire il codice utente; ad esempio, il lato sinistro di una pipe scorre in una subshell con output standard collegato alla pipe. La subshell inizia anche con la stessa directory corrente, la stessa maschera di segnale, ecc. Una delle poche eccezioni è che le subshell non ereditano trap personalizzate:segnali ignorati (trap '' SIGNAL ) rimangono ignorati nella subshell, ma altre trap (trap CODE SEGNALE ) vengono ripristinati all'azione predefinita.

Una subshell è quindi diversa dall'esecuzione di uno script. Uno script è un programma separato. Questo programma separato potrebbe casualmente essere anche uno script che viene eseguito dallo stesso interprete del genitore, ma questa coincidenza non dà al programma separato alcuna visibilità speciale sui dati interni del genitore. Le variabili non esportate sono dati interni, quindi quando viene eseguito l'interprete per lo script della shell figlio, non vede queste variabili. Le variabili esportate, ovvero le variabili di ambiente, vengono trasmesse ai programmi eseguiti.

Quindi:

x=1
(echo $x)

stampa 1 perché la subshell è una replica della shell che l'ha generata.

x=1
sh -c 'echo $x'

capita di eseguire una shell come processo figlio di una shell, ma il x sulla seconda riga non ha più alcun collegamento con il x sulla seconda riga che in

x=1
perl -le 'print $x'

o

x=1
python -c 'print x'

Un'eccezione è ksh93 shell in cui il fork è ottimizzato e la maggior parte dei suoi effetti collaterali vengono emulati.
Semanticamente, sono copie. Dal punto di vista dell'implementazione, c'è molta condivisione in corso.
Per il lato destro, dipende dalla shell.
Se lo provi, tieni presente che cose come $(trap) può segnalare le trappole della shell originale. Nota anche che molte shell hanno bug nei casi d'angolo che coinvolgono trappole. Ad esempio ninjalj nota che a partire da bash 4.3, bash -x -c 'trap "echo ERR at $BASH_SUBSHELL $BASHPID" ERR; set -E; false; echo one subshell; (false); echo two subshells; ( (false) )' esegue il ERR trap dalla subshell nidificata nel caso "due subshell", ma non il ERR trap dalla subshell intermedia — set -E l'opzione dovrebbe propagare il ERR trap a tutte le subshell ma la subshell intermedia è ottimizzata e quindi non è lì per eseguire il suo ERR trappola.

Correlati:Linux – Perché setuid non funziona??
Linux
  1. Padroneggia il comando ls di Linux

  2. Alias ​​della riga di comando nella shell di Linux

  3. Come assegnare l'output di un comando a una variabile di shell?

  4. Il punto del comando esterno `cd`?

  5. Esegui uno script di shell dal comando docker-compose, all'interno del contenitore

Comando sorgente in Linux

Che cos'è la shell in Linux?

Shell dei comandi

Comando Bash fc:utilizza facilmente Bash Shell come un professionista

Cosa significa la sintassi |&nel linguaggio della shell?

Nascondere l'output di un comando shell solo in caso di successo?