我正在使用以下脚本,该脚本是根据我在网络上发现的其他想法拼凑而成的,以满足我监控日志文件和捕获错误的目的。
tail -f log_file | while read LOGLINE
do
echo -e "${LOGLINE}"
if [[ "${LOGLINE}" == *ERROR* ]] ; then
echo -e "ERROR FOUND : ${LOGLINE}\n"
# handle the error here
fi
done
如果生成日志文件的程序崩溃或被终止且不再写入
日志,我怎么检测到它?事实上,tail
只会等待并等到另一条线。
答案 0 :(得分:2)
通常,如果您不一定知道进程名称,或者只是想知道任何进程是否正在访问文件,您可以尝试fuser
。例如,在Linux上如果我有一个服务器进程写入server.log,那么fuser server.log
给出类似的东西:
/var/log/server.log: 28977
其中28977是服务器进程的进程ID。当服务器进程退出时,fuser
不返回任何内容。显然在你的情况下你也有尾部进程读取文件,所以你期望有多个PID,例如:
/var/log/server.log: 28977 28990
从手册页注意:“fuser仅将PID输出到stdout,其他所有内容都发送到stderr。”。因此,举例来说,您可以管道wc -w
并检查您至少获得2
。获取1
只表示您的tail -f
正在访问该文件。
在循环中集成它的障碍是read
将阻塞,直到它可以读取一行,因此在文件未被写入任何更长时间后,在循环内执行的任何检查都将永远不会运行。您需要使用read -t
并指定超时。像这样:
tail -f log_file | while [ 1 ]
do
read -t 10 LOGLINE
if [[ -z "${LOGLINE}" && $? -ne 0 ]] ; then
# Variable is empty and read timed out
if [[ `fuser log_file 2> /dev/null | wc -w` < 2 ]] ; then
# Nothing else is using the log file
pkill -f "tail -f log_file" # Specific, so we don't kill tails of other files
break
fi
else
echo -e "${LOGLINE}"
# Do your stuff...
fi
done
(感谢anubhava提醒我pkill!另外,请注意,如果你知道写入日志的过程有足够的识别信息,你可以做一个pgrep而不是热熔器检查。)
如果您正在使用Linux,那么更简单的另一件事就是使用尾部的--pid
选项,如果具有该PID的进程已停止,它将停止它。然后你可以这样做:
LOG_WRITER=`pgrep something-identifying-the-process-writing-the-log`
tail -f log_file --pid=$LOG_WRITER | while read LOGLINE
…the rest of your script
然而,似乎可能存在这种情况,即没有注意到该过程已经停止。这对你来说可能已经足够了。
答案 1 :(得分:1)
您可以致电pgrep
检查原始流程是否正在运行&gt;
while read -r LOGLINE
do
echo -e "${LOGLINE}"
if [[ "${LOGLINE}" == *ERROR* ]] ; then
echo -e "ERROR FOUND : ${LOGLINE}\n"
# handle the error here
if pgrep -q process; then
echo "process has exited/crashed"
# kill tail process and break out of loop
pkill -f tail
break
fi
fi
done < <(tail -f log_file)
答案 2 :(得分:1)
要获取打开日志文件的所有进程的进程ID,请使用lsof
:
lsof -Fp /path/to/your/logfle
请注意,这只会显示实际打开文件的进程。您可能会错过使文件保持关闭的程序,除非它们实际需要写入时的短暂时刻。
lsof
对脚本友好,有很多选项。请参阅man lsof
。
这是一个脚本,一旦没有打开日志文件的进程,它就会将消息写入屏幕:
while lsof -Fp /tmp/mylogfile >/dev/null
do
sleep 1
done
echo "No processes have the log file open"
上面有一个问题:您的tail -f
进程将打开文件。当打开该文件的进程数低于2时,您可能希望显示该消息:
while [ "$(lsof -Fp /tmp/mylogfile | wc -l)" -ge 2 ]
do
sleep 1
done
echo "There are less than two processes with the log file open"
[我最初在Unix site上回答了这个问题。由于这个问题正在被关闭,我在这里保留答案。]
答案 3 :(得分:0)
您的方法存在一般问题:
while ... 构造中的代码仅在日志文件更改时运行,即当有问题的进程将某些内容写入日志文件时。
现在,如果该进程在没有写入日志文件的情况下崩溃(您要检测的事件),那么您将永远不会再次进入while循环体。
因此,在while循环中检查进程是否有效是没有用的 - 除非进程在崩溃时在日志中留下有用的消息,那么你当然可以检查这样的消息。
您必须运行第二个监控流程,以检测流程何时终止。该问题的一个简单解决方案是mon
,您可以在此处找到:https://github.com/visionmedia/mon
我建议不要进行间接检查(“是否仍然可以写入日志文件?”);只是直接检查过程,并使用专门的工具来做到这一点。