É possível redirecionar toda a saída de um script de shell Bourne para algum lugar, mas com comandos de shell dentro do próprio script?
Redirecionar a saída de um único comando é fácil, mas quero algo mais como este:
#!/bin/sh
if [ ! -t 0 ]; then
# redirect all of my output to a file here
fi
# rest of script...
Significado: se o script for executado de maneira não interativa (por exemplo, cron), salve a saída de tudo em um arquivo. Se executado interativamente a partir de um shell, deixe a saída ir para stdout, como de costume.
Eu quero fazer isso para um script normalmente executado pelo utilitário periódico FreeBSD. Faz parte da execução diária, que normalmente não me importo de ver todos os dias no email, por isso não o envio. No entanto, se algo dentro desse script em particular falhar, isso é importante para mim e eu gostaria de poder capturar e enviar por e-mail a saída dessa parte dos trabalhos diários.
Atualização: A resposta de Joshua é direta, mas eu também queria salvar e restaurar stdout e stderr em todo o script, o que é feito assim:
# save stdout and stderr to file descriptors 3 and 4, then redirect them to "foo"
exec 3>&1 4>&2 >foo 2>&1
# ...
# restore stdout and stderr
exec 1>&3 2>&4
exec 1>&3 2>&4 3>&- 4>&-
Respostas:
Abordando a questão como atualizada.
Os colchetes '{...}' fornecem uma unidade de redirecionamento de E / S. Os colchetes devem aparecer onde um comando pode aparecer - simplisticamente, no início de uma linha ou após ponto e vírgula. ( Sim, isso pode ser mais preciso; se você quiser reclamar, me avise. )
Você está certo de que pode preservar o stdout e o stderr originais com os redirecionamentos mostrados, mas geralmente é mais simples para as pessoas que precisam manter o script posteriormente para entender o que está acontecendo se você definir o escopo do código redirecionado, como mostrado acima.
As secções relevantes do manual do Bash são Agrupamento Comandos e I / O redirecionamento . As secções relevantes da especificação POSIX concha são comandos de compostos e de I / O de redireccionamento de . O Bash possui algumas notações extras, mas é semelhante à especificação do shell POSIX.
fonte
>>
. Algumas pessoas têm o hábito de>
. Anexar é sempre mais seguro e mais recomendado do que exagerar. Alguém escreveu um aplicativo que usa o comando de cópia padrão para exportar alguns dados para o mesmo destino.Normalmente, colocávamos um deles na parte superior do script ou perto dela. Os scripts que analisam suas linhas de comando fazem o redirecionamento após a análise.
Enviar stdout para um arquivo
com stderr
anexar stdout e stderr ao arquivo
Como Jonathan Leffler mencionou em seu comentário :
exec
tem dois trabalhos separados. O primeiro é substituir o shell atualmente em execução (script) por um novo programa. O outro está alterando os redirecionamentos de E / S no shell atual. Isso se distingue por não ter argumentoexec
.fonte
exec
tem dois trabalhos separados. Uma é substituir o script atual por outro comando, usando o mesmo processo - você especifica o outro comando como argumento paraexec
(e pode ajustar os redirecionamentos de E / S ao fazê-lo). A outra tarefa é alterar os redirecionamentos de E / S no script atual do shell sem substituí-lo. Essa notação se distingue por não ter um comando como argumento paraexec
. A notação nesta resposta é da variante "Somente E / S" - apenas altera o redirecionamento e não substitui o script que está sendo executado. (Oset
comando é semelhante multi-propósito.)exec > >(tee -a "logs/logdata.log") 2>&1
imprime os registros na tela, bem como escreve-los em um arquivoVocê pode transformar o script inteiro em uma função como esta:
então, no final do script, tenha o seguinte:
Como alternativa, você pode registrar tudo no arquivo de log a cada execução e ainda gerar o resultado para o stdout simplesmente fazendo:
fonte
Para salvar o stdout e o stderr originais, você pode usar:
Por exemplo, o código a seguir imprimirá "walla1" e "walla2" no arquivo de log (
a.txt
), "walla3" em stdout, "walla4" em stderr.fonte
exec 5>&1
eexec 6>&2
, usando a notação de redirecionamento de saída, em vez da notação de redirecionamento de entrada para as saídas. Você se sai bem porque, quando o script é executado a partir de um terminal, a entrada padrão também é gravável e a saída e o erro padrão são legíveis em virtude (ou é 'vício'?) De uma peculiaridade histórica: o terminal é aberto para leitura e gravação e a mesma descrição de arquivo aberto é usada para todos os três descritores de arquivo de E / S padrão.fonte