TL;DR
The following alternative should do the trick:
#!/bin/bash
MS01_LOG_FILE=/var/log/dmesg
MS02_LOG_FILE=/var/log/syslog
TIMEOUT=10 # modify to your liking
tail -n 0 -f "$MS01_LOG_FILE" "$MS02_LOG_FILE" | while :
do
IFS= read -t $TIMEOUT -r line
# do your funny things here
done
Details
First quoting from help read
(see bash reference manual for the builtin command "read")
-t timeout
Cause read to time out and return failure if a complete line of input (or a specified number of characters) is not read within
timeout seconds. timeout may be a decimal number with a fractional
portion following the decimal point. This option is only effective if
read is reading input from a terminal, pipe, or other special file; it
has no effect when reading from regular files. If read times out, read
saves any partial input read into the specified variable name. If
timeout is 0, read returns immediately, without trying to read and
data. The exit status is 0 if input is available on the specified file
descriptor, non-zero otherwise. The exit status is greater than 128 if
the timeout is exceeded.
Note that the exit status being greater than 128 for detecting a read timeout is not guaranteed between implementations (e.g. on my OS X's bash it is 1).
Now simply adding -t $TIMEOUT
to your initial script provides only one part of the solution since the broken pipe won't be detected until anything gets emitted from the tail pipe.
Moving the read
into a endless while loop solves that issue.
Depending on what you want to do instead of # do your funny things here
you might now be confronted with the issue of escaping from that child process jail.
In that case check https://stackoverflow.com/questions/20558295/quit-from-pipe-in-bash
... | while true; do IFS= read -r -t 42 line; ... done