¿Cómo redirigir y agregar stdout y stderr a un archivo con Bash?

1535

Para redirigir stdout a un archivo truncado en Bash, sé usar:

cmd > file.txt

Para redirigir stdout en Bash, agregando a un archivo, sé usar:

cmd >> file.txt

Para redirigir stdout y stderr a un archivo truncado, sé usar:

cmd &> file.txt

¿Cómo redirijo stdout y stderr anexando a un archivo? cmd &>> file.txtno funciono para mi

flybywire
fuente
37
Me gustaría señalar que &> outfile es un código específico de Bash (y otros) y no portátil. La forma de ser portátil (similar a las respuestas adjuntas) siempre fue y sigue siendo> outfile 2> & 1
TheBonsai

Respuestas:

1999
cmd >>file.txt 2>&1

Bash ejecuta las redirecciones de izquierda a derecha de la siguiente manera:

  1. >>file.txt: Abrir file.txten modo agregar y redirigir stdoutallí.
  2. 2>&1: Redireccionar stderra "a dónde stdoutva actualmente" . En este caso, ese es un archivo abierto en modo anexar. En otras palabras, &1reutiliza el descriptor de archivo que stdoutusa actualmente.
Alex Martelli
fuente
33
¡Funciona genial! pero ¿hay alguna manera de darle sentido a esto o debería tratar esto como una construcción atómica de bash?
flybywire
181
Es una redirección simple, las declaraciones de redirección se evalúan, como siempre, de izquierda a derecha. >> archivo: rojo. STDOUT a archivo (modo de agregado) (abreviatura de 1 >> archivo) 2> & 1: Rojo. STDERR a "donde va stdout" Tenga en cuenta que la interpretación "redirigir STDERR a STDOUT" es incorrecta.
TheBonsai
31
Dice "agregar salida (stdout, descriptor de archivo 1) en file.txt y enviar stderr (descriptor de archivo 2) al mismo lugar que fd1".
Pausado hasta nuevo aviso.
2
@TheBonsai sin embargo, ¿qué pasa si necesito redirigir STDERR a otro archivo pero anexar? ¿es posible?
arod
41
si lo haces cmd >>file1 2>>file2deberías lograr lo que quieres.
Woodrow Douglass
367

Hay dos formas de hacer esto, dependiendo de su versión de Bash.

La forma clásica y portátil ( Bash pre-4 ) es:

cmd >> outfile 2>&1

Una forma no portátil, comenzando con Bash 4 es

cmd &>> outfile

(análogo a &> outfile)

Para un buen estilo de codificación, debes

  • decida si la portabilidad es una preocupación (luego use la forma clásica)
  • decida si la portabilidad incluso para Bash pre-4 es una preocupación (luego use la forma clásica)
  • no importa qué sintaxis use, no la cambie dentro del mismo script (¡confusión!)

Si su script ya comienza con #!/bin/sh(sin importar si fue intencionado o no), entonces la solución Bash 4, y en general cualquier código específico de Bash, no es el camino a seguir.

También recuerde que Bash 4 &>>es una sintaxis más corta: no introduce ninguna funcionalidad nueva ni nada por el estilo.

La sintaxis es (además de otra sintaxis de redirección) descrita aquí: http://bash-hackers.org/wiki/doku.php/syntax/redirection#appending_redirected_output_and_error_output

TheBonsai
fuente
8
Prefiero & >> ya que es consistente con &> y >>. También es más fácil leer "agregar salida y errores a este archivo" que "enviar errores a la salida, agregar salida a este archivo". Nota mientras que Linux tiene en general una versión actual de fiesta, OS X, en el momento de la escritura, aún requiere de fiesta de 4 a instalado manualmente a través de homebrew etc
mikemaccana
Me gusta más porque es más corto y solo tiene Tweoi lugares por línea, entonces, ¿qué haría, por ejemplo, zsh con "& >>"?
Phillipp
También es importante tener en cuenta que en un trabajo cron, debe usar la sintaxis anterior a 4, incluso si su sistema tiene Bash 4.
hyperknot
55
@zsero cron no usa bash en absoluto ... lo usa sh. Puede cambiar el shell predeterminado anteponiendo SHELL=/bin/bashal crontab -earchivo.
Ray Foss
89

En Bash también puede especificar explícitamente sus redireccionamientos a diferentes archivos:

cmd >log.out 2>log_error.out

