Indique imediatamente qual saída foi enviada para stderr

8

Ao automatizar uma tarefa, é sensato testá-la primeiro manualmente. Seria útil, entretanto, se algum dado que vai para stderr fosse imediatamente reconhecível como tal, e distinguível dos dados indo para stdout, e ter toda a saída em conjunto, então é óbvio qual é a sequência de eventos.

Um último toque seria legal se, na saída do programa, ele imprimisse seu código de retorno.

Todas essas coisas ajudariam na automação. Sim, posso ecoar o código de retorno quando um programa termina, e sim, posso redirecionar stdout e stderr; O que eu realmente gosto é que um shell, script ou redirecionador fácil de usar que mostre stdout em preto, mostre stderr intercalado com ele em vermelho e imprima o código de saída no final.

Existe tal animal? [Se isso importa, estou usando o Bash 3.2 no Mac OS X].

Update : Desculpe, faz meses desde que eu olhei para isso. Eu criei um script de teste simples:

#!/usr/bin/env python
import sys

print "this is stdout"
print >> sys.stderr, "this is stderr"
print "this is stdout again"

No meu teste (e provavelmente devido ao modo como as coisas são armazenadas em buffer), o rse e o hilite exibem tudo, desde stdout e depois tudo de stderr. O método fifo obtém a ordem certa, mas parece colorir tudo seguindo a linha stderr. ind reclamou das minhas linhas stdin e stderr, e depois colocou a saída de stderr por último.

A maioria dessas soluções é viável, já que não é atípico que apenas a última saída vá para stderr, mas ainda assim, seria bom ter algo que funcionasse um pouco melhor.

    
por Clinton Blackmore 24.08.2009 / 18:16

6 respostas

3

Você também pode conferir o stderred: link

    
por 13.12.2011 / 22:42
9

Acabei de criar um método maluco envolvendo FIFOs.

$ mkfifo foo
$ grep --color . foo &
$ your_command 2>foo

Se quiser que a saída do stderr seja separada, você pode abrir dois shells separados e executar " grep --color . foo " em um sem o & , em seguida, executar o comando no outro (ainda com o 2>foo ) . Você obterá o stderr no grep one e o stdout no principal.

Isso funciona porque a saída stderr é roteada pelo FIFO em grep --color , cuja cor padrão é vermelha (pelo menos é para mim). Quando estiver pronto, apenas rm do FIFO ( rm foo ).

Ressalva : não sei ao certo como isso lidará com a ordem de saída, você terá que testá-la.

    
por 24.08.2009 / 23:11
7

Sim, isso é possível. Olhe para a seção "Make STDERR red" neste site para um exemplo de trabalho.

O código básico é este

# Red STDERR
# rse <command string>
function rse()
{
    # We need to wrap each phrase of the command in quotes to preserve arguments that contain whitespace
    # Execute the command, swap STDOUT and STDERR, colour STDOUT, swap back
    ((eval $(for phrase in "$@"; do echo -n "'$phrase' "; done)) 3>&1 1>&2 2>&3 | sed -e "s/^\(.*\)$/$(echo -en \033)[31;1m$(echo -en \033)[0m/") 3>&1 1>&2 2>&3
}

Uma breve explicação é dada na própria função. O que é fazer é mover STDOUT e STDERR sobre, então sed obtém STDERR em 1, colore-o e depois o troca de volta. Pense no fluxo de arquivos 3 como uma variável temporária aqui.

A chamada é bem simples

rse commands

No entanto, certas invocações não funcionarão como esperado; as advertências são todas fornecidas na página vinculada.

Btw, acho que também é possível vir com uma solução do formulário

commands | rse 

onde rse irá colorir a saída.

Também encontrei este projeto hilite que parece fazer isso. Eu não tentei, mas pode ser o que você está procurando.

hilite is a tiny utility which executes the command you specify, highlighting anything printed to stderr. It is designed mainly for use with builds, to make warnings and errors stick out like a sore cliche.

Outros projetos relacionados:

por 24.08.2009 / 20:30
1

Outro programa é ind:

link

Ele executa o subprocesso em um arquivo, que os outros provavelmente não executam. Isso pode importar onde a ordem é importante (geralmente acontece), uma vez que o stderr é imediatamente liberado nos terminais e o stdout é totalmente armazenado em buffer quando não é um tty.

Para uma explicação completa, veja isto: link

Além disso, o ind funciona com programas interativos e caracteres de controle. O Bash funciona como o normal quando iniciado com "ind bash -i".

Isso pode funcionar para dar cores enquanto preserva Ctrl-P et.al.

ind -P $(echo -ne '3[31;1m') -p $(echo -ne '3[0m') bash -i
    
por 24.08.2009 / 22:36
1

Aqui estão muitas respostas para destacar a saída do stderr ainda. Eu só posso adicionar um muito fácil - em uma linha, que você anexa ao comando:

command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m"; done)

Mas você precisa adicionar isso após o comando a cada vez.

Eu, pessoalmente, gosto da possibilidade mencionada por @nagul, a função rse adicionada ao bashrc.

Mas quero adicionar a solução para imprimir o código de saída. Você pode adicionar este valor ao início da sua linha de prompt do bash:

hostname$ command
  Some error occurred. Returned exit code.
EC hostname$

Em que EC é o código de saída do comando.

Eu tenho isso definido no caminho, que quando o código de saída é 0, ele não será impresso, mas qualquer outro valor será impresso antes do próximo prompt na cor vermelha.

O truque todo é feito em ~ / .bashrc:

my_prompt() {
 EXITSTATUS="$?"
 RED="\[3[1;31m\]"
 OFF="\[3[m\]"

PROMPT="${debian_chroot:+($debian_chroot)}\h \$ "

if [ "${EXITSTATUS}" -eq 0 ]; then
   PS1="${PROMPT}"
else
   PS1="${RED}$EXITSTATUS${OFF} ${PROMPT}"
fi
}

PROMPT_COMMAND=my_prompt

A linha de prompt é definida por padrão pela variável PS1. Copie o que tiver aqui para a variável PROMPT e crie a variável PS1 com ou sem o código de saída.

Bash mostrará a informação na variável PS1 no prompt.

    
por 19.01.2012 / 11:29
1

annotate-output utility ( devscripts pacote Debian), se você quiser fazê-lo sem cores

$ annotate-output /tmp/test.py    
14:24:57 I: Started /tmp/test.py
14:24:57 E: this is stderr
14:24:57 O: this is stdout
14:24:57 O: this is stdout again
14:24:57 I: Finished with exitcode 0
    
por 04.10.2013 / 14:31