Le funzioni vengono eseguite come sottoprocessi in Bash?


28

In Advanced Bash-Scripting Guide , nell'esempio 27-4 , 7 ° riga dal basso, ho letto questo:

Una funzione viene eseguita come processo secondario.

Ho fatto un test su Bash e sembra che la frase sopra sia sbagliata.

Le ricerche su questo sito, Bash Man e il mio motore di ricerca non portano luce.

Hai la risposta e vorresti spiegare?


12
Come notato, quella guida è fuorviante all'estremo. Consiglio invece la guida di Wooledge Bash .
Carattere jolly

Risposte:


36

La Guida avanzata agli script di Bash non è sempre affidabile e i suoi script di esempio contengono pratiche obsolete come l'uso di backtick effettivamente deprecati per la sostituzione dei comandi, ovvero `command`anziché $(command).

In questo caso particolare, è palesemente errato.

La sezione sulle funzioni della shell nel manuale (canonico) di Bash lo afferma definitivamente

Le funzioni della shell vengono eseguite nel contesto della shell corrente; non viene creato alcun nuovo processo per interpretarli.


10
"La Guida avanzata agli script di Bash è generalmente inaffidabile" Molto vero.
Giovanni 1024,

1
Puoi fornire riferimenti a sostegno della tua prima frase?
Will Vousden,

5
@ WillVousden come sarebbe un riferimento qui? Un mucchio di esempi delle carenze tecniche della guida? Un documento in cui gli esperti della comunità bash hanno precedentemente notato che non è affidabile? Sarebbe d'aiuto se un membro di StackOverflow con un badge dorato in bash acconsentisse in un commento? : p
kojiro,

3
@WillVousden Non penso che ciò che desideri esista in una forma affidabile stessa. Mendel Cooper ha aggiornato e risolto problemi con la guida in passato, ma non esiste un tracker di bug pubblico o un elenco di errata. (Forse questa è la frase più dannosa che posso fare.) Quindi quando troviamo un difetto (percepito o reale) tutto ciò che possiamo fare è inviare un'e-mail all'autore e sperare per il meglio.
Kojiro

3
@WillVousden, ... se vuoi una cronologia di quanto tempo il consenso nel canale #bash di freenode è stato che l'ABS dovrebbe essere evitato, vedi wooledge.org/~greybot/meta/abs - il secondo campo in ogni riga è il timestamp e il primo è il nome utente; Spero che sia sufficiente affermare che i nomi utente in questione sono individui molto rispettati.
Charles Duffy,

32

Le funzioni di parentesi graffe verranno eseguite all'interno del processo della shell chiamante, a meno che non abbiano bisogno della propria subshell che è:

  • quando li esegui in background con &
  • quando li esegui come collegamento in una pipeline

Reindirizzamenti o env extra. le variabili non imporranno una nuova subshell:

hw(){
    echo hello world from $BASHPID
    echo var=$var
} 
var=42 hw >&2
echo $BASHPID  #unexports var=42 and restores stdout here

Se si definisce la funzione tra parentesi anziché in ricci:

hw()(
  echo hello world from $BASHPID
)
hw 
echo $BASHPID

verrà sempre eseguito in un nuovo processo.

La sostituzione dei comandi $()crea sempre anche processi in bash (ma non in ksh se si eseguono builtin al suo interno).


Non sapevo f() (...)fosse permesso. Ci sono altre definizioni oltre a {...}e (...)? In Bash, non mi piacciono ancora gli altri.
Tomasz,

1
@tomas È possibile utilizzare la function hw { echo hello world; } sintassi (non è necessario ()se si digita functione si possono specificare i reindirizzamenti subito dopo la finale }o )come in hw(){ echo error; } >&2. Questo è tutto.
PSkocik

2
Questa è la risposta a cui ho pensato subito ed è assolutamente corretta. Dovrebbe essere votata come la risposta corretta. f()(...)eseguire sempre una propria shell, mentre f(){...}non lo è.
rexkogitans,

11
NB le funzioni bash accettano qualsiasi comando composto, quindi anche foo() [[ x = x ]]una definizione di funzione valida. Tuttavia, se guardi la funzione con type foovedrai che questo è ancora zucchero sintattico per foo() { [[ x = x ]]; }. Lo stesso vale per le funzioni subshell: bar() ( : )diventa bar() { ( : ); }.
Kojiro,

1
@kojiro nice +1. non lo sapevo
PSkocik,

9

Il comando in questione da quell'esempio è simile a:

echo ${arrayZ[@]/%e/$(replacement)}

L'esempio in seguito afferma:

#    $( ... ) is command substitution.
#    A function runs as a sub-process.

Essendo benefico per ABS Guide, ciò che apparentemente intendevano scrivere è che la funzione viene eseguita all'interno di una sostituzione di comando e il comando all'interno di una sostituzione di comando viene eseguito in una subshell .


È molto fuorviante. Grazie per la tua interpretazione.
Tomasz,

5
@tomas "molto fuorviante." Si Molto. A differenza della Guida ABS, Greg's Wiki è un'eccellente fonte di informazioni avanzate sulla bash.
Giovanni 1024,

1
Saluti. Qual è la tua opinione su questo: wiki.bash-hackers.org/start ?
Tomasz,

@tomas Non ne ho una conoscenza di prima mano.
Giovanni 1024,

2
@tomas, ... la mia opinione sul wiki di bash-hacker è che è una fonte eccellente. Non l'ho mai affrontato in modo così completo come il wiki di Wooledge, ma tende ad essere accurato e scritto con precisione.
Charles Duffy,
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.