Como posso alcançar
cmd >> file1 2>&1 1>>file2
Ou seja, o stdout e o stderr devem redirecionar para um arquivo (arquivo1) e apenas o stdout (arquivo2) deve redirecionar para outro (ambos no modo de acréscimo)?
O problema é que, quando você redireciona sua saída, ela não está mais disponível para o próximo redirecionamento. Você pode canalizar tee
em um subshell para manter a saída para o segundo redirecionamento:
( cmd | tee -a file2 ) >> file1 2>&1
ou se você gostaria de ver a saída no terminal:
( cmd | tee -a file2 ) 2>&1 | tee -a file1
Para evitar a inclusão do stderr do primeiro tee
para file1
, você deve redirecionar o stderr do seu comando para alguns descritor de arquivo (por exemplo, 3), e depois adicioná-lo ao stdout novamente:
( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
# or
( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1
(obrigado @ fra-san)
Com zsh
:
cmd >& out+err.log > out.log
No modo de acréscimo:
cmd >>& out+err.log >> out.log
Em zsh
e desde que a mult_ios
opção não tenha sido desativada, quando um descritor de arquivo (aqui 1) é redirecionado várias vezes para gravação, o shell implementa um built-in tee
para duplicar a saída para todos os destinos.
out+err
eout
dizer aqui. Nomes de arquivos? Fluxos a serem redirecionados?cmd >& file1 > file2
Você pode: marcar stdout (usando um sed UNBUFFERED, ou seja:
sed -u ...
:), o stderr também vai para stdout (sem marcação, pois não passou por essa marcação com sed) e, assim, conseguir diferenciar os 2 no arquivo de log resultante.O seguinte: é lento (pode ser seriamente otimizado, usando por exemplo um script perl em vez de um tempo ...; faça ...; feito, por exemplo, que gerará sub-conchas e comandos em todas as linhas!), Estranho (parece que eu preciso dos 2 {} estágios em um renomear stdout e depois no outro adicionar o "falled through" stderr), etc. Mas é: uma " prova de conceito ", que tentará manter a saída solicita o máximo de stdout e stderr o máximo possível:
fonte
ls unknown
) para imprimir algo no stderr?>&2 echo "error"
seria ótimo. (2)tee
pode acrescentar vários arquivos ao mesmo tempo. (3) Por que não apenas emcat
vez degrep "^"
? (4) seu script falhará quando a saída stderr começar_stdout_
. (5) por que?ls loop
produzirá tanto stdout quanto stderr, misturados (alternativamente), em uma ordem controlada; para que possamos verificar se mantivemos essa ordem stderr / stdout, apesar da marcação de stdout 2): gnu tail, talvez, mas não cauda regular (por exemplo, em Aix.). 3): grep "^" também mostra os dois nomes de arquivos. 4): isso pode ser alterado pela variável 5): o exemplo complicado funciona em discos antigos (ex, antigo Aix) onde eu testei (nenhum perl disponível).uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406
...)Se a ordem de saída deve ser: stdout then stderr ; não há solução apenas com redirecionamento.
O stderr deve ser armazenado em um arquivo temporal
Descrição:
A única maneira de redirecionar uma saída (um fd como stdout ou stderr) para dois arquivos é reproduzi-la. O comando
tee
é a ferramenta correta para reproduzir um conteúdo do descritor de arquivo. Portanto, uma idéia inicial de ter uma saída em dois arquivos seria usar:Isso reproduz o stdin do tee nos dois arquivos (1 e 2), deixando a saída do tee ainda não utilizada. Mas precisamos acrescentar (usar
-a
) e precisamos apenas de uma cópia. Isso resolve os dois problemas:Para fornecer
tee
com stdout (aquele a repetir), precisamos consumir stderr diretamente fora do comando. De uma maneira, se a ordem não for importante (a ordem de saída (provavelmente) será preservada conforme gerada, o que ocorrer primeiro será armazenado primeiro). Ou:cmd 2>>file1 | tee -a file2 >>file1
cmd 2>>file1 > >( tee -a file2 >>file1 )
( cmd | tee -a file2 ) >> file1 2>&1
A opção 2 funciona apenas em algumas conchas. A opção 3 usa um subshell adicional (mais lento), mas usa os nomes de arquivo apenas uma vez.
Porém, se o stdout precisar ser o primeiro (qualquer que seja a saída da ordem gerada), precisamos armazenar o stderr para anexá-lo ao arquivo no final (primeira solução publicada).
fonte
sponge
:(cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err
No interesse da diversidade:
Se o seu sistema suportar
/dev/stderr
, entãovai funcionar. A saída padrão do
cmd
é enviada para o stdout e o stderr do pipeline. O erro padrão docmd
desviotee
e sai do stderr do pipeline.tão
cmd
ecmd
, misturado.É uma simples questão de enviar esses fluxos para os arquivos corretos.
Como em quase qualquer abordagem como essa (incluindo a resposta de Stéphane ), as
file1
linhas podem ficar fora de ordem.fonte