grep -q' not exiting with 'tail -f'
tail -f
will read a file and display lines later added, it will not terminate (unless a signal like SIGTERM
is sent). grep
is not the blocking part here, tail -f
is. grep
will read from the pipe until it is closed, but it never is because tail -f
does not quit and keep the pipe open.
A solution to your problem would probably be (not tested and very likely to perform badly):
tail -f logfile | while read line; do
echo $line | grep -q 'find me to quit' && break;
done
Ending tail -f started in a shell script
The best answer I can come up with is this
- Put a timeout on the read,
tail -f logfile | read -t 30 line
- Start tail with
--pid=$$
, that way it'll exit when the bash-process has finished.
It'll cover all cases I can think of (server hangs with no output, server exits, server starts correctly).
Dont forget to start your tail before the server.
tail -n0 -F logfile 2>/dev/null | while read -t 30 line
the -F
will 'read' the file even if it doesn't exist (start reading it when it appears). The -n0
won't read anything already in the file, so you can keep appending to the logfile instead of overwriting it each time, and to standard log rotation on it.
EDIT:
Ok, so a rather crude 'solution', if you're using tail. There are probably better solutions using something else but tail, but I got to give it to you, tail gets you out of the broken-pipe quite nicely. A 'tee' which is able to handle SIGPIPE would probably work better. The java process actively doing a file system drop with an 'im alive' message of some sort is probably even easier to wait for.
function startServer() {
touch logfile
# 30 second timeout.
sleep 30 &
timerPid=$!
tail -n0 -F --pid=$timerPid logfile | while read line
do
if echo $line | grep -q 'Started'; then
echo 'Server Started'
# stop the timer..
kill $timerPid
fi
done &
startJavaprocess > logfile &
# wait for the timer to expire (or be killed)
wait %sleep
}
tail -f | grep in if statement
Your pipe (tail -f ... | grep ...
) will never end.
Add -m 1
to your GNU grep
to exit after first match.
How to 'grep' a continuous stream?
Turn on grep
's line buffering mode when using BSD grep (FreeBSD, Mac OS X etc.)
tail -f file | grep --line-buffered my_pattern
It looks like a while ago --line-buffered
didn't matter for GNU grep (used on pretty much any Linux) as it flushed by default (YMMV for other Unix-likes such as SmartOS, AIX or QNX). However, as of November 2020, --line-buffered
is needed (at least with GNU grep 3.5 in openSUSE, but it seems generally needed based on comments below).
Do a tail -F until matching a pattern
Try this:
sh -c 'tail -n +0 -f /tmp/foo | { sed "/EOF/ q" && kill $$ ;}'
The whole command-line will exit as soon as the "EOF" string is seen in /tmp/foo
.
There is one side-effect: the tail
process will be left running (in the background) until anything is written to /tmp/foo
.
Using tail in a subshell in conjunction with while/break does not exit the loop
Try this, although it's not quite the same (it doesn't skip the beginning of the log file at startup):
triggerwordfound=
while [ -z "$triggerwordfound" ]; do
while read line; do
echo $line
if echo $line|grep "${triggerword}";then
echo "Logout completion detected"
start_leaks_detection
triggerwordfound=true
echo "Leaks detection complete"
fi
done
done < "$logfile"
echo "Outside loop"
The double loop effectively does the same thing as tail -f
.
Linux: Block until a string is matched in a file (tail + grep with blocking)
Thanks both for answers, but the important part was that the process blocks until found, then ends. I found this:
grep -q 'PATTERN' <(tail -f file.log)
-q
is not much portable, but I will only use Red Hat Enterprise Linux so it's ok.
And with timeout:
timeout 180 grep -q 'PATTERN' <(tail -f file.log)
Related Topics
What Is the Status of Posix Asynchronous I/O (Aio)
A Way to Determine a Process'S "Real" Memory Usage, I.E. Private Dirty Rss
Automatically Kill Process That Consume Too Much Memory or Stall on Linux
Accessing Data Appended to an Elf Binary
Linux Join Utility Complains About Input File Not Being Sorted
How to Diff Top Lines of Two Files Without Intermediate File
Pass Private Key Password to Openvpn Command Directly in Ubuntu 10.10
Redirect Qemu Window Output to Terminal Running Qemu
Calculate Total Used Disk Space by Files Older Than 180 Days Using Find
How to Compile Linux Kernel with Something Other Than Gcc
Kdevtmpfsi - How to Find and Delete That Miner
Change Filenames to Lowercase in Ubuntu in All Subdirectories
Sed: How to Delete Lines Matching a Pattern That Contains Forward Slashes
Setting Up a Subdomain with Apache on Linux