Bash – Configure Shell to Print STDERR and STDOUT in Different Colors

bashcolorsstderrstdoutterminal

I want to set my terminal up so stderr is printed in a different color than stdout; maybe red. This would make it easier to tell the two apart.

Is there a way to configure this in .bashrc? If not, is this even possible?


Note: This question was merged with another that asked for stderr, stdout and the user input echo to be output in 3 different colours. Answers may be addressing either question.

Best Answer

This is a harder version of Show only stderr on screen but write both stdout and stderr to file.

The applications running in the terminal use a single channel to communicate with it; the applications have two output ports, stdout and stderr, but they're both connected to the same channel.

You can connect one of them to a different channel, add color to that channel, and merge the two channels, but this will cause two problems:

  • The merged output may not be exactly in the same order as if there had been no redirection. This is because the added processing on one of the channel takes (a little) time, so the colored channel may be delayed. If any buffering is done, the disorder will be worse.
  • Terminals use color changing escape sequences to determine the display color, e.g. ␛[31m means “switch to red foreground”. This means that if some output destined to stdout arrives just as some output for stderr is being displayed, the output will be miscolored. (Even worse, if there's a channel switch in the middle of an escape sequence, you'll see garbage.)

In principle, it would be possible to write a program that listens on two ptys¹, synchronously (i.e. won't accept input on one channel while it's processing output on the other channel), and immediately outputs to the terminal with appropriate color changing instructions. You'd lose the ability to run programs that interact with the terminal. I don't know of any implementation of this method.

Another possible approach would be to cause the program to output the proper color changing sequences, by hooking around all the libc functions that call the write system call in a library loaded with LD_PRELOAD. See sickill's answer for an existing implementation, or Stéphane Chazelas's answer for a mixed approach that leverages strace.

In practice, if that's applicable, I suggest redirecting stderr to stdout and piping into a pattern-based colorizer such as colortail or multitail, or special-purpose colorizers such as colorgcc or colormake.

¹ pseudo-terminals. Pipes wouldn't work because of buffering: the source could write to the buffer, which would break the synchronicity with the colorizer.

Related Question