Dites immédiatement quelle sortie a été envoyée à stderr

8

Lors de l'automatisation d'une tâche, il est judicieux de la tester d'abord manuellement. Il serait utile, cependant, si des données allant vers stderr soient immédiatement reconnaissables en tant que telles, et se distinguent des données allant vers stdout, et d'avoir toutes les sorties ensemble afin qu'il soit évident quelle est la séquence des événements.

Une dernière touche qui serait bien si, à la sortie du programme, il imprimait son code retour.

Toutes ces choses aideraient à automatiser. Oui, je peux faire écho au code retour à la fin d'un programme, et oui, je peux rediriger stdout et stderr; ce que j'aimerais vraiment un shell, un script ou un redirecteur facile à utiliser qui montre stdout en noir, montre stderr entrelacé avec lui en rouge et imprime le code de sortie à la fin.

Y a-t-il une telle bête? [Si cela importe, j'utilise Bash 3.2 sur Mac OS X].


Mise à jour : Désolé, cela fait des mois que je n'ai pas regardé ça. Je suis venu avec un script de test simple:

#!/usr/bin/env python
import sys

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

Dans mes tests (et probablement en raison de la façon dont les choses sont tamponnées), rse et hilite affichent tout depuis stdout puis tout depuis stderr. La méthode fifo obtient l'ordre correct mais semble tout coloriser en suivant la ligne stderr. ind s'est plaint de mes lignes stdin et stderr, puis a mis la sortie de stderr en dernier.

La plupart de ces solutions sont réalisables, car il n'est pas atypique que seule la dernière sortie soit envoyée à stderr, mais ce serait quand même bien d'avoir quelque chose qui fonctionne un peu mieux.

Clinton Blackmore
la source
Si vous êtes paresseux (ou avez des doigts endoloris) comme moi, vous pouvez prendre un sous-shell avec les solutions ci-dessous (par exemple rse zsh) et maintenant toutes les commandes colorisent stderr.
biais

Réponses:

3

Vous pouvez également consulter stderred: https://github.com/sickill/stderred

malade malade
la source
Malheureusement, stderred rompt "open" et "mvim" pour les utilisateurs Mac comme l'OP.
AlcubierreDrive
Cela fonctionne très bien et obtient l'ordre de sortie de la bonne façon en raison de la façon dont cela fonctionne. Configurez-le une fois et activez-le dans votre profil, et vous obtenez des messages rouges chaque fois que stderr est écrit.
Clinton Blackmore
1
@JonRodriguez, il me semble que le problème avec la commande "open" a été corrigé .
Clinton Blackmore
9

Je viens de concevoir une méthode folle impliquant des FIFO.

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

Si vous souhaitez que la sortie stderr soit séparée, vous pouvez ouvrir deux shells distincts et exécuter " grep --color . foo" dans l'un sans le &, puis exécuter la commande dans l'autre (toujours avec le 2>foo). Vous obtiendrez le stderr dans l' grepun et le stdout dans le principal.

Cela fonctionne parce que la sortie stderr est acheminée via le FIFO vers grep --color, dont la couleur par défaut est le rouge (du moins c'est pour moi). Lorsque vous avez terminé, juste rmle FIFO ( rm foo).

Attention : je ne sais vraiment pas comment cela va gérer l'ordre de sortie, vous devrez le tester.

jtbandes
la source
C'est assez lisse.
Clinton Blackmore
7

Oui, c'est possible. Regardez la section "Rendre STDERR rouge" sur ce site pour un exemple de travail.

Le code de base est le suivant

# 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
}

Une brève explication est donnée dans la fonction elle-même. Ce qui est fait, c'est déplacer STDOUT et STDERR, donc sed obtient STDERR en 1, le colore, puis le remplace. Considérez le flux de fichiers 3 comme une variable temporaire ici.

L'appel est assez simple

rse commands

Cependant, certaines invocations ne fonctionneront pas comme prévu; les mises en garde sont toutes fournies sur la page liée.

Btw, je pense qu'il est également possible de venir avec une solution de la forme

commands | rse 

où rse colorisera la sortie.

J'ai aussi trouvé ce projet hilite qui semble faire ça. Je ne l'ai pas essayé, mais c'est peut-être ce que vous cherchez.

hilite est un petit utilitaire qui exécute la commande que vous spécifiez, mettant en évidence tout ce qui est imprimé sur stderr. Il est principalement conçu pour être utilisé avec des builds, pour faire ressortir les avertissements et les erreurs comme un cliché douloureux.

Autres projets connexes:


la source
rse et hilite sont assez proches de ce que je veux.
Clinton Blackmore
1

Un autre programme est ind:

http: // www.habets.pp.se/synscan/programs.php?prog=ind (vous devez assembler l'hyperlien vous-même, je n'ai pas assez de points pour plus d'un par réponse). Il y a une capture d'écran et même une capture d'écran.

Il exécute le sous-processus dans un pty, ce que les autres ne font probablement pas. Cela peut être important là où l'ordre est important (c'est souvent le cas), car stderr est immédiatement vidé dans les terminaux et stdout est entièrement tamponné lorsqu'il n'est pas un tty.

Pour une explication complète, voir ceci: http://blog.habets.pp.se/2008/06/Buffering-in-pipes

En outre, ind fonctionne avec des programmes interactifs et des caractères de contrôle. Bash fonctionne comme d'habitude lorsqu'il est lancé avec "ind bash -i".

Cela pourrait fonctionner pour vous donner des couleurs tout en préservant Ctrl-P et.al.

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

Voici beaucoup de réponses pour mettre encore en évidence la sortie stderr. Je ne peux ajouter qu'un seul assez facile - dans une ligne, que vous attachez à la commande:

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

Mais vous devez ajouter ceci après la commande à chaque fois.

Personnellement, j'aime la possibilité mentionnée par @nagul, la fonction rse ajoutée à bashrc.

Mais je veux ajouter la solution pour imprimer le code de sortie. Vous pouvez ajouter cette valeur au début de votre ligne d'invite bash:

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

Où EC est le code de sortie de la commande.

Je l'ai défini de la manière suivante: lorsque le code de sortie est 0, il ne sera pas imprimé, mais toute autre valeur sera imprimée avant la prochaine invite en couleur rouge.

L'astuce se fait dans ~ / .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

La ligne d'invite est définie par défaut par la variable PS1. Copiez tout ce que vous avez ici dans la variable PROMPT, puis créez la variable PS1 avec ou sans code de sortie.

Bash affichera les informations de la variable PS1 à l'invite.

srnka
la source
C'est exactement ce que je cherchais, merci!
Dylon
1

il y a un annotate-outpututilitaire ( devscriptspaquet Debian), si vous voulez le faire sans couleurs

$ 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
mykhal
la source