8

When automating a task, it is sensible to test it first manually. It would be helpful, though, if any data going to stderr was immediately recognizeable as such, and distinguishable from the data going to stdout, and to have all the output together so it is obvious what the sequence of events is.

One last touch that would be nice is if, at program exit, it printed its return code.

All of these things would aid in automating. Yes, I can echo the return code when a program finishes, and yes, I can redirect stdout and stderr; what I'd really like it some shell, script, or easy-to-use redirector that shows stdout in black, shows stderr interleaved with it in red, and prints the exit code at the end.

Is there such a beast? [If it matters, I'm using Bash 3.2 on Mac OS X].


Update: Sorry it has been months since I've looked at this. I've come up with a simple test script:

#!/usr/bin/env python
import sys

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

In my testing (and probably due to the way things are buffered), rse and hilite display everything from stdout and then everything from stderr. The fifo method gets the order right but appears to colourize everything following the stderr line. ind complained about my stdin and stderr lines, and then put the output from stderr last.

Most of these solutions are workable, as it is not atypical for only the last output to go to stderr, but still, it'd be nice to have something that worked slightly better.

1
  • If you are lazy (or have sore fingers) like me you can grab a subshell with the below solutions (e.g. rse zsh) and now all commands colorize stderr.
    – bias
    Apr 19, 2011 at 3:43

6 Answers 6

3

You can also check out stderred: https://github.com/sickill/stderred

3
  • Unfortunately, stderred breaks "open" and "mvim" for Mac users like the OP. Dec 26, 2011 at 8:45
  • 1
    This works very nicely, and gets the output order in the correct fashion due to the way it works. Set it up once, and turn it on in your profile, and you get red messages whenever stderr is written to. Oct 29, 2012 at 15:48
  • 1
    @JonRodriguez, it appears to me that the issue with the "open" command has been fixed. Oct 29, 2012 at 15:50
9

I just devised a crazy method involving FIFOs.

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

If you'd like the stderr output separate, you can open up two separate shells and run "grep --color . foo" in one without the &, then run the command in the other (still with the 2>foo). You'll get the stderr in the grep one and the stdout in the main one.

This works because the stderr output is routed through the FIFO into grep --color, whose default color is red (at least it is for me). When you're done, just rm the FIFO (rm foo).

Caveat: I'm really not sure how this will handle output order, you'll have to test it out.

1
7

Yes, this is possible. Look at the section "Make STDERR red" on this site for a working example.

The basic code is this

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

A brief explanation is given in the function itself. What is does is move STDOUT and STDERR about, so sed gets STDERR in 1, colors it, and then swaps it back. Think of file stream 3 as a temp variable here.

The call is pretty simple

rse commands

However, certain invocations will not work as expected; the caveats are all provided on the linked page.

Btw, I think it is also possible to come with a solution of the form

commands | rse 

where rse will colorize the output.

I also found this hilite project that seems to do this. I haven't tried it out, but it might be what you're looking for.

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.

Other related projects:

1
  • rse and hilite are pretty close to what I want. Apr 7, 2010 at 22:34
2

Here is a lot of responses for highlighting the stderr output yet. I can only add one pretty easy - in one row, which you attach to the command:

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

But you have to add this after command each time.

I, personally, like the possibility mentioned by @nagul , the rse function added to bashrc.

But I want to add the solution for printing the exit code. You can add this value to the beginning of your bash prompt row:

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

Where EC is exit code of the command.

I have it set in the way, that when the exit code is 0, it will be not printed, but any other value is printed before next prompt in red color.

The whole trick is done in ~/.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

The prompt line is by default defined by PS1 variable. Copy whatever you have here into the variable PROMPT and then create the PS1 variable with or without exit code.

Bash will show the information in PS1 variable in the prompt.

0
1

there's annotate-output utility (devscripts Debian package), if you would like to do it without colors

$ 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
1

Another program is ind:

http://www.habets.pp.se/synscan/programs.php?prog=ind There is a screenshot and even a screencast there.

It runs the subprocess in a pty, which the others probably don't. This can matter where order matters (it often does), since stderr is immediately flushed in terminals and stdout is fully buffered when it's not a tty.

For a full explanation, see this: http://blog.habets.pp.se/2008/06/Buffering-in-pipes

Also, ind works with interactive programs and control characters. Bash works just like normal when started with "ind bash -i".

This could work to give you colors while preserving Ctrl-P et.al.

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .