Cómo redirigir la salida a un archivo y stdout
Frecuentes
Visto 723,771 veces
1124
En bash, llamando foo
mostraría cualquier salida de ese comando en la salida estándar.
llamar foo > output
redirigiría cualquier salida de ese comando al archivo especificado (en este caso, 'salida').
¿Hay alguna forma de redirigir la salida a un archivo? y ¿Se muestra en stdout?
10 Respuestas
1597
El comando que quieres se llama tee
:
foo | tee output.file
Por ejemplo, si solo te importa stdout:
ls -a | tee output.file
Si desea incluir stderr, haga lo siguiente:
program [arguments...] 2>&1 | tee outfile
2>&1
redirige el canal 2 (stderr / error estándar) al canal 1 (stdout / salida estándar), de modo que ambos se escriben como stdout. También se dirige al archivo de salida dado a partir del tee
mando.
Además, si quieres anexar al archivo de registro, use tee -a
como:
program [arguments...] 2>&1 | tee -a outfile
Respondido 23 Oct 17, 18:10
Si OP quiere que se redirija "toda la salida", también deberá tomar stderr: "ls -lR / 2> & 1 | tee output.file" - James Brady
@evanmcdonnal La respuesta no es incorrecta, es posible que no sea lo suficientemente específica o completa según sus requisitos. Ciertamente, existen condiciones en las que es posible que no desee que stderr como parte de la salida se guarde en un archivo. Cuando respondí esto hace 5 años, asumí que el OP solo quería stdout, ya que mencionó stdout en el tema de la publicación. - Zoredache
Ah, lo siento, podría haber estado un poco confundido. Cuando lo probé, simplemente no obtuve ningún resultado, tal vez todo iba a stderr. - evanmcdonnal
Utiliza -a
argumento sobre tee
para agregar contenido a output.file
, en lugar de sobrescribirlo: ls -lR / | tee -a output.file
- juez
Si estás usando $?
luego devolverá el código de estado de tee
, que probablemente no sea lo que desea. En su lugar, puede utilizar ${PIPESTATUS[0]}
. - La Goutte
518
$ program [arguments...] 2>&1 | tee outfile
2>&1
vuelca los flujos stderr y stdout.
tee outfile
toma la secuencia que obtiene y la escribe en la pantalla y en el archivo "outfile".
Esto es probablemente lo que busca la mayoría de la gente. La situación probable es que algún programa o script esté trabajando duro durante mucho tiempo y produciendo una gran cantidad de resultados. El usuario desea verificarlo periódicamente para ver el progreso, pero también desea que la salida se escriba en un archivo.
El problema (especialmente cuando se mezclan flujos stdout y stderr) es que se depende de que el programa elimine los flujos. Si, por ejemplo, todas las escrituras en stdout son no enrojecido, pero todas las escrituras a stderr se encuentran las enrojecidos, terminarán fuera de orden cronológico en el archivo de salida y en la pantalla.
También es malo si el programa solo genera 1 o 2 líneas cada pocos minutos para informar el progreso. En tal caso, si el programa no eliminara la salida, el usuario ni siquiera vería ninguna salida en la pantalla durante horas, porque ninguna de ellas pasaría por la tubería durante horas.
Actualización: el programa unbuffer
, Parte de la expect
paquete, resolverá el problema de almacenamiento en búfer. Esto hará que stdout y stderr escriban en la pantalla y el archivo inmediatamente y los mantengan sincronizados cuando se combinan y se redirigen a tee
. P.ej:
$ unbuffer program [arguments...] 2>&1 | tee outfile
contestado el 22 de mayo de 14 a las 04:05
¿Alguien sabe de un 'unbuffer' para osx? - Juan Mee
Si está usando OS X, es un poco más fácil usar unbuffer en la mayoría de los casos, aunque no si desea pasar señales al comando que está ejecutando. Mi comentario estaba más dirigido a usuarios que están en Linux, donde es más probable que coreutils esté instalado de forma predeterminada. @ Ethan, vea esta respuesta si está confundido acerca de la sintaxis stdbuf: stackoverflow.com/a/25548995/942781 - Peter
Tenga en cuenta que python
tiene una opción incorporada -u
que anula el búfer de salida. - fabian789
Un salvavidas absoluto para entrenar modelos de aprendizaje automático en los que quiero iniciar sesión sin código adicional, pero también ver el resultado durante las horas / días que se necesitan para ejecutar, ¡gracias! - rococó
140
Otra forma que funciona para mí es,
<command> |& tee <outputFile>
como se muestra en manual de bash gnu
Ejemplo:
ls |& tee files.txt
Si se usa '| &', command1's Error estándar, además de su salida estándar, está conectado a la entrada estándar de command2 a través de la tubería; es taquigrafía para 2> & 1 |. Esta redirección implícita del error estándar a la salida estándar se realiza después de cualquier redirección especificada por el comando.
Para obtener más información, consulte redirección
respondido 18 mar '17, 23:03
Si estás usando $?
luego devolverá el código de estado de tee
, que probablemente no sea lo que desea. En su lugar, puede utilizar ${PIPESTATUS[0]}
. - La Goutte
Este método descarta la salida de la consola en color, ¿alguna idea? - shakram02
Pruebe: unbuffer ls -l --color = auto | tee files.txt - Luciano Andrés Martini
14
Algo para agregar ...
El paquete unbuffer tiene problemas de soporte con algunos paquetes en las versiones de fedora y redhat unix.
Dejando a un lado los problemas
Seguir funcionó para mí
bash myscript.sh 2>&1 | tee output.log
¡Gracias ScDF & Mateo tus aportaciones me ahorraron mucho tiempo ..
contestado el 23 de mayo de 17 a las 12:05
9
Usar tail -f output
Deberia trabajar.
Respondido 19 Abr '20, 14:04
4
Respuesta de bonificación ya que este caso de uso me trajo aquí:
En el caso de que necesite hacer esto como algún otro usuario
echo "some output" | sudo -u some_user tee /some/path/some_file
Tenga en cuenta que el eco se producirá a medida que usted y la escritura del archivo ocurrirá como "some_user", lo que sucederá NO El trabajo es si tuviera que ejecutar el eco como "algún_usuario" y redirigir la salida con >> "algún_archivo" porque la redirección del archivo sucederá como usted.
Sugerencia: tee también admite agregar con el indicador -a, si necesita reemplazar una línea en un archivo como otro usuario, puede ejecutar sed como el usuario deseado.
Respondido 20 Jul 17, 17:07
4
Puede hacer eso para todo su script usando algo como eso al principio de su script:
#!/usr/bin/env bash
test x$1 = x$'\x00' && shift || { set -o pipefail ; ( exec 2>&1 ; $0 $'\x00' "$@" ) | tee mylogfile ; exit $? ; }
# do whaetever you want
Esto redirige las salidas stderr y stdout al archivo llamado mylogfile
y deja que todo salga a la normalidad al mismo tiempo.
Se utilizan algunos trucos estúpidos:
- utilizado
exec
sin comando para configurar redirecciones, - utilizado
tee
para duplicar salidas, - reinicia el script con las redirecciones deseadas,
- utilizar un primer parámetro especial (un simple
NUL
carácter especificado por el$'string'
notación bash especial) para especificar que el script se reinicia (su trabajo original no puede usar ningún parámetro equivalente), - intente conservar el estado de salida original al reiniciar el script utilizando el
pipefail
.
Feo pero útil para mí en determinadas situaciones.
contestado el 03 de mayo de 19 a las 11:05
2
< command > |& tee filename
# esto creará un archivo "nombre de archivo" con el estado del comando como contenido. Si un archivo ya existe, eliminará el contenido existente y escribirá el estado del comando.
< command > | tee >> filename
# esto agregará el estado al archivo pero no imprime el estado del comando en standard_output (pantalla).
Quiero imprimir algo usando "echo" en la pantalla y agregar esos datos repetidos a un archivo.
echo "hi there, Have to print this on screen and append to a file"
Respondido 01 Feb 18, 16:02
-14
La camiseta es perfecta para esto, pero esto también hará el trabajo.
ls -lr / > output | cat output
respondido 19 nov., 12:10
Eso es un error si la salida aún no existe y no hace lo que usted quiere si lo hace, en general no tiene sentido. Quizás quisiste decir ";" en lugar de "|" ? - roberto apuesta
Incluso si usaste un ;
, la salida se retrasaría mucho durante un comando lento. - brad koch
Si alguien acaba de terminar aquí buscando capturar la salida de error en un archivo, eche un vistazo a: unix.stackexchange.com/questions/132511/… - Murphy
Una nota sobre terminología: cuando ejecuta
foo > output
los datos is escrito en stdout y stdout is el archivo llamadooutput
. Es decir, escribiendo en el archivo is escribiendo en stdout. Estás preguntando si es posible escribir tanto en stdout como en la terminal. - William Pursell@WilliamPursell No estoy seguro de que tu aclaración mejore las cosas :-) ¿Qué tal esto? OP pregunta si es posible dirigir el llamado programa stdout a un archivo y al programa de llamadas stdout (el último es el stdout que el programa llamado heredaría si no se hiciera nada especial; es decir, el terminal, si el programa que llama es una sesión de bash interactiva). Y tal vez también quieran dirigir el programa llamado stderr de manera similar ("cualquier resultado de ese comando" podría interpretarse razonablemente en el sentido de incluir stderr). - Don Hatch