Como executar um comando em segundo plano sem saída, a menos que haja um erro

13

Como suprimir a saída de um comando, mas mostrá-lo se a saída do comando codifica um erro?

    
por Xster 23.07.2015 / 05:13

3 respostas

17

Infelizmente, a suposição de que stderr é usado apenas para saída de erro nem sempre está correta. Em vez disso, stderr é frequentemente usado para toda e qualquer saída e diagnósticos interativos , ou seja, a saída destinada ao usuário para ler em um prompt interativo 1 . wget e dd são exemplos bem conhecidos.

Alguns comandos fornecerão um sinalizador (por exemplo, -quiet ou -silent ) para suprimir a saída sem erros - leia as man pages para ver se existe alguma.

Outra convenção que detém com mais frequência é o código de saída : um programa retorna um código de saída quando sai. Normalmente 2 , um código de saída de 0 indica sucesso e qualquer outro código de saída indica um erro.

Com bash , você pode obter o código de saída do último comando da variável $? . Em fish , use a variável $status . Você pode canalizar stderr para um arquivo temporário e imprimi-lo somente se ocorrer um erro. Por exemplo ( fish ):

command 2>/tmp/outputbuffer
if $status
    cat /tmp/outputbuffer
rm /tmp/outputbuffer

Você também pode usar alguns atalhos, se não estiver comandando comandos:

if command 2>/tmp/outputbuffer
    cat /tmp/outputbuffer
rm /tmp/outputbuffer

Ou:

command 2>/tmp/outputbuffer; or cat /tmp/outputbuffer; rm /tmp/outputbuffer;

Você também pode canalizar stdout para o mesmo buffer usando 2>&1 >/tmp/outputbuffer .

(Nota: Eu não sei realmente fish , então eu estou adaptando o conceito para o que eu posso encontrar em sua documentação. A sintaxe pode estar um pouco errada. Além disso, você pode usar mktemp para gerar um arquivo temporário exclusivo - execute-o e registre o nome do arquivo em uma variável.)

Se você precisar executar a coisa toda no plano de fundo de um shell que também está usando interativamente ao mesmo tempo, é melhor escrever um script para lidar com a ocultação de saída e executar esse script em segundo plano com as técnicas padrão ( fish ). Poxa, você pode colocar algo como a seguinte função em ~/.config/fish/config.fish :

function run-silent
    set temp (mktemp)
    if $argv 2>&1 >$temp
        cat $temp
    rm $temp
end

Chame com run-silent somecommand & (onde o & à direita faz com que seja executado em segundo plano)

Observe que isso engolirá o código de saída original e despejará os stdout e stderr no caso de uma falha. Você pode personalizá-lo conforme necessário.

1 Não há garantia de que a saída de erro não apareça em stdout - alguns programas descarregarão todas as saídas de lá!

2 Infelizmente, isso nem sempre é o caso - o código de saída é completamente controlado pelo programa, e alguns indicarão algumas condições de sucesso com saídas diferentes de zero. Mais uma vez, verifique o manual.

    
por 23.07.2015 / 08:10
12

Utilitários Unix enviam mensagens gerais para stdout e mensagens de erro para stderr , portanto, se quisermos ver apenas mensagens de erro, será suficiente para suprimir stdout , de modo que somente stderr seja enviado para o console.

A maneira de fazer isso (em bash e fish ) é anexar >/dev/null ao comando. Isso canaliza stdout para o nada, mas o stderr (com suas mensagens de erro) ainda chega ao console.

Então, por exemplo:

O comando echo 1 >/dev/null não imprime nada, porque a saída normal stdout é suprimida e nada foi gravado em stderr.

O comando man doesnotexist >/dev/null imprime uma mensagem de erro porque man grava sua mensagem de erro em stderr .

    
por 23.07.2015 / 05:34
2

Isso executará o comando em segundo plano e gravará erros em um arquivo de log enquanto ignora a saída normal

    command > /dev/null 2> /tmp/example_error.log &
    
por 23.07.2015 / 09:43

Tags