esperar error en el comando

esperar error en el comando

El siguiente guión no tiene otro propósito que ilustrar esta pregunta.

#!/usr/bin/env zsh

arbitrary_pipeline () {
    shuf | tr a-z A-Z
}

tmpdir=$( mktemp -d )

mkfifo $tmpdir/{orig,alt}

{ tee $tmpdir/orig | arbitrary_pipeline > $tmpdir/alt; } &
pid=$!

paste $tmpdir/orig $tmpdir/alt

rm -rf $tmpdir

wait $pid

El script utiliza teey dos canalizaciones con nombre para dividir algunas entradas estándar (arbitrarias) en dos flujos, redirige uno de ellos a un canal arbitrario y pasa las entradas a los dos flujos resultantes paste. Esquemáticamente:

STDIN --- > --.- arbitrary_pipeline -.
               \                      \
          paste `----<FIRST-ARGUMENT>  `- <SECOND-ARGUMENT> --> STDOUT

(En este caso arbitrary_pipelinesimplemente mezcla su entrada estándar y la convierte a mayúsculas, pero, como su nombre lo indica, podría ser cualquier cosa).

La salida estándar del script se ve bien, pero el waitcomando siempre falla:

% grep -iP 'z.*s.*h' /usr/share/dict/words | /tmp/test.sh
Nietzsche   CITIZENSHIP'S
Zubeneschamali  NIETZSCHE
Zubeneschamali's    ZUBENESCHAMALI
citizenship CITIZENSHIP
citizenship's   ZUBENESCHAMALI'S
/tmp/test.sh:wait:18: pid 26357 is not a child of this shell

¿Qué estoy haciendo mal?


FWIW:

/usr/bin/env zsh --version
# zsh 5.0.7 (x86_64-pc-linux-gnu)

EDICIONES:

  1. Se agregaron llaves alrededor de la teetubería, según la sugerencia de Jordanm. (Sin embargo, los resultados no cambiaron).
  2. reemplazado &!con &en respuesta al comentario de Stéphane Chazelas. (Nuevamente, los resultados no cambiaron).

Respuesta1

Antes de 5.0.8, zshno podía esperar a que hubiera trabajos que ya estaban muertos. Eso se cambió en 5.0.8 en 2014. Vea el cambioallá.

Aquí, puedes simplemente redirigir stderr para /dev/nullignorar el problema:

wait $pid 2> /dev/null

Tenga en cuenta que en:

{ tee $tmpdir/orig | arbitrary_pipeline > $tmpdir/alt; } &

Como optimización, zshno bifurcará un proceso adicional arbitrary_pipeline, lo ejecutará en el mismo proceso que ejecuta ese subshell iniciado en segundo plano.

pasteno terminará antes de ver EOF en su entrada estándar, siendo su entrada estándar la tubería donde $pid(y sus hijos, si los hay) están escribiendo en el otro extremo. Por lo tanto, no verá eof hasta que $pid(y sus hijos) hayan cerrado todos sus descriptores de archivos (normalmente solo stdout) en el extremo de escritura de la tubería. A menos que $pidcierre explícitamente su salida estándar (lo cual es muy poco común), eso solo sucederá cuando salga.

Lo que eso significa es que paste, en la mayoría de los casos, no saldrá antes $pid; sigue siendo una buena idea hacerlo waitpor si acaso.

Tenga en cuenta que aquí puede utilizar a coprocpara evitar los fifos temporales:

coproc arbitrary_pipeline
cat >&p | paste - /dev/fd/3 3<&p &
coproc : close
wait

(tenga en cuenta que waittambién espera la coprocs).

información relacionada