¿Es posible redirigir toda la salida de un script de shell Bourne a algún lugar, pero con comandos de shell dentro del propio script?
Redirigir la salida de un solo comando es fácil, pero quiero algo más como esto:
#!/bin/sh
if [ ! -t 0 ]; then
# redirect all of my output to a file here
fi
# rest of script...
Significado: si el script se ejecuta de forma no interactiva (por ejemplo, cron), guarde la salida de todo en un archivo. Si se ejecuta de forma interactiva desde un shell, deje que la salida vaya a stdout como de costumbre.
Quiero hacer esto para un script normalmente ejecutado por la utilidad periódica de FreeBSD. Es parte de la ejecución diaria, que normalmente no me gusta ver todos los días en el correo electrónico, por lo que no me la envían. Sin embargo, si algo dentro de este script en particular falla, eso es importante para mí y me gustaría poder capturar y enviar por correo electrónico la salida de esta parte de los trabajos diarios.
Actualización: la respuesta de Joshua es acertada, pero también quería guardar y restaurar stdout y stderr en todo el script, lo que se hace así:
# save stdout and stderr to file descriptors 3 and 4, then redirect them to "foo"
exec 3>&1 4>&2 >foo 2>&1
# ...
# restore stdout and stderr
exec 1>&3 2>&4
exec 1>&3 2>&4 3>&- 4>&-
Respuestas:
Abordando la pregunta como actualizada.
Las llaves '{...}' proporcionan una unidad de redirección de E / S. Las llaves deben aparecer donde pueda aparecer un comando, de manera simplista, al comienzo de una línea o después de un punto y coma. ( Sí, eso se puede hacer más preciso; si quieres objetar, házmelo saber ) .
Tiene razón en que puede preservar el stdout y stderr original con las redirecciones que mostró, pero por lo general es más simple para las personas que tienen que mantener el script más tarde para comprender lo que está sucediendo si alcanza el código redirigido como se muestra arriba.
Las secciones relevantes del manual de Bash son Comandos de agrupación y redirección de E / S . Las secciones correspondientes de la especificación POSIX shell son comandos compuestos y I / O redirección . Bash tiene algunas anotaciones adicionales, pero por lo demás es similar a la especificación de shell POSIX.
fuente
>>
. Algunas personas tienen la costumbre de>
. Anexar siempre es más seguro y más recomendable que sobresalir. Alguien escribió una aplicación que usa el comando de copia estándar para exportar algunos datos al mismo destino.Por lo general, colocaríamos uno de estos en o cerca de la parte superior del script. Las secuencias de comandos que analizan sus líneas de comando realizarían la redirección después del análisis.
Enviar stdout a un archivo
con stderr
anexar stdout y stderr al archivo
Como Jonathan Leffler mencionó en su comentario :
exec
Tiene dos trabajos separados. El primero es reemplazar el shell (script) que se está ejecutando actualmente con un nuevo programa. El otro está cambiando las redirecciones de E / S en el shell actual. Esto se distingue por no tener argumentos paraexec
.fuente
exec
tiene dos trabajos separados. Una es reemplazar el script actual con otro comando, usando el mismo proceso: especifica el otro comando como argumento paraexec
(y puede ajustar las redirecciones de E / S a medida que lo hace). El otro trabajo está cambiando las redirecciones de E / S en el script de shell actual sin reemplazarlo. Esta notación se distingue por no tener un comando como argumento paraexec
. La notación en esta respuesta es de la variante "solo E / S": solo cambia la redirección y no reemplaza el script que se está ejecutando. (Elset
comando es igualmente multipropósito.)exec > >(tee -a "logs/logdata.log") 2>&1
imprime los registros en la pantalla y los escribe en un archivoPuede hacer que todo el script sea una función como esta:
entonces al final del guión ten esto:
Alternativamente, puede registrar todo en el archivo de registro en cada ejecución y aún enviarlo a stdout simplemente haciendo:
fuente
Para guardar el stdout y stderr original, puede usar:
Por ejemplo, el siguiente código imprimirá "walla1" y "walla2" en el archivo de registro (
a.txt
), "walla3" en stdout, "walla4" en stderr.fuente
exec 5>&1
yexec 6>&2
, usando la notación de redirección de salida en lugar de la notación de redirección de entrada para las salidas. Se saldrá con la suya porque cuando el script se ejecuta desde un terminal, la entrada estándar también se puede escribir y tanto la salida estándar como el error estándar son legibles en virtud (¿o es un 'vicio'?) De una peculiaridad histórica: el terminal está abierto para lectura y escritura y la misma descripción de archivo abierto se utiliza para los tres descriptores de archivo de E / S estándar.fuente