¿Existe una directriz oficial de POSIX, GNU u otra sobre dónde se deben imprimir los informes de progreso y la información de registro (cosas como "Hacer foo; foo hecho")? Personalmente, tiendo a escribirlos en stderr para poder redirigir stdout y obtener solo la salida real del programa. Recientemente me dijeron que esto no es una buena práctica ya que los informes de progreso no son en realidad errores y solo los mensajes de error deben imprimirse en stderr.
Ambas posiciones tienen sentido y, por supuesto, puede elegir una u otra según los detalles de lo que está haciendo, pero me gustaría saber si hay un estándar comúnmente aceptado para esto. No he podido encontrar ninguna regla específica en POSIX, los estándares de codificación GNU o cualquier otra lista de mejores prácticas ampliamente aceptada.
Tenemos algunas preguntas similares, pero no abordan este problema exacto:
Cuándo usar la redirección a stderr en scripts de shell : la respuesta aceptada sugiere lo que tiendo a hacer, mantener la salida final del programa en stdout y cualquier otra cosa para stderr. Sin embargo, esto solo se presenta como la opinión de un usuario, aunque respaldada por argumentos.
¿Debería el mensaje de uso ir a stderr o stdout? : Esto es específico para mensajes de ayuda, pero cita el estándar de codificación GNU. Este es el tipo de cosas que estoy buscando, pero no se limita a mensajes de ayuda solamente.
Entonces, ¿hay alguna regla oficial sobre dónde deben imprimirse los informes de progreso y otros mensajes informativos (que no son parte del resultado real del programa)?
stdout
junto con los resultados es una forma segura de hacer que los resultados sean inútiles. Si alguna vez necesita canalizar los resultados a otro programa, dicho programa necesitaría separar los resultados de los hilanderos. Además, si redirige la salida a un archivo, no podrá ver los hilanderos. EN MI HUMILDE OPINIÓN.stdout
es en realidad una forma segura y correcta de lanzar hilanderos y otros mensajes informativos, pero como muchos programadores dicen 'El silencio es dorado. No emite nada si todo está bien. de hecho, stderr siempre se usa para hacer eso debido a la definición vaga y también stdout puede romper la secuencia de la tubería. para guía oficialstderr
para informar mensajes de error, excepto cuando--verbose
se usa un indicador, en cuyo punto también se incluyen informes de progreso.Respuestas:
Posix define las secuencias estándar de la siguiente manera :
La Biblioteca GNU C describe los flujos estándar de manera similar:
Por lo tanto, las definiciones estándar tienen poca guía para el uso de la transmisión más allá de "salida convencional / normal" y "salida de diagnóstico / error". En la práctica, es común redirigir una o ambas de estas secuencias a archivos y tuberías, donde los indicadores de progreso serán un problema . Algunos sistemas incluso monitorean la
stderr
salida y la consideran una señal de problemas. Por lo tanto, la información de progreso puramente auxiliar es problemática en cualquier flujo.En lugar de enviar indicadores de progreso incondicionalmente a cualquiera de las transmisiones estándar, es importante reconocer que la salida de progreso solo es apropiada para transmisiones interactivas . Con eso en mente, recomiendo escribir contadores de progreso solo después de verificar si la secuencia es interactiva (por ejemplo, con
isatty()
) o cuando está explícitamente habilitada por una opción de línea de comandos. Esto es especialmente importante para que los medidores de progreso que dependen del comportamiento de actualización de la terminal tengan sentido, como las barras de% completado.Para ciertos mensajes de progreso muy simples ("Iniciando X" ... "Hecho con X") es más razonable incluir la salida incluso para transmisiones no interactivas. En ese caso, considere cómo los usuarios podrían interactuar con las transmisiones, como buscar con,
grep
paginarless
o monitorear contail -f
. Si tiene sentido ver los mensajes de progreso en esos contextos, será mucho más fácil consumirlosstdout
.fuente
N% done
y cosas comodoing foo
yfoo done
. Este último siempre debe mantenerse, ya que se utilizan para la depuración cuando se redirige a un archivo. Por lo tanto, su sugerencia de verificar si la transmisión es interactiva no es aplicable (aunque generalmente es una muy buena idea).curl
yyum
. En ese caso, me gustaría pensar acerca de si y cómo el usuario desea interactuar con la salida a través degrep
oless
o herramientas similares.POSIX define el error estándar como
Esto no limita su uso solo a mensajes de error. Consideraría la información de progreso como salida de diagnóstico, por lo que pertenece al error estándar.
fuente
stdout
tiene un buffer de línea por defecto, mientras que nostderr
tiene buffer, por lo questderr
es la opción natural para escribir texto / barras / spinners de progreso que no contienen una nueva línea. (Si escribe ese textostdout
, debe abarrotar sus llamadas de salida de progresostdout.flush()
para que sea visible).stdout
, es necesario eliminar incluso si su texto no contiene un salto de línea si desea que sus informes de progreso para mostrar realmente en tiempo real cuando redirigida.POSIX es un poco más concreto sobre "información de diagnóstico" en Shell y Utilidades , 1.4: Valores predeterminados de descripción de la utilidad (énfasis mío):
IANASL, pero interpreto que significa que stderr solo tendrá salida si la utilidad devolverá un código de salida de error. Dado que este no debería ser el curso normal de los eventos para una ejecución exitosa, una utilidad POSIX no debería imprimir información de progreso a menos que ocurra un error (a menos que, por supuesto, se especifique lo contrario, etc.).
fuente
Por el principio de exclusión, solo puede ir a stderr. Sí, sé que preguntaste sobre una especificación oficial, que no puedo presentarte más allá del enlace a la especificación POSIX, dada por Stephen Kitt, que establece que stderr es para fines de diagnóstico.
El punto más importante es que stdin y stdout tienen una función que no permite imprimir informes de progreso en stdout: por supuesto, forman la secuencia de tuberías que en los comandos de shell de Unix no es solo un efecto secundario, sino el núcleo del poderoso enfoque de canalización .
Entonces. Nada excepto la verdadera "carga útil" de su programa pertenece a stdout. Si su programa no tiene salida, entonces nada debería ir a stdout. Esto deja stderr para todo lo demás , incluidos los informes de progreso.
De acuerdo, esto deja un agujero: probablemente sería bueno tener un "stdfluff" o algo así que no sea para resultados ni errores, sino informes de progreso, depuración y algo así. De hecho, nada le impide hacerlo, es decir, puede imprimir su progreso en el descriptor de archivo 3. Ejemplo:
Esto no produce salida. (*)
Esto se imprime en fd-3, que se redirige a stdout.
(*) El primer ejemplo no produce resultados pero sigue siendo un poco exagerado; el
open
falla y$!
lo contendríano such file or directory
; solo tome esto como un ejemplo, por supuesto no es para ser utilizado de esta manera en serio. En un programa real, si desea seguir esta ruta, puede probar si/dev/fd/3
es utilizable y tomar esto como una pista de si activar sus informes de progreso; tendrías que hacerlo bastante temprano para que no te confundan tus propiosopen
archivos reales y tal ...fuente
fd-3
? El tercer disquete?El mensaje de uso debe ir a stdout si el usuario lo ha invocado
--help
y stderr si ha cometido un error. Imprimirlo en stderr incondicionalmente es desagradable porque hace que sea más difícil verlo con un buscapersonas / grep / etc.Además, puedo sugerir una tercera forma: abrir / dev / tty para informes de progreso / spinners / etc.
fuente
--help
o mensajes de ayuda en absoluto. Por favor, vuelva a leer la pregunta.