BASH: Tail follows a file until string isn’t matched

The problem seems pretty easy… for the first look.

# Prepare :>/tmp/output.log (sleep 1s; echo "exit on match" >> /tmp/output.log) & tail -n +0 -f /tmp/output.log | sed '/exit on match/{p;q}'

My first reaction was “Wuuuut?”, because tail isn’t react on SIGPIPE.

It is happens because tail stop to react on SIGPIPE and start watch for a file, I suppose, with inotify mechanism.

There is different ways how to do that, I’ll show you a couple of them.

Using named pipes:

:>/tmp/output.log (sleep 1s; echo "exit on match" >> /tmp/output.log) & mkfifo /tmp/fifo.$$ sed '/exit on match/{p;q}' "/tmp/fifo.$$" & tail --pid=$! -n +0 -f /tmp/output.log >> /tmp/fifo.$$ rm -f /tmp/fifo.$$

And without it:

:>/tmp/output.log (sleep 1s; echo "exit on match" >> /tmp/output.log) & tail -n +0 -f /tmp/output.log | (sed '/exit on match/q'; awk '{gsub(/\([^)]\+\)/,"_"); print $5}' /proc/self/stat | xargs pkill -g)

In the second case will be printed string “Terminated” into stderr and, I suppose, this one-liner should be a bit commented:

program1 | program2 will be executed as the group of processes, where each of sequence (sed …; awk) will executed as program2, so, of course it’ll be in the same group as program1. That’s what wee need!
Forgive me linux gurus for so abstracted explanation (:

Now, there start to working the magic path /proc/self, what gives us access to the current process environment, and as expected – processes group ID.

Nothing left, except getting GID and kill it.


Leave a Reply

Your email address will not be published. Required fields are marked *