Informe imediatamente qual saída foi enviada ao stderr


8

Ao automatizar uma tarefa, é sensato testá-la primeiro manualmente. Seria útil, no entanto, se algum dado que fosse armazenado no stderr fosse imediatamente reconhecido como tal, e distinguível dos dados que armazenassem o stdout, e ter toda a saída juntos, para que fique óbvio qual é a sequência de eventos.

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

Todas essas coisas ajudariam na automação. Sim, eu posso ecoar o código de retorno quando um programa termina, e sim, eu posso redirecionar stdout e stderr; o que eu realmente gostaria de algum 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 uma fera assim? [Se importa, estou usando o Bash 3.2 no Mac OS X].


Atualização : Desculpe, já faz meses desde que eu olhei para isso. Eu vim com 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"

Nos meus testes (e provavelmente devido à maneira como as coisas são armazenadas em buffer), o rse e o hilite exibem tudo, desde stdout e, em seguida, tudo sobre stderr. O método fifo acerta a ordem, mas parece colorir tudo que segue a linha stderr. ind reclamou das minhas linhas stdin e stderr e depois colocou a saída do stderr por último.

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


Se você é preguiçoso (ou tem dedos doloridos) como eu, pode pegar um subshell com as soluções abaixo (por exemplo, rse zsh) e agora todos os comandos colorem o stderr.
viés

Respostas:


3

Você também pode conferir stderred: https://github.com/sickill/stderred


Infelizmente, as interrupções stderred "abrem" e "mvim" para usuários de Mac como o OP.
AlcubierreDrive

Isso funciona muito bem e obtém a ordem de saída da maneira correta devido à maneira como funciona. Configure-o uma vez, ative-o no seu perfil e você receberá mensagens em vermelho sempre que o stderr for gravado.
Clinton Blackmore


9

Eu apenas inventei um método maluco envolvendo FIFOs.

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

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

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

Advertência : Eu realmente não tenho certeza de como isso irá lidar com a ordem de saída, você terá que testá-la.


Isso é bem liso.
Clinton Blackmore

7

Sim, isso é possível. Veja a seção "Tornar o STDERR vermelho" 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\1$(echo -en \\033)[0m/") 3>&1 1>&2 2>&3
}

Uma breve explicação é dada na própria função. O que é preciso é mover STDOUT e STDERR, para que o sed coloque STDERR em 1, colore e cole novamente. Pense no fluxo de arquivos 3 como uma variável temporária aqui.

A ligação é bem simples

rse commands

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

Aliás, acho que também é possível vir com uma solução da forma

commands | rse 

onde rse colorirá a saída.

Eu também encontrei esse projeto hilite que parece fazer isso. Ainda não experimentei, mas pode ser o que você está procurando.

O hilite é um pequeno utilitário que executa o comando que você especificar, destacando qualquer coisa impressa no stderr. Ele foi projetado principalmente para uso em construções, para fazer com que avisos e erros se destacem como um clichê dolorido.

Outros projetos relacionados:


rse e hilite estão bem próximos do que eu quero.
Clinton Blackmore

1

Outro programa é ind:

http: // www.habets.pp.se/synscan/programs.php?prog=ind (você precisa montar o hiperlink por conta própria, não tenho pontos suficientes para mais de um por resposta). Há uma captura de tela e até um screencast lá.

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

Para uma explicação completa, consulte o seguinte: http://blog.habets.pp.se/2008/06/Buffering-in-pipes

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

Isso pode funcionar para fornecer cores e preservar Ctrl-P et.al.

ind -P $(echo -ne '\033[31;1m') -p $(echo -ne '\033[0m') bash -i

1

Aqui estão muitas respostas para destacar a saída stderr ainda. Só posso adicionar uma bem 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ê deve adicionar este comando após cada vez.

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 esse valor ao início da linha do prompt do bash:

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

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

Tenho definido da maneira que, quando o código de saída for 0, ele não será impresso, mas qualquer outro valor será impresso antes do próximo prompt na cor vermelha.

Todo o truque é feito em ~ / .bashrc:

my_prompt() {
 EXITSTATUS="$?"
 RED="\[\033[1;31m\]"
 OFF="\[\033[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 você tem aqui na variável PROMPT e, em seguida, crie a variável PS1 com ou sem código de saída.

O Bash mostrará as informações na variável PS1 no prompt.


Era exatamente isso que eu procurava, obrigado!
quer

1

existe annotate-outpututilidade ( devscriptspacote 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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.