¿Podría elaborar el acto de manera diferente como parte de su pregunta?
devnull
Usted tiene un control limitado sobre cuánto prog2ha progresado cuando prog1sale, debido al almacenamiento en búfer interno utilizado para implementar la tubería y cómo prog1y cómo prog2están programados.
chepner
También mire [¿En qué orden se ejecutan los comandos canalizados?] (Unix.stackexchange.com/q/37508)
DK Bose
Respuestas:
4
La respuesta general es no. Es posible prog2salir antes prog1incluso de comenzar (obviamente, eso no puede suceder si prog2realmente lee alguna entrada, lo que esperaría que hiciera si lo está usando en una tubería). Definitivamente es posible prog2salir antes prog1; Esto sucede, por ejemplo, cuando se prog2trata de un programa de búsqueda que sale tan pronto como encuentra una coincidencia, en cuyo caso prog1puede que todavía no haya terminado de producir todos los datos.
No hay una forma directa de prog2recuperar el estado de salida prog1o incluso saber que prog1ha salido. Todo lo que prog2puede saber es que prog1ha cerrado su extremo de la tubería, lo que puede hacer sin morir.
Si desea obtener el estado de salida prog1de prog2, hay dos métodos comunes: se puede escribir en un archivo, o se puede enviar a través de la tubería. Enviar el estado de salida como la última línea de los datos canalizados es una posibilidad. Debe asegurarse de no procesar la última línea hasta que sepa que es la última línea, es decir, hasta que haya intentado leer la siguiente.
{ prog1; echo $?;}|…
Aquí hay un ejemplo donde el lado derecho es un filtro de texto que colorea cada línea que contiene la palabra "error" en rojo. Si el lado izquierdo falla, el lado derecho sale con el mismo estado.
{ prog1; echo $?;}| awk '
NR != 1 {
if (line ~ /[Ee][Rr][Rr][Oo][Rr]/) print "\033[31m" line "\033[0m";
else print line;
}
{line = $0}
END {exit($0)}
'
Intenté { command; echo ${PIPESTATUS[@]}; } | sort | ...para que el estado de salida venga primero en la secuencia. ¡Todo es muy interesante!
@ illuminÉ Eso solo funcionaría si ${PIPESTATUS[@]}se ordena antes que cualquier otra cosa en la salida de command. Si commandimprime varios números, o si puede imprimir texto arbitrario, tiene problemas: no podrá distinguir su salida de la línea de estado.
Gilles 'SO- deja de ser malvado'
Gracias, de hecho, solo logra ordenar un estado de éxito al principio si el comando no contiene 0 en su salida jajaja. Tgif / s.
2
Aunque puede en algunos casos especiales (vea las otras respuestas) no puede en todos los casos. Algunos programas de filtro simplemente continuarán, mientras que otros mantendrán toda la salida, la desatarán de una sola vez y luego saldrán.
Para un ejemplo de un programa "simplemente continúe", grepservidor, como lo haría tail -f /var/log/some_log_file. El uso sorten una tubería provoca un "bloqueo", ya sortque recogerá la entrada hasta que la tubería frente a ella se cierre. El uso xargsagrega una complicación adicional: ¿son los programas iniciados por xargs(puede comenzar muchas instancias) parte de la tubería o no?
-1 porque te votaron por racionalizar una respuesta incorrecta.
ctrl-alt-delor
@richard ¿Eh? La respuesta de Bruce es correcta (aunque el segundo párrafo es un poco confuso).
Gilles 'SO- deja de ser malvado'
1
La respuesta: no directamente.
@terdon ha ilustrado que el código de salida del comando anterior en la tubería debe enviarse como un parámetro explícito al siguiente comando.
Recuerde que la tubería es simplemente un mapeo del STDOUT del comando anterior al STDIN del siguiente comando; los códigos de salida no se envían a STDOUT (o STDERR).
-1 porque te votaron positivamente por citar una respuesta incorrecta y no decir mucho más.
ctrl-alt-delor
justo lo suficiente @richard ... Debería haber una doble comprobación ... eso es lo que pasó, si me esfuerzo para responder a una pregunta cuando muy cansado ...
pepoluan
1
Todos los procesos, en proceso, se inician antes de cualquier salida. Por prog2lo tanto, podría tener que obtener esta información después de que haya comenzado, también tendría que retrasar el procesamiento hasta que prog1haya salido, esto podría detener la tubería. Parece haber problemas fundamentales al hacer lo que pides, no limitaciones del sistema operativo.
Probablemente deba considerar un archivo temporal o colocar el resultado en una variable.
Ejemplo para una pequeña cantidad de datos, usando una variable.
tmp=$(prog1)if test "z$PIPESTATUS"=="z0"then…else…fi
Hay un vacío en tu razonamiento. prog2se inicia antes de que se prog1complete en general, pero podría haber una forma de recibir el estado de salida prog1mientras se está ejecutando.
prog2
ha progresado cuandoprog1
sale, debido al almacenamiento en búfer interno utilizado para implementar la tubería y cómoprog1
y cómoprog2
están programados.Respuestas:
La respuesta general es no. Es posible
prog2
salir antesprog1
incluso de comenzar (obviamente, eso no puede suceder siprog2
realmente lee alguna entrada, lo que esperaría que hiciera si lo está usando en una tubería). Definitivamente es posibleprog2
salir antesprog1
; Esto sucede, por ejemplo, cuando seprog2
trata de un programa de búsqueda que sale tan pronto como encuentra una coincidencia, en cuyo casoprog1
puede que todavía no haya terminado de producir todos los datos.No hay una forma directa de
prog2
recuperar el estado de salidaprog1
o incluso saber queprog1
ha salido. Todo lo queprog2
puede saber es queprog1
ha cerrado su extremo de la tubería, lo que puede hacer sin morir.Si desea obtener el estado de salida
prog1
deprog2
, hay dos métodos comunes: se puede escribir en un archivo, o se puede enviar a través de la tubería. Enviar el estado de salida como la última línea de los datos canalizados es una posibilidad. Debe asegurarse de no procesar la última línea hasta que sepa que es la última línea, es decir, hasta que haya intentado leer la siguiente.Aquí hay un ejemplo donde el lado derecho es un filtro de texto que colorea cada línea que contiene la palabra "error" en rojo. Si el lado izquierdo falla, el lado derecho sale con el mismo estado.
fuente
{ command; echo ${PIPESTATUS[@]}; } | sort | ...
para que el estado de salida venga primero en la secuencia. ¡Todo es muy interesante!${PIPESTATUS[@]}
se ordena antes que cualquier otra cosa en la salida decommand
. Sicommand
imprime varios números, o si puede imprimir texto arbitrario, tiene problemas: no podrá distinguir su salida de la línea de estado.Aunque puede en algunos casos especiales (vea las otras respuestas) no puede en todos los casos. Algunos programas de filtro simplemente continuarán, mientras que otros mantendrán toda la salida, la desatarán de una sola vez y luego saldrán.
Para un ejemplo de un programa "simplemente continúe",
grep
servidor, como lo haríatail -f /var/log/some_log_file
. El usosort
en una tubería provoca un "bloqueo", yasort
que recogerá la entrada hasta que la tubería frente a ella se cierre. El usoxargs
agrega una complicación adicional: ¿son los programas iniciados porxargs
(puede comenzar muchas instancias) parte de la tubería o no?fuente
La respuesta: no directamente.
@terdon ha ilustrado que el código de salida del comando anterior en la tubería debe enviarse como un parámetro explícito al siguiente comando.
Recuerde que la tubería es simplemente un mapeo del STDOUT del comando anterior al STDIN del siguiente comando; los códigos de salida no se envían a STDOUT (o STDERR).
fuente
Todos los procesos, en proceso, se inician antes de cualquier salida. Por
prog2
lo tanto, podría tener que obtener esta información después de que haya comenzado, también tendría que retrasar el procesamiento hasta queprog1
haya salido, esto podría detener la tubería. Parece haber problemas fundamentales al hacer lo que pides, no limitaciones del sistema operativo.Probablemente deba considerar un archivo temporal o colocar el resultado en una variable.
Ejemplo para una pequeña cantidad de datos, usando una variable.
fuente
prog2
se inicia antes de que seprog1
complete en general, pero podría haber una forma de recibir el estado de salidaprog1
mientras se está ejecutando.Para terminar la respuesta de Gilles ,
Es un enfoque.
prog2
podría/tmp/prog1.status
, o/tmp/prog1.status
periódicamente mientras lee la entrada estándar.fuente