19

I'm watching different logs by

tail -q -f /var/log/syslog -f /var/log/fail2ban.log -f /var/log/nginx/error.log

How can I have the output of each log colored differently?

3

2 Answers 2

21

Using GNU grep for the colouring:

color() { GREP_COLOR=$1 grep --color '.*'; }

(tail -qf /var/log/syslog | color 31 &
tail -qf /var/log/fail2ban.log | color 32 &
tail -qf /var/log/nginx/error.log | color 33)

Note that the first 2 are started in background. That means they won't be killed if you press Ctrl-C (shell explicitly ignore SIGINT for asynchronous jobs).

To prevent that, you can do instead:

color() { GREP_COLOR=$1 grep --line-buffered --color=always '.*'; }

(tail -qf /var/log/syslog | color 31 &
tail -qf /var/log/fail2ban.log | color 32 &
tail -qf /var/log/nginx/error.log | color 33) | cat

That way, upon Ctrl-C, the last tail+grep and cat die (of the SIGINT) and the other two grep+tails will die of a SIGPIPE the next time they write something.

Or restore the SIGINT handler (won't work with all shells):

color() { GREP_COLOR=$1 grep --color '.*'; }

((trap - INT; tail -qf /var/log/syslog | color 31) &
(trap - INT; tail -qf /var/log/fail2ban.log | color 32) &
tail -qf /var/log/nginx/error.log | color 33)

You can also do it in the color function. That won't apply to tail, but tail will die of a SIGPIPE the next time it writes if grep dies.

color() (trap - INT; GREP_COLOR=$1 exec grep --color '.*')

(tail -qf /var/log/syslog | color 31 &
tail -qf /var/log/fail2ban.log | color 32 &
tail -qf /var/log/nginx/error.log | color 33)

Or make the whole tail+grep a function:

tailc() (trap - INT; export GREP_COLOR="$1"; shift; tail -qf -- "$@" |
   grep --color '.*')
tailc 31 /var/log/syslog &
tailc 32 /var/log/syslog &
tailc 33 /var/log/nginx/error.log

Or the whole thing:

tailc() (
  while [ "$#" -ge 2 ]; do
    (trap - INT; tail -f -- "$2" | GREP_COLOR=$1 grep --color '.*') &
    shift 2
  done
  wait
)

tailc 31 /var/log/syslog 32 /var/log/syslog 33 /var/log/nginx/error.log
3
  • When I put this into my "watch.sh" script, it returns to my console but messages get printed, see i.imgur.com/yaiBwMo.png
    – Daniel W.
    Commented Aug 19, 2014 at 11:34
  • @Dan, see the edit Commented Aug 19, 2014 at 12:24
  • Thank you for your effort in writing this answer, I gone with the tailc function which worked best and looks most intuitive in the script.
    – Daniel W.
    Commented Aug 19, 2014 at 12:37
4

Someting like this worked for me:

(tail -f /var/log/syslog | awk -W interactive '{printf "\033[1;31m%s\033[0m\n", $0}' & \
tail -f /var/log/auth.log | awk -W interactive '{printf "\033[1;32m%s\033[0m\n", $0}' & \
tail -f /var/log/Xorg.0.log | awk -W interactive '{printf "\033[1;34m%s\033[0m\n", $0}')

Explanation:

  • tail -f file: append data as file grows
  • awk -W interactive: set awk to interactive mode
  • '{printf "\033[1;31m%s\033[0m\n", $0}' print the output colorzized to the terminal.
  • \033[1;31m means red
  • \033[1;32m means green
  • \033[1;34m means blue
1
  • -W interactive seems to be mawk-specific. (the way mawk buffers its input by default is also unique, and -W interactive would not be needed in other awk implementations). Commented Aug 19, 2014 at 15:17

You must log in to answer this question.

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