using awk rather than grep:
awk '/string1/ { print >> "output1.log" ; fflush() }
/string2/ { print >> "output2.log" ; fflush() }
/string3/ { print >> "output3.log" ; fflush() }' input.log
This outputs all matching lines to their respective output.log files. That's because I can't make sense of your conflicting tail -f
and tail -n 1
requirements. If you really do want it to start following input.log
from the current last line, then pipe tail -f -n 1
into the awk
script and get rid of the input.log
at the end of the line. e.g.
tail -f -n 1 input.log | awk '...same awk script as above...'
You could also do it with tee
and grep
and process substitution
(but it will be noticeably slower):
tee >(grep --line-buffered string1 >> output1.log) \
>(grep --line-buffered string2 >> output2.log) \
>(grep --line-buffered string3 >> output3.log) < input.log
or
tail -f -n 1 input.log | tee .....
NOTE: The fflush()
in the awk
solution, and the --line-buffered
option in the tee
solution are only needed if you're piping the output of tail -f
(or some other never-ending process) into awk
or tee
.
Without them, the output files will only be written when the output buffers (of awk or grep) are full - and if the job is aborted while there is unwritten output in the buffers (e.g. by pressing Ctrl-C) then any output still in the buffers will be lost.
With them, both solutions run much slower (because they flush output on every write) - but that's unlikely to be significant except with very large input files.
BTW, this isn't an issue when the input ends - in that case, both awk and grep flush their output buffers automatically before exiting.
Another alternative would be to run the pipe to awk
(or tee
) in a sub-shell that trapped and ignored the Interrupt signal from Ctrl-C. e.g.
tail -f input.log | (
trap '' INT
awk '/string1/ { print >> "output1.log" }
/string2/ { print >> "output2.log" }
/string3/ { print >> "output3.log" }'
)
The tail -f
is affected (killed) by pressing Ctrl-C, but the sub-shell running awk
ignores it. awk
flushes its output buffers and exits when the tail
is killed because its input has finished.
See Trap Ctrl-C in awk script for an another example/explanation.
If you don't want it to follow the log file, then don't use tail
's -f
option.
Just use tail -n 1 | .....
or see Guy's answer which prints the last match for all three strings into their respective output files.
tail -f -n 1
starts following the log file from the (current) last line. also,awk
would be better suited to this thangrep
.