Anexar sería:

cmd >>log.out 2>>log_error.out
Aaron R.
fuente
66
Redirigir dos secuencias al mismo archivo usando su primera opción hará que la primera escriba "encima" de la segunda, sobrescribiendo algunos o todos los contenidos. Use cmd >> log.out 2> log.out en su lugar.
Orestis P.
3
Gracias por atrapar eso; tienes razón, uno golpeará al otro. Sin embargo, su comando tampoco funciona. Creo que la única forma de escribir en el mismo archivo es como se ha dado anteriormente cmd >log.out 2>&1. Estoy editando mi respuesta para eliminar el primer ejemplo.
Aaron R.
65

En Bash 4 (así como ZSH 4.3.11):

cmd &>>outfile

recién salido de la caja

AB
fuente
2
@todos: esta es una buena respuesta, ya que funciona con bash y es breve, por lo que he editado para asegurarme de que menciona bash explícitamente.
mikemaccana
10
@mikemaccana: la respuesta de TheBonsai muestra la solución bash 4 desde 2009
jfs
52

Esto debería funcionar bien:

your_command 2>&1 | tee -a file.txt

Almacenará todos los registros en file.txt y los volcará en la terminal.

Pradeep Goswami
fuente
Esta es la respuesta correcta si también desea ver la salida en el terminal. Sin embargo, esta no fue la pregunta que se hizo originalmente.
Mikko Rantalainen
25

Prueba esto

You_command 1>output.log  2>&1

Su uso de &> x.file funciona en bash4. lo siento por eso : (

Aquí vienen algunos consejos adicionales.

0, 1, 2 ... 9 son descriptores de archivos en bash.

0 representa stdin, 1 representa stdout, 2 representa stderror. 3 ~ 9 es de repuesto para cualquier otro uso temporal.

Cualquier descriptor de archivo se puede redirigir a otro descriptor de archivo o archivo mediante el operador >o >>(agregar).

Uso: < file_descriptor > > < nombre de archivo | & file_descriptor >

Por favor refiérase a http://www.tldp.org/LDP/abs/html/io-redirection.html

Quintus.Zhou
fuente
Su ejemplo hará algo diferente a lo que solicitó el OP: redirigirá el stderr de You_commandstdout y el stdout de You_commandal archivo output.log. Además, no se agregará al archivo pero lo sobrescribirá.
pabouk
Correcto: el descriptor de archivo podría ser cualquier valor que sea más de 3 para todos los demás archivos.
Itachi
55
Su respuesta muestra el error de redirección de salida más común: redirigir STDERR a donde STDOUT está apuntando actualmente y solo después de eso redireccionar STDOUT al archivo. Esto no hará que STDERR se redirija al mismo archivo. El orden de las redirecciones es importante.
Jan Wikholm
1
significa, primero debería redirigir STDERROR a STDOUT, luego redirigir STDOUT a un archivo. 1 > output.log 2>&1
Quintus.Zhou
1
@ Quintus.Zhou Yup. Su versión redirige err hacia fuera y, al mismo tiempo, hacia fuera para archivar.
Alex Yaroshevich
11

Me sorprende que en casi diez años, nadie haya publicado este enfoque todavía:

Si usa versiones anteriores de bash donde &>>no está disponible, también puede hacer:

(cmd 2>&1) >> file.txt

Esto genera un subshell, por lo que es menos eficiente que el enfoque tradicional cmd >> file.txt 2>&1y, en consecuencia, no funcionará para los comandos que necesitan modificar el shell actual (por ejemplo cd, pushd), pero este enfoque me parece más natural y comprensible:

  1. Redirigir stderr a stdout.
  2. Redireccione la nueva stdout agregando a un archivo.

Además, los paréntesis eliminan cualquier ambigüedad de orden, especialmente si desea canalizar stdout y stderr a otro comando.

jamesdlin
fuente
Esta implementación provoca un proceso adicional para que el sistema se ejecute. El uso de la sintaxis cmd >> file 2>&1funciona en todos los shells y no necesita un proceso adicional para ejecutarse.
Mikko Rantalainen
@MikkoRantalainen Ya expliqué que genera una subshell y es menos eficiente. El objetivo de este enfoque es que si la eficiencia no es un gran problema (y rara vez lo es), de esta manera es más fácil de recordar y más difícil equivocarse.
jamesdlin