Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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

share|improve this question

3 Answers 3

up vote 3 down vote accepted

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

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

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).

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

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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