Obtengo un comportamiento extraño al canalizar la salida de una función al comando tee. El primer problema es que no puedo salir del programa cuando utilizo el comando exit cuando se llama desde una función canalizada a tee. Por ejemplo:

myfunction(){
    # Some stuff here
    exit 1
}

myfunction | tee -a $UPGRADE_LOG

Cuando ejecuto el código anterior, el programa no se cierra y se ejecuta hasta su finalización.

El otro problema que tengo es que tee parece haber causado que algún código se ejecute de tal manera que se deshaga el orden secuencial. Tengo la siguiente salida:

SHOWING SYSTEM-WIDE AND INSTATNCE MEMORY USAGE:
Are you sure you would like to back up the instance given current memory contraints? [y/n]: Filesystem                           Size   Used  Avail  Use%  Mounted on
/dev/mapper/system-root              15G    13G   1.5G   90%   /
Log File Size: 24K   Total Size to Package: 248K Available Space: 1.5G

Cuándo debería ejecutarse como:

SHOWING SYSTEM-WIDE AND INSTATNCE MEMORY USAGE:
Filesystem                           Size   Used  Avail  Use%  Mounted on
/dev/mapper/system-root              15G    13G   1.5G   90%   /
Log File Size: 24K   Total Size to Package: 248K Available Space: 1.5G
Are you sure you would like to back up the instance given current memory contraints? [y/n]: 

Las cosas funcionan correctamente cuando no se usa tee. Los problemas parecen estar relacionados entre sí. ¿Alguna idea de por qué este es el caso y qué debo hacer al respecto?

1
willh99 16 oct. 2018 a las 16:57

2 respuestas

La mejor respuesta

La respuesta de kvantour le dice por qué sucede esto. Este te dice cómo solucionarlo. :)

with_logs_piped() {
  local logfile=$1; shift
  "$@" > >(tee -a -- "$logfile") 2>&1  # 2>&1 redirects stderr through the same tee so it's
}                                      # ...also logged, and shows up sync'd with stdout.

myfunction() {
    # Some stuff here
    exit 1
}

with_logs_piped "$UPGRADE_LOG" myfunction

Lo importante aquí es que, en lugar de utilizar una canalización normal, estamos utilizando una sustitución de proceso para tee - entonces myfunction se ejecuta en su propio shell, no en un subshell, por lo que exit se aplica correctamente.


En cuanto a por qué la redirección de stdout a través de tee desincroniza stderr, consulte Redirigir y recombinar stderr / stdout por separado sin perder el orden

2
Charles Duffy 16 oct. 2018 a las 14:48

La instrucción exit sale del (sub) shell en el que se está ejecutando el proceso. Ahora aquí viene la sorpresa:

Canalizaciones

Una canalización es una secuencia de uno o más comandos separados por uno de los operadores de control | o |&. El formato de una canalización es:

[time [-p]] [ ! ] command [ [|⎪|&] command2 ... ]

Cada comando de una canalización se ejecuta como un proceso independiente (es decir, en una subcapa).

fuente: man bash

Entonces, la declaración exit de la función simplemente mata la subcapa de la canalización. En realidad, esto significa que exit no hace nada en una canalización

$ exit | exit | echo foo
foo
$ exit | exit
$ # shell not terminated

Nota: esto es claramente dependiente del shell porque se comporta de manera diferente.

1
kvantour 16 oct. 2018 a las 14:38