Saída direta de um comando para um arquivo, incluindo o comando original E imprimir no terminal

8

Ao executar alguns testes, preciso executar uma série de comandos. Seria extremamente útil para mim e me pouparia muito tempo, se houvesse uma maneira de fazer todas essas coisas:

  • Execute o comando que preciso executar
  • Redirecione toda a saída do comando para um arquivo especificado
  • Inclua o comando original no arquivo especificado
  • Imprima a saída do comando original no terminal

As pessoas sugeriram o uso de tee para mim, o que faz um ótimo trabalho de impressão no terminal, além de enviar para um arquivo, mas não inclui o comando original. O que eu gostaria de terminar é um arquivo em que a primeira linha seja o comando que eu executei e, abaixo disso, a saída do comando.

Alguém sugeriu isso:

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

Mas isso não imprime a saída no terminal nem inclui o comando original no arquivo.

Eu apreciaria todas as idéias.

shaneoh
fonte
2
Quase duplicado de askubuntu.com/q/688498/295286 .
Sergiy Kolodyazhnyy
Não encontrei isso na minha pesquisa - não exatamente o mesmo, mas provavelmente teria me levado à resposta.
Shaneoh 28/11
sim, e é por isso que eu disse quase o duplicado. Mas, para ser perfeitamente sincero com a minha opinião, você pode usar praticamente qualquer solução a partir daí e usá-la com o canal tee.
Sergiy Kolodyazhnyy

Respostas:

14

É isso que teevocê está procurando.

ls -l | tee outfile

imprime a saída ls -lpara stdout (ou seja, o terminal) e a salva no arquivo outfileao mesmo tempo. Mas : Ele não grava o nome do comando nem no stdout nem no arquivo. Para conseguir isso, apenas echoo nome do comando antes de executar o comando e canalize as duas saídas para tee:

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

Isso é complicado de digitar, então por que não definir uma função?

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

Depois disso, você pode simplesmente correr

both ls -l

para obter o resultado desejado. Coloque a função no seu ~/.bashrcpara defini-la em cada novo terminal.

Se você deseja especificar o arquivo de saída como o primeiro argumento, como em

both output ls -l

em vez disso, faça:

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

Se você não deseja que o arquivo de saída seja sobrescrito, mas sim anexado a ele, adicione a -aopção a tee.

sobremesa
fonte
9

Você pode usar o scriptcomando que criará um arquivo datilografado de tudo o que é impresso no seu terminal. Ele cria conchas bifurcadas e registra tudo até que o shell seja encerrado.

$ 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

Então, se eu cat my_outputreceber a mesma saída:

$ 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
fonte
6

Você pode usar a função de depuração do shell junto com tee:

( set -x; command1 args...; command2 args ) 2>&1 | tee output.log
  • ( ... )inicia um sub shell que permite "coletar" os fluxos de saída de todos os comandos executados dentro do sub shell. Ele também contém o efeito do setcomando abaixo para este sub-shell.

  • set -xativa a xopção shell que imprime todos os comandos que o shell executa no fluxo de erros padrão antes de executá-los.

  • 2>&1 redireciona o fluxo 2 (erro padrão) para o fluxo 1 (saída padrão).

  • | redireciona o fluxo de saída padrão do comando esquerdo para o fluxo de entrada padrão do comando direito.

  • tee FILEcopia o fluxo de entrada padrão para o arquivo FILEe para a saída padrão.

Se sua sequência de comandos já estiver em um arquivo de script, faria mais sentido executá-la assim:

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