Envia stdout e stderr para o arquivo, syslog e terminal

7

Para algumas máquinas em nuvem que estou lançando, estou tentando fazer login em um arquivo específico, syslog e terminal / console.

Na parte superior dos scripts de instalação da minha 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 para 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 a partir de um console remoto. Quando isso acontece, fico completamente cego porque o console está em branco quando o script bash é executado.

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

Estou executando o Ubuntu 16.04.

    
por Jonathan Oliver 10.09.2016 / 22:30

3 respostas

7

Adicione uma substituição de processo aninhada e outro tee como:

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

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

    
por 10.09.2016 / 22:43
3

I'm completely blind because the console is blank as the bash script executes.

Você pode querer resolver o problema de uma maneira diferente: execute o script bash em segundo plano, e execute less /tmp/box-setup.log e 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 tmux ou screen para obter várias sessões multiplexadas em uma conexão ssh. Use o mesmo comando less em outro shell.

O problema original:

tee pode copiar para vários destinos. Torne um deles o terminal, usando o arquivo /dev/tty special. Eu acho que sempre se refere ao controle do processo atual. Ou provavelmente melhor, para /dev/stderr , pois o stderr de tee 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, mas é mais eficiente que (tee /dev/stderr | tee "/tmp/box-setup.log" | logger ...) .

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

    
por 11.09.2016 / 03:06
1

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

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

Saída padrão e erro padrão serão mesclados. Não há como mantê-los separados se você quiser preservar o pedido deles, o que geralmente é desejável. Não importa se ambos estão indo para o mesmo lugar (por exemplo, o terminal) de qualquer maneira.

    
por 11.09.2016 / 01:33