When watching a growing log file with e.g. "less -iS +F service.log" I want to limit the display to lines matching a certain pattern.
I tried something like
less +F service.log | grep <pattern> | less +F which doesn't work. Also
cat < service.log | grep <pattern> | less +F doesn't do what I want. It looks like the input is already closed and less doesn't show changes.
How can I limit the display to lines matching a certain pattern?
5 Answers
This question is ages old, but I still think it's worth adding a solution. Instead of trying to grep first and then use less, what about using filtering inside less?
In brief:
use less +Fon your fileCTRL-Cto temporarily break the "following" action- Type
&and your pattern to enable filtering - Issue
+Fto re-enable the "following" action
More details on this answer on the Unix&Linux StackExchange
3I haven't yet worked out how to do this without a temp file, but here is a script that demonstrates a functional grep-filtered less +F (which cleans up its temp file). I call it lessf.
One of the key elements is the --line-buffered argument to grep that permits tail output to continue to flow through the pipeline (the unbuffer command provided by expect provides similar functionality for any program).
#!/bin/sh LOGFILE=$1 shift PATTERN=$@ TEMP_DIR=/tmp/lesstmp TEMP_FILE="$TEMP_DIR/$(basename $LOGFILE)" [ ! -d $TEMP_DIR ] && mkdir $TEMP_DIR trap 'rm -rf "$TEMP_DIR"; exit' INT TERM EXIT ( tail -f "$LOGFILE" | grep --line-buffered $PATTERN ) > "$TEMP_FILE" | less +F "$TEMP_FILE" trap - INT TERM EXIT Example usage:
lessf /var/log/system.log foobar
lessf /var/log/system.log -v nobar
If you don't mind spawning and tearing down a couple of processes each line, use a read while loop
tail -f filename.log|while read line; do echo $line | grep pattern; done tail -f service.log | grep <pattern> 1The solution seemed simply
LESSOPEN='|grep <pattern> %s' less +F service.log but less doesn't continue to read new lines from the growing log file.
1