Enviar stdout y stderr a archivo, syslog y terminal

8

Para algunas máquinas en la nube que estoy iniciando, estoy tratando de iniciar sesión en un archivo específico, syslog y el terminal / consola.

En la parte superior de los scripts de configuración de mi máquina / inicio de nube, tengo lo siguiente:

#!/bin/bash
exec &> >(tee "/tmp/box-setup.log" | logger -t box-setup)
apt-get install -y some-package

Esto funciona muy bien al enviar la salida a un archivo y syslog, pero no se canaliza a la salida al terminal.

En general, no tener salida de terminal no es un gran problema, excepto cuando estoy depurando desde una consola remota. Cuando eso sucede, estoy completamente ciego porque la consola está en blanco mientras se ejecuta el script bash.

¿Hay una manera simple de utilizar la bashredirección o lo que sea para canalizar toda la salida (salida estándar junto con error estándar) a un archivo, syslog y el terminal simultáneamente?

Estoy ejecutando Ubuntu 16.04.

Jonathan Oliver
fuente

Respuestas:

8

Agregue una sustitución de proceso anidada y otra teeallí como:

exec &> >(tee >(tee "/tmp/box-setup.log" | logger -t box-setup))

El primero teedentro de la sustitución del proceso principal envía STDOUT / STDERR al terminal y también a la sustitución del proceso anidada, el teeinterior que guarda el contenido en el archivo /tmp/box-setup.logy la tubería también se usa para enviar la salida al loggerSTDIN.

heemayl
fuente
Estoy confundido acerca de las múltiples invocaciones de tee, se bifurcará en n streams, ¿no debería ser esto equivalente? exec &> >(tee /tmp/box-setup.log >(logger -t box-setup))
ThorSummoner
3

Estoy completamente ciego porque la consola está en blanco mientras se ejecuta el script bash.

Es posible que desee resolver ese problema de una manera diferente: ejecute su script bash en segundo plano, y ejecute less /tmp/box-setup.logy presione F para seguir actualizando la pantalla a medida que se agregan líneas al archivo que está mirando (como tail -f).

Si ejecutar el script en segundo plano es un problema, use tmuxo screenpara obtener múltiples sesiones multiplexadas en una conexión ssh. Use el mismo lesscomando en otro shell.


El problema original:

teePuede copiar a múltiples destinos. Convierta uno de ellos en terminal, utilizando el /dev/ttyarchivo especial. Creo que siempre se refiere al control del proceso actual. O probablemente mejor, /dev/stderrya que teeel stderr todavía está conectado al stderr del shell. (Esto le permite silenciar el script con &> / dev / null).

exec &> >(tee /dev/stderr "/tmp/box-setup.log" | logger -t box-setup)

Por cierto, esto es equivalente pero más eficiente que (tee /dev/stderr | tee "/tmp/box-setup.log" | logger ...).

Sería posible usar algo de clonación de descriptores de archivo para proporcionar teeel stdout del script original, en lugar de stderr.

Peter Cordes
fuente
1

Simplemente agregue /dev/stderr(su elección) como salida a tee.

exec &> >(tee /dev/stderr "/tmp/box-setup.log" | logger -t box-setup)

La salida estándar y el error estándar se fusionarán. No hay forma de mantenerlos separados si desea preservar su orden, lo que generalmente es deseable. No importa si ambos van al mismo lugar (por ejemplo, la terminal) de todos modos.

Gilles 'SO- deja de ser malvado'
fuente
teeLa salida estándar es la tubería al registrador, no la terminal. Es stderren ese punto que sigue siendo el terminal, basado en exec &> >(tee /dev/stderr > /dev/null)trabajar como se esperaba en un shell interactivo. stderrparece una mejor idea que mi /dev/ttyidea, ya que te permite cerrar fácilmente el script con una redirección si lo deseas.
Peter Cordes