How to have tail -f show colored output

  • I'd like to be able to tail the output of a server log file that has messages like:

    INFO
    SEVERE
    

    etc, and if it's SEVERE, show the line in red; if it's INFO, in green. What kind of alias can I setup for a tail command that would help me do this?

  • Try out multitail. This is an übergeneralization of tail -f. You can watch multiple files in separate windows, highlight lines based on their content, and more.

    multitail -c /path/to/log
    

    The colors are configurable. If the default color scheme doesn't work for you, write your own in the config file. For example, call multitail -cS amir_log /path/to/log with the following ~/.multitailrc:

    colorscheme:amir_log
    cs_re:green:INFO
    cs_re:red:SEVERE
    

    Another solution, if you're on a server where it's inconvenient to install non-standard tools, is to combine tail -f with sed or awk to add color selection control sequences. This requires tail -f to flush its standard output without delay even when its standard output is a pipe, I don't know if all implementations do this.

    tail -f /path/to/log | awk '
      /INFO/ {print "\033[32m" $0 "\033[39m"}
      /SEVERE/ {print "\033[31m" $0 "\033[39m"}
    '
    

    or with sed

    tail -f /path/to/log | sed --unbuffered \
        -e 's/\(.*INFO.*\)/\o033[32m\1\o033[39m/' \
        -e 's/\(.*SEVERE.*\)/\o033[31m\1\o033[39m/'
    

    If your sed isn't GNU sed, replace \o033 by a literal escape character and remove --unbuffered.

    Yet another possibility is to run tail -f in an Emacs shell buffer and use Emacs's syntax coloring abilities.

    how can you do this with `sed`? (sorry for being lazy and not figuring it out myself!) But would you please add a `sed` example as well.

    @Ali Sed is less convenient because it doesn't have a syntax for the escape character, you need to have it literally in the script or use a shell quoting method to work it in. I recommend that you use awk.

    @Gilles Thank you for sharing your knowledge. Though, is there a way to do this with *vim* as like *Emacs* does?

    @Gilles In your `tail -f` with `awk` code, if a string doesn't have *INFO* and *SEVERE*, the string isn't be printed. How can I print the *remain* strings either? (The string doesn't need to be colored)

    @Benjamin Add `; next` before the closing braces to skip further processing, and a new processing line `1 {print}` at the end (`1` means always).

    It works different to ccze and colortail in the way that each line is colored according to keywords (instead of terms, like: hostname, date-time,IP address, etc). For example, "SEVERE" keyword will make the whole line with red background and white text color. Using the default color scheme, looks very saturated of colors. Its better if you try it.

    the awk version worked well for what I needed. And on an XServe. thx

    I have a syntax error at `[` for the `awk` version.

    For `sed`, the problem is that it uses buffer, so I don't see the content appearing until the buffer is full. I've added `--unbuffered`.

    @OndraŽižka Only if you pipe it into something else, otherwise it's line-buffered.

    +1 for suggesting Emacs. Works well.

    `sed --unbuffered -e 's/\(.*FATAL.*\)/\o033[1;31m\1\o033[0;39m/' -e 's/\(.*ERROR.*\)/\o033[31m\1\o033[39m/' -e 's/\(.*WARN.*\)/\o033[33m\1\o033[39m/' -e 's/\(.*INFO.*\)/\o033[32m\1\o033[39m/' -e 's/\(.*DEBUG.*\)/\o033[34m\1\o033[39m/' -e 's/\(.*TRACE.*\)/\o033[30m\1\o033[39m/' -e 's/\(.*[Ee]xception.*\)/\o033[1;39m\1\o033[0;39m/'`

    My version of `sed` doesn't accept `--unbuffered`. Nor does it accept `\oNNN` sequences. For the latter, I had to use embedded `printf`s like here

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM