Como redirecionar a saída e sair em caso de falha no comando?

Como redirecionar a saída e sair em caso de falha no comando?

É assim que registro stdout e stderr em meus scripts (geralmente cronjobs):

#!/bin/bash
mylog() {
    echo "[`date '+%Y-%m-%d %H:%M:%S'`] $1"
}
(
mylog 'start'

some-command || mylog 'error' && exit 1

mylog 'end'
) >> /var/log/my-log.log 2>&1

Em alguns scripts eu uso return em vez de exit e funciona bem, mas agora diz que não posso usar return a menos que inclua o script com src ou use-o em uma função. Então mudei para sair, mas o problema é que ele não registra nada, parece que interrompe o redirecionamento de saída >>. Outro problema é que não poderei incluí-lo posteriormente com o src, pois só quero parar esse script, não tudo.

Eu uso o redirecionamento de saída porque quero registrar tudo, mesmo que nenhum erro tenha ocorrido. E às vezes os comandos nem retornam códigos de saída adequados, então não posso confiar nisso.

Então, como posso 'retornar' em caso de erro? Conheço 'set -e', mas prefiro ter mais controle sobre quando parar o script.

Alguma ideia?

Responder1

Não consigo explicar o comportamento que você está enfrentando, mas aqui está uma solução possível:

#!/bin/bash
meulog() {
    echo "[$(data '+%Y-%m-%d %H:%M:%S')] $1"
}

meu principal() {
    (
        meulog 'iniciar'

        algum comando || mylog 'erro' && retorno 1

        meulog 'fim'
    ) >> /var/log/my-log.log 2>&1
}

meu principal

Como alternativa, remova o redirecionamento da mymaindefinição da função e coloque-o na mymainchamada da função:

mymain >> /var/log/my-log.log 2>&1

(Você também deve ser capaz de excluir os parênteses da mymaindefinição da função.) Alternativamente, como você deseja que o IO seja redirecionado para ointeiroscript, você pode separar o redirecionamento das instruções de ação:

exec >> /var/log/my-log.log
executivo 2>&1
meu principal

Como não entendo por que sua abordagem está falhando, não posso explicar por que qualquer uma das opções acima tem maior probabilidade de funcionar conforme desejado. No entanto, são maneiras ligeiramente diferentes de fazer a mesma coisa e isso pode ser suficiente. A propósito, mudei `date …`para $(date …)apenas por motivos gerais; Não acredito que isso tenha algo a ver com o seu problema.

Responder2

Que tal usar o screencomando no Linux? Isso seria um truque, a menos que você esteja decidido a programar uma solução sozinho.

informação relacionada