Como salvar stdout em arquivo, stderr em arquivo, stdout + stderr em arquivo e obter stdout + stderr no terminal normalmente para um script de shell

Como salvar stdout em arquivo, stderr em arquivo, stdout + stderr em arquivo e obter stdout + stderr no terminal normalmente para um script de shell

Como posso salvar stdout em um arquivo, stderr em outro arquivo, stdout + stderr em um terceiro arquivo e também obter stdout + stderr no terminal normalmente para um script de shell?

Encontrei isso em outro lugar:

exec > >(tee std_out) 2> >(tee err_out >&2)
ls # Should got to std_out
fsdfs # Command not found goes to err_out

O que é muito próximo. Se eu executar bash test.sh 2>&1 | tee output, funcionará, mas não tenho acesso a como meu script é executado. É um sistema cicd. Preciso ser capaz de fazer a "saída combinada" de dentro do script usando exec.

Estou criando uma biblioteca de CI/CD e não consigo saber para que os clientes usariam a biblioteca, então quero levar em conta cada caso de uso.

Responder1

Simplesmente expandindo sua abordagem:

exec 2> >(tee -a stderr stdall) 1> >(tee -a stdout stdall)

O erro padrão será gravado no arquivo chamado stderr, a saída padrão em stdoute tanto o erro padrão quanto a saída padrão também serão gravados no console (ou o que quer que os dois descritores de arquivo estejam apontando no momento execda execução) e em stdall.
tee -a(append) é necessário para evitar stdallque seja substituído pelo segundo teeque começa a escrever nele.

Observe quea ordemem que os redirecionamentos são realizados é relevante: a segunda substituição do processo é afetada pelo primeiro redirecionamento, ou seja, os erros que ele emitiu seriam enviados para >(tee -a stderr stdall). Você pode, é claro, redirecionar o erro padrão da segunda substituição do processo para /dev/nullevitar esse efeito colateral. Redirecionar a saída padrão antes do erro padrão enviaria todos os erros para stdoute stdalltambém.

Como os comandos nas substituições de processos do Bash são executadosde forma assíncrona, não há como garantir que a saída será exibida na ordem em que foi gerada. Pior ainda, fragmentos da saída padrão e do erro padrão provavelmente acabarão aparecendo na mesma linha.

Responder2

Seu script pode ser executado sozinho $0(definindo e verificando uma variável de ambiente para evitar recursão infinita) em vez de depender da > >(...)construção do bash, que IMLE é caprichosa e não confiável.

if [ "$REDIRECTED" != 1 ]; then
        export REDIRECTED=1
        set -o pipefail
        { { "$0" | tee stdout >&3; } 2>&1 | tee stderr; } 3>&1 | tee stdboth
        exit
fi
# rest of your script here

Como teenão usa buffer de linha (nem poderia ser forçado a fazê-lo com stdbuf(1)), a ordem dos dados gravados em stdout e stderr não será respeitada na saída final. Com um comando que usa buffer completo e grava em stdout e stderr, mesmo um buffer de linha teenão ajudará e, pior, você pode obter linhas de saída que são metade stdout e metade stderr.

Não acho que haja alguma solução para isso usando apenas a linguagem shell e utilitários de linha de comando prontamente disponíveis.

Responder3

Estou criando uma biblioteca de CI/CD e não consigo saber para que os clientes usariam a biblioteca, então quero levar em conta cada caso de uso.

Questiono a necessidade do bash para processar as saídas, visto que este é o cenário. Idealmente, neste contexto, você desejaria registrar a data e hora da saída e fornecer a ela um ID para o tipo de saída padrão e que o aplicativo seja aquele que decide o que fazer com as mensagens.

informação relacionada