Envie stdout e stderr para arquivo, syslog e terminal

8

Para algumas máquinas na nuvem que estou iniciando, estou tentando fazer logon em um arquivo específico, syslog e no terminal / console.

Na parte superior dos scripts de configuração da máquina / cloud-init, tenho o seguinte:

#!/bin/bash
exec &> >(tee "/tmp/box-setup.log" | logger -t box-setup)
apt-get install -y some-package

Isso funciona muito bem no envio de saída para um arquivo e syslog, mas não canaliza a saída para o terminal.

De um modo geral, não ter saída de terminal não é um grande problema, exceto quando estou depurando de um console remoto. Quando isso acontece, fico completamente cego porque o console está em branco enquanto o script bash é executado.

Existe uma maneira simples de usar o bashredirecionamento ou o que quer que seja para canalizar toda a saída (saída padrão e erro padrão) para um arquivo, syslog e o terminal simultaneamente?

Estou executando o Ubuntu 16.04.

Jonathan Oliver
fonte

Respostas:

8

Adicione uma substituição de processo aninhado e outra teelá como:

exec &> >(tee >(tee "/tmp/box-setup.log" | logger -t box-setup))

O primeiro teena substituição do processo principal envia STDOUT / STDERR para o terminal e também para a substituição do processo aninhado, o teeinterior que salva o conteúdo no arquivo /tmp/box-setup.loge o canal é usado para enviar a saída para loggero STDIN também.

heemail
fonte
Estou confuso com várias invocações de tee, ele bifurca-se em n fluxos, isso não deveria ser equivalente? exec &> >(tee /tmp/box-setup.log >(logger -t box-setup))
ThorSummoner 23/02
3

Sou completamente cego porque o console está em branco enquanto o script bash é executado.

Você pode resolver esse problema de uma maneira diferente: execute seu script bash em segundo plano e execute less /tmp/box-setup.loge pressione F para continuar atualizando a tela à medida que as linhas são adicionadas ao arquivo que está assistindo (como tail -f).

Se a execução do script em segundo plano for um problema, use tmuxou screenpara obter várias sessões multiplexadas em uma conexão ssh. Use o mesmo lesscomando em outro shell.


O problema original:

teepode copiar para vários destinos. Faça de um deles o terminal, usando o /dev/ttyarquivo especial. Eu acho que sempre se refere ao controle do processo atual. Ou provavelmente melhor, /dev/stderrpois teeo stderr do s ainda está conectado ao stderr do shell. (Isso permite silenciar o script com &> / dev / null).

exec &> >(tee /dev/stderr "/tmp/box-setup.log" | logger -t box-setup)

BTW, isso é equivalente a, mas mais eficiente que (tee /dev/stderr | tee "/tmp/box-setup.log" | logger ...).

Seria possível usar alguma clonagem de descritor de arquivo para fornecer teeo stdout do script original, em vez do stderr.

Peter Cordes
fonte
1

Basta adicionar /dev/stderr(sua escolha) como uma saída para tee.

exec &> >(tee /dev/stderr "/tmp/box-setup.log" | logger -t box-setup)

A saída padrão e o erro padrão serão mesclados. Não há como mantê-los separados se você quiser preservar a ordem deles, o que geralmente é desejável. Não importa se os dois estão indo para o mesmo local (por exemplo, o terminal).

Gilles 'SO- parar de ser mau'
fonte
teestdout é o pipe para o logger, não o terminal. É stderrnesse ponto que ainda é o terminal, com base no exec &> >(tee /dev/stderr > /dev/null)trabalho esperado em um shell interativo. stderrparece uma ideia melhor do que a minha /dev/tty, pois permite que você feche facilmente o script com um redirecionamento, se desejar.
Peter Cordes