¿Las funciones se ejecutan como subprocesos en Bash?

28

En Advanced Bash-Scripting Guide , en el ejemplo 27-4 , 7ª línea desde abajo, he leído esto:

Una función se ejecuta como un subproceso.

Hice una prueba en Bash, y parece que la afirmación anterior está mal.

Las búsquedas en este sitio, Bash Man, y mi motor de búsqueda no aportan ninguna luz.

¿Tienes la respuesta y te gustaría explicar?

Tomász
fuente
12
Como se señaló, esa guía es engañosa en extremo. Recomiendo la Guía Wooledge Bash en su lugar.
Comodín el

Respuestas:

36

La Guía avanzada de secuencias de comandos de Bash no siempre es confiable y sus secuencias de comandos de ejemplo contienen prácticas desactualizadas, como el uso de backticks obsoletos para la sustitución de comandos, es decir, en `command`lugar de $(command).

En este caso particular, es descaradamente incorrecto.

La sección sobre Funciones de Shell en el manual (canónico) Bash establece definitivamente que

Las funciones de shell se ejecutan en el contexto de shell actual; No se crea ningún proceso nuevo para interpretarlos.

Anthony G - justicia para Monica
fuente
10
"La Guía avanzada de secuencias de comandos Bash generalmente no es confiable" Muy cierto.
John1024
1
¿Puedes dar referencias para apoyar tu primera oración?
Will Vousden
55
@WillVousden, ¿cómo sería una referencia aquí? ¿Un montón de ejemplos de las deficiencias técnicas de la guía? ¿Un documento donde los expertos de la comunidad bash hayan notado previamente que no es confiable? ¿Sería útil que un miembro de stackoverflow con una insignia de oro en bash accediera en un comentario? : p
kojiro
3
@ WillVousden No creo que lo que quieras exista de forma confiable. Mendel Cooper ha actualizado y solucionado problemas con la guía en el pasado, pero no hay un rastreador de errores público o una lista de erratas. (Quizás esa es la declaración más condenatoria que puedo hacer). Entonces, cuando encontramos un defecto (percibido o real), todo lo que podemos hacer es enviar un correo electrónico al autor y esperar lo mejor.
kojiro
3
@WillVousden, ... si desea un historial de cuánto tiempo ha sido el consenso en el canal freenode #bash de que se debe evitar el ABS, consulte wooledge.org/~greybot/meta/abs : el segundo campo en cada línea es la marca de tiempo y el primero es el nombre de usuario; Espero que sea suficiente la afirmación de que los nombres de usuario en cuestión son individuos muy respetados.
Charles Duffy el
32

Las funciones de llaves se ejecutarán dentro del proceso del shell de llamada, a menos que necesiten su propio subshell que es:

  • cuando los ejecutas en segundo plano con &
  • cuando los ejecutas como un enlace en una tubería

Redirecciones o env extra. las variables no forzarán una nueva subshell:

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

Si define la función con paréntesis en lugar de curvas:

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

siempre se ejecutará en un nuevo proceso.

La sustitución de comandos $()también siempre crea procesos en bash (pero no en ksh si ejecuta incorporados dentro de él).

PSkocik
fuente
No sabía que f() (...)está permitido. ¿Hay otras definiciones aparte de {...}y (...)? En Bash, todavía no estoy interesado en los demás.
Tomasz el
1
@tomas Puede usar la function hw { echo hello world; } sintaxis (no es necesario ()si escribe functiony puede especificar las redirecciones justo después de la final }o )como en hw(){ echo error; } >&2. Eso es todo.)
PSkocik
2
Esta es la respuesta en la que pensé de inmediato, y es absolutamente correcta. Debe votarse como la respuesta correcta. f()(...)siempre ejecuta un propio shell, mientras f(){...}que no lo hace.
rexkogitans
11
Nota: las funciones bash aceptan cualquier comando compuesto, por lo que también foo() [[ x = x ]]es una definición de función válida. Sin embargo, si observa la función con type foo, verá que todavía es azúcar sintáctica foo() { [[ x = x ]]; }. Lo mismo puede decirse de las funciones subshell: bar() ( : )se convierte bar() { ( : ); }.
kojiro
1
@kojiro agradable +1. no sabía eso
PSkocik
9

El comando en cuestión de ese ejemplo se ve así:

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

El ejemplo posterior dice:

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

Al ser caritativo con ABS Guide, lo que aparentemente querían escribir es que la función se ejecuta dentro de una sustitución de comando y el comando dentro de una sustitución de comando se ejecuta en una subshell .

John1024
fuente
Eso es muy engañoso. Gracias por tu interpretación.
Tomasz el
55
@tomas "muy engañoso". Si mucho. A diferencia de la Guía de ABS, Greg's Wiki es una excelente fuente de información avanzada de bash.
John1024
1
Aclamaciones. ¿Cuál es su opinión sobre este: wiki.bash-hackers.org/start ?
Tomasz el
@tomas No tengo conocimiento de primera mano de eso.
John1024
2
@tomas, ... mi propia opinión sobre el wiki de bash-hackers es que es una excelente fuente. No lo he revisado de manera tan completa como la wiki de Wooledge, pero tiende a ser precisa y precisa.
Charles Duffy el