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

14

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

Xster
fonte

Respostas:

17

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

Alguns comandos fornecerão um sinalizador (por exemplo, -quietou -silent) para suprimir a saída sem erro - leia suas páginas de manual para ver se existe alguma.


Outra convenção que é mantida 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 0indica 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 $statusvariável Você pode canalizar stderrpara um arquivo temporário e imprimi-lo apenas 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 encadeando 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 stdoutpara o mesmo buffer usando 2>&1 >/tmp/outputbuffer.

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

Se você precisar executar a coisa toda em segundo plano de um shell que também estiver 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) Heck, 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

Ligar com run-silent somecommand &(onde o final &faz com que seja executado em segundo plano)

Note que isto irá engolir o código de saída original, e vai despejar tanto stdoute stderrem 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 stdout- alguns programas despejam toda a saída 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.

Prumo
fonte
ligeiro ajuste de peixe, há um lugar especial para colocar funções em ~ / .config / peixe / funções /
Xster
12

Os utilitários Unix enviam mensagens gerais para stdout, e mensagens de erro para stderr, portanto, se queremos apenas ver mensagens de erro, será suficiente suprimir, stdoutpara que somente a stderrsaída seja obtida no console.

A maneira de fazer isso (nos dois bashe fish) é anexar >/dev/nullao comando. Isso leva o stdout ao nada, mas o stderr (com suas mensagens de erro) ainda chega ao console.

Então, por exemplo:

O comando echo 1 >/dev/nullimprime nada, porque a stdoutsaída normal é suprimida e nada foi gravado no stderr.

O comando man doesnotexist >/dev/nullimprime uma mensagem de erro, porque mangrava sua mensagem de erro em stderr.

Maximillian Laumeister
fonte
2

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

    command > /dev/null 2> /tmp/example_error.log &
Genkus
fonte