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?

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
  • 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. Aug 19 '14 at 11:34
  • @Dan, see the edit – Stéphane Chazelas Aug 19 '14 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. Aug 19 '14 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
  • -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). – Stéphane Chazelas Aug 19 '14 at 15:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.