Salida directa de un comando a un archivo que incluye el comando original, e imprimir en el terminal

8

Cuando ejecuto algunas pruebas, necesito ejecutar una serie de comandos. Sería extremadamente útil para mí y me ahorraría mucho tiempo si hubiera una manera de hacer todas estas cosas:

  • Ejecute el comando que necesito ejecutar
  • Redireccionar toda la salida del comando a un archivo especificado
  • Incluye el comando original en el archivo especificado
  • Imprima la salida del comando original en la terminal

La gente me ha sugerido usar tee, que hace un gran trabajo al imprimir en la terminal, así como enviarlo a un archivo pero no incluye el comando original. Con lo que me gustaría terminar es con un archivo donde la primera línea es el comando que ejecuté, y luego debajo está el resultado del comando.

Alguien sugirió esto:

echo "ls -l" | xargs -I{} bash -c "echo >> output.file; eval {} >> output.file"

Pero esto no imprime la salida en el terminal ni incluye el comando original en el archivo.

Agradecería cualquier idea.

shaneoh
fuente
2
Casi duplicado de askubuntu.com/q/688498/295286 .
Sergiy Kolodyazhnyy
No encontré esto en mi búsqueda, no exactamente lo mismo, pero probablemente me habría llevado a la respuesta.
shaneoh
Sí, y es por eso que dije casi el duplicado. Pero para ser sincero con mi opinión, podría tomar casi cualquier solución a partir de ahí y utilizarla con tuberías tee.
Sergiy Kolodyazhnyy

Respuestas:

14

Eso es lo teeque estás buscando.

ls -l | tee outfile

imprime la salida de ls -lstdout (es decir, el terminal) y la guarda en el archivo outfileal mismo tiempo. Pero : no escribe el nombre del comando ni en stdout ni en el archivo. Para lograr eso, solo echoel nombre del comando antes de ejecutar el comando y canalizar ambas salidas a tee:

( echo "ls -l" && ls -l ) | tee outfile

Es engorroso escribir, así que ¿por qué no definir una función?

both(){ ( echo "$@" && "$@" ) | tee outfile ;}

Después de eso puedes correr

both ls -l

para obtener el resultado deseado. Ponga la función en su ~/.bashrcpara tenerla definida en cada nueva terminal.

Si desea poder especificar el archivo de salida como primer argumento como en

both output ls -l

en cambio hazlo:

both(){ ( echo "${@:2}" && "${@:2}" ) | tee "$1" ;}

Si no desea que se sobrescriba el archivo de salida, sino que se anexe, agregue la -aopción tee.

postre
fuente
9

Puede utilizar el scriptcomando que creará un archivo de texto mecanografiado de todo lo impreso en su terminal. Crea un caparazón bifurcado y registrará todo hasta que salga de ese caparazón.

$ script my_output
Script started on Tue 28 Nov 2017 09:46:15 AM UTC
$ whoami
ajefferiss
$ exit
Script done on Tue 28 Nov 2017 09:46:27 AM UTC

Entonces, si cat my_outputobtengo el mismo resultado:

$ cat my_output
Script started on Tue 28 Nov 2017 09:46:15 AM UTC
$ whoami
ajefferiss
$ exit
exit

Script done on Tue 28 Nov 2017 09:46:27 AM UTC
AJefferiss
fuente
6

Puede usar la función de depuración del shell junto con tee:

( set -x; command1 args...; command2 args ) 2>&1 | tee output.log
  • ( ... )inicia un sub-shell que le permite "recopilar" las secuencias de salida de todos los comandos ejecutados dentro del sub-shell. También contiene el efecto del setcomando a continuación para este sub-shell.

  • set -xhabilita la xopción de shell que imprime todos los comandos que ejecuta el shell en la secuencia de error estándar antes de ejecutarlos.

  • 2>&1 redirige el flujo 2 (error estándar) al flujo 1 (salida estándar).

  • | redirige el flujo de salida estándar del comando izquierdo al flujo de entrada estándar del comando derecho.

  • tee FILEcopia la secuencia de entrada estándar al archivo FILEy a la salida estándar.

Si su secuencia de comandos ya está en un archivo de script, tendría más sentido ejecutarlo así:

bash -x /path/to/script args... 2>&1 | tee output.log
David Foerster
fuente