Como saber se a saída de um comando ou script de shell é stdout ou stderr

31

Digamos que eu execute um comando ou script de shell e me dê saída. Sem conhecer as partes internas desse comando ou script de shell, como determinar se a saída é de stderr ou stdout ?

Por exemplo,

$ ls -ld /
drwxrwxr-t  35 root  admin  1258 Dec 11 19:16 /

vs

ls -ld /test
ls: /test: No such file or directory

Como posso verificar se o primeiro comando foi impresso em stdout e o segundo em stderr (foi?)?

    
por KM. 23.02.2015 / 23:10

7 respostas

18

Não há como saber quando a saída já foi impressa. Nesse caso, tanto stdout como stderr estão conectados ao terminal, portanto, as informações sobre qual fluxo foi gravado já estavam perdidas no momento em que o texto apareceu em seu terminal; eles foram combinados pelo programa antes de chegar ao terminal.

O que você pode fazer, em um caso como o acima, seria executar o comando com stdout e stderr redirecionado para lugares diferentes e ver o que acontece. Ou execute-o duas vezes, uma vez com stdout redirecionado para /dev/null e uma vez com stderr redirecionado para /dev/null e veja quais desses casos resultam na exibição do texto.

Você pode redirecionar stdout para /dev/null alinhando >/dev/null no final da linha de comando e pode redirecionar stderr para /dev/null adicionando 2>/dev/null .

    
por 23.02.2015 / 23:33
7

Você pode redirecionar o stdout usando > file e redirecionar o stderr usando 2> file . Muitos shells modernos suportam o redirecionamento para comandos, portanto, você pode usar sed para destacar qual saída vem de qual fluxo:

$ ls 2> >(sed 's/^/2: /') > >(sed 's/^/1: /')
1: unity_support_test.0
1: vmwareDnD

$ ls foo 2> >(sed 's/^/2: /') > >(sed 's/^/1: /')
2: ls: cannot access foo: No such file or directory
    
por 24.02.2015 / 01:11
5

O script annotate-output do devscripts do Debian permite que você faça isso de maneira seletiva:

$ annotate-output ls -ld /test
14:54:22 -: Started ls -ld /test
14:54:22 E: ls: cannot access /test: No such file or directory
14:54:22 -: Finished with exitcode 2

A segunda coluna indica stdout e stderr com O e E , respectivamente.

Existem algumas ressalvas, sendo a principal como foi observado nas outras respostas: você não pode fazer isso depois do fato. Nem o shell nem o terminal estão cientes de como um programa arbitrário usa seus descritores de arquivos, embora o shell seja responsável por configurá-los inicialmente.

Esse método usa fifos, escrever para um fifo pode se comportar de maneira diferente de escrever para um tty, e escrever para dois fifos diferentes é definitivamente diferente (possíveis problemas de temporização / intercalação). Além disso, não é adequado para uso interativo, por ex. annotate-output bash não é um ótimo plano, mas é útil para muitos outros propósitos. Existem muitos, muitos exemplos de scripts e funções do shell em respostas a perguntas relacionadas sobre a colorização de stdin / stdout / stderr, o mais robusto é stderrd que usa modificação em tempo de execução de programas (a maioria) para modificar dados gravados em stderr.

Esta pergunta à qual o Anko está vinculado tem boas respostas sobre o tema relacionado: colorindo a saída stdout / stderr: Posso configurar o meu shell para imprimir STDERR e STDOUT em cores diferentes?

    
por 24.02.2015 / 14:30
1

Além das outras respostas, é interessante apontar para /proc/$PID/fd (embora não responda à pergunta):

$ cat > /dev/null 2> /tmp/blablah &
[1] 3073

[1]+  Stopped                 cat > /dev/null 2> /tmp/blablah
$ ls -l /proc/3073/fd
total 0
lrwx------ 1 kampde kampde 64 Feb 24 11:43 0 -> /dev/pts/33
l-wx------ 1 kampde kampde 64 Feb 24 11:43 1 -> /dev/null
l-wx------ 1 kampde kampde 64 Feb 24 11:43 2 -> /tmp/blablah

Como você pode ver, aqui você pode ver os descritores de arquivos abertos para um processo. 0 é o STDIN , 1 é o STDOUT e 2 é o STDERR . Se você não tivesse o STDOUT ou STDERR redirecionado, você veria /dev/pts/33 (neste exemplo, pelo menos) porque eles apontariam para o terminal.

notas : /proc/$PID existe apenas para processos em execução. Nesse caso, usei cat sem argumentos, portanto, não termina até eu fechar o STDIN . Eu também executei em segundo plano, então eu tenho o PID imediatamente por causa deste exemplo.

    
por 24.02.2015 / 11:50
0

Não está claro o que você está perguntando, mas isso pode ajudar

ls -ld /
echo $?    # Exit status 0 returned because command executed successfully.

ls -ld /test
echo $?    # Non-zero exit status returned -- command failed to execute

Fonte

Se o código de saída for 0, significa simplesmente que o comando foi executado corretamente (stdout), aqui você pode encontrar significados se o código de saída for diferente de 0 (stderr)

    
por 23.02.2015 / 23:24
0

Normalmente STDERR terá o nome do programa anexado à mensagem com dois pontos.

Exemplo:

rpm -zq some_utils 
rpm: -zq: unknown option

Vs

rpm -ql some_utils 
package some_utils is not installed
    
por 15.09.2017 / 11:02
-1

Para capturar e testar a saída de erros:

ls -l test 2>errors
if [ -s errors ]; then echo "There were errors:" && cat errors; fi
rm errors
    
por 03.03.2015 / 04:26