4

I'm trying to find a way (through escape characters or software) to display coloured lines in my php error log.

Right now I'm reading from them (live) with

tail -n 50 -f /var/log/apache2/error.log

which is great but I'd love to be able to error_log() certain lines to be red, for example, flag an authentication error. Is there any way to do this?

I'm using PHP 5.3 on Ubuntu 12.04

3 Answers 3

6

I have written a little Perl script that changes the colors of text matching a user defined regular expression. Here's the script:

#!/usr/bin/env perl
use Getopt::Std;
use strict;
use Term::ANSIColor; 

my %opts;
getopts('hic:l:',\%opts);
    if ($opts{h}){
      print<<EoF; 
Use -l to specify the pattern(s) to highlight. To specify more than one 
pattern use commas. 

-l : A Perl regular expression to be colored. Multiple expressions can be
     passed as comma separated values: -l foo,bar,baz
-i : makes the search case sensitive
-c : comma separated list of colors;

EoF
      exit(0);
    }

my $case_sensitive=$opts{i}||undef;
my @color=('bold red','bold blue', 'bold yellow', 'bold green', 
           'bold magenta', 'bold cyan', 'yellow on_magenta', 
           'bright_white on_red', 'bright_yellow on_red', 'white on_black');
if ($opts{c}) {
   @color=split(/,/,$opts{c});
}
my @patterns;
if($opts{l}){
     @patterns=split(/,/,$opts{l});
}
else{
    $patterns[0]='\*';
}

# Setting $| to non-zero forces a flush right away and after 
# every write or print on the currently selected output channel. 
$|=1;

while (my $line=<>) 
{ 
    for (my $c=0; $c<=$#patterns; $c++){
    if($case_sensitive){
        if($line=~/$patterns[$c]/){
           $line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ge;
        }
    }
    else{
        if($line=~/$patterns[$c]/i){
          $line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ige;
        }
      }
    }
    print STDOUT $line;
}

If you save it as color in a directory that is in your $PATH and make it executable (chmod +x /usr/bin/color), you can color lines from your error log like this:

tail -f -n 50 /var/log/apache2/error.log | color -l "\[error\]","\[notice\]"

As written, the script has predefined colors for 10 different patterns, so giving it a comma separated list as I have in the example above will color each of the patterns matched in a different color.

enter image description here

2
  • +1 for a great script/answer. I would love to add another +1 for properly invoking perl via env.
    – Hennes
    Commented Jul 3, 2013 at 15:20
  • Hope you didn't write this just for the question :P Thanks, just what I was looking for Commented Jul 3, 2013 at 15:54
6

In addition to @terdon's fancy script with multiple colors, here is a more simple possibility -- given you are satisfied with only one color (red):

tail -n 50 -f /var/log/apache2/error.log | grep --color -P 'error|'
  • --color obviously tells grep to color its output
  • -P activates Perl Compatible Regular Expressions
  • the only tricky part is |: This is the logical OR, so foo|bar matches either "foo" or "bar". Here the regex is closed right after this operator, so it matches the empty string. That way lines without "error" simply get printed (without any coloring)

Note: Probably not all versions of grep support both options, --color and -P, but with a recent GNU grep it should work (tested with GNU grep 2.6.3).

3
  • +1 for the |, what a clever idea. I had toyed with using grep for this but thought I could only select matching lines.
    – terdon
    Commented Jul 3, 2013 at 16:28
  • @terdon: Thanks, but it was you who taught me about the empty string in perl :)
    – mpy
    Commented Jul 3, 2013 at 21:33
  • Perhaps, but it was you who thought f this application :)
    – terdon
    Commented Jul 4, 2013 at 11:33
4

sed can be used for this.

apache-log-error.sed (copy and paste)

s/\[notice\]/[33m&[30m/
s/\[error\].*/[31m&[30m/

Run with:

cat error.log | sed -f apache-log-error.sed

You can remove the .* after \[error\] if you don't want the whole line colored.

If you want to do this on the command line you can use

cat error.log | sed -e 's/\[notice\]/\'$'\033[33m&\033[30m/' -e 's/\[error\].*/\'$'\033[31m&\033[30m/'

This can be turned into an alias or a shell script for convenience.

In the first example, typing ^[[33m into vim requires you type Ctrl+v then Escape to embed ascii value 27 (shown here as "^[") in the file. "[33m" can be typed in normally. In the second example, '$'\033 is something you type normally, and bash translates that into the ascii value 27.

You must log in to answer this question.

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