ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Which is supposed to work as follows: tail fetches the last 50 files from a log file and continues fetching newly written data until a match is found by grep and it silently exits with success (as instructed by the -q flag). This works if tail writes following lines after grep exits, receives SIGPIPE or similar, and the whole pipeline exits with grep's exit status, which is 0. Nice and candy. The problem is that when both of the following are true: a match is found resulting in grep's successful completion AND no more data is written to the log file, tail doesn't know that the reader of the pipeline has exited and continues "watching" the file for new data (as commanded by -F flag) until the timeout of 10 seconds passes and timeout exits with 143 (128+SIGTERM, which is 15).
Is there any way to make the whole pipeline exit immediately with grep's exit code no matter what?
mkfifo /tmp/fifo2
tail -q -n50 -F /tmp/fifo2 | grep -qE aaa
# will stop immediately when I do:
echo adsfasdf aaa sdgfaa > /tmp/fifo2
What do you mean by exit immediately? tail -F reads continuously and grep will [wait for and] stop if match found.
Thanks for replying, pan64.
Although I'm facing the problem in FreeBSD, it can easily be repeated in Ubuntu using this script:
Code:
#!/bin/sh
trap 'rm -f "$tmp"' EXIT
tmp="$(mktemp)"
[ "$tmp" ] || exit
strings /vmlinuz > "$tmp"
wc -l "$tmp"
for i in `seq 100`; do
timeout 1 sh -c "tail -q -n$((100*$i)) -F '$tmp' | grep -qE ."
echo "Exit $? for $((100*$i))"
done
Code:
rihad@rihad:~$ ./sh
50775 /tmp/tmp.Lf3mMRWjwR
Exit 124 for 100
Exit 124 for 200
Exit 124 for 300
Exit 124 for 400
Exit 124 for 500
Exit 124 for 600
Exit 124 for 700
Exit 124 for 800
Exit 124 for 900
Exit 124 for 1000
Exit 124 for 1100
Exit 124 for 1200
Exit 0 for 1300
Exit 0 for 1400
Exit 0 for 1500
Exit 0 for 1600
Exit 0 for 1700
Exit 0 for 1800
Exit 0 for 1900
Exit 0 for 2000
Exit 124 for 2100
Exit 0 for 2200
Exit 0 for 2300
Exit 0 for 2400
Exit 0 for 2500
Exit 0 for 2600
Exit 0 for 2700
Exit 0 for 2800
Exit 0 for 2900
Exit 0 for 3000
Exit 0 for 3100
Exit 0 for 3200
Exit 0 for 3300
Exit 0 for 3400
Exit 0 for 3500
Exit 0 for 3600
Exit 124 for 3700
Exit 0 for 3800
Exit 0 for 3900
Exit 0 for 4000
Exit 0 for 4100
Exit 0 for 4200
Exit 0 for 4300
Exit 0 for 4400
Exit 0 for 4500
Exit 124 for 4600
Exit 124 for 4700
Exit 124 for 4800
Exit 124 for 4900
Exit 124 for 5000
Exit 124 for 5100
Exit 124 for 5200
Exit 124 for 5300
Exit 124 for 5400
Exit 124 for 5500
Exit 124 for 5600
^C
rihad@rihad:~$
In theory the pipeline should always exit 0 if there's at least one nonempty line for grep to match.
In practice the correctness of the exit status depends on whether tail writes anything to its output after grep exits or not.
When it does, we see "Exit 0" above. When it doesn't, we see Exit 124 (which means timeout had to kill the pipeline after 1 second).
In theory the pipeline should always exit 0 if there's at least one nonempty line for grep to match..
So that may mean there was no nonempty line sent within that second.
Adding to post #4, it is not that simple, because SIGPIPE will be generated later, when grep already exited (and tail still wanted to write into it and its buffer is full). (there was a long thread about it on LQ, but I can't find it).
So you may need to implement it differently, probably using pipe:
Code:
mkfifo /tmp/fifo
timeout 10 grep pattern /tmp/fifo &
save timeout_pid
tail -f logfile > /tmp/fifo &
save tail_pid
wait timeout_pid
you get the exit code of grep/timeout here
kill tail_pid
or you can fully reimplement it in python/perl/whatever
That's an excellent idea. I've run a few tests and it seems to be doing the right thing. As a plus it doesn't require bash for its "process substitution" feature, which sometimes leaves fifos lying around (/tmp/sh-np*).
That's an excellent idea. I've run a few tests and it seems to be doing the right thing. As a plus it doesn't require bash for its "process substitution" feature, which sometimes leaves fifos lying around (/tmp/sh-np*).
You left out -q for grep. Without it grep simply keeps reading its input and printing matching lines until it reaches eof. With -q grep doesn't print anything, but exits successfully on the very first match.
You left out -q for grep. Without it grep simply keeps reading its input and printing matching lines until it reaches eof. With -q grep doesn't print anything, but exits successfully on the very first match.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.