【发布时间】:2019-07-26 10:54:04
【问题描述】:
我的要求是使用 cron 作业中的 shell 脚本读取正在不断更新的服务器日志(相对较大)文件。如果找到字符串,我将阅读直到最后一个可用行以查找字符串和电子邮件。下次 cron 作业开始时,作业应从上次完成的行或位置读取。任何建议我如何在 shell 脚本中执行此操作。
【问题讨论】:
-
您必须将文件位置保存到临时文件,然后从该文件位置开始读取。
我的要求是使用 cron 作业中的 shell 脚本读取正在不断更新的服务器日志(相对较大)文件。如果找到字符串,我将阅读直到最后一个可用行以查找字符串和电子邮件。下次 cron 作业开始时,作业应从上次完成的行或位置读取。任何建议我如何在 shell 脚本中执行此操作。
【问题讨论】:
以下内容可以帮助您入门:
tail -f your_file | while read line
do case "$line" in
*"string_to_search"*) echo "" | mutt -s "Guilty string found" a_mail@mail.com
;;
esac
done
【讨论】:
tail -f your_file | grep --line-buffered "string_to_search" | ... rest of the script。但是,操作请求Next time when the cron job starts the job should read from the line or position where it was last finished. 存在问题
我使用timeout 超时tail 并使用一些保存文件来保存我们解析的行位置:
# statefile where we save the number of parsed already lines
statefile=/tmp/statefile.txt
# initialize count variable - to zero, or from statefile
if [ -e "$statefile" ]; then
count=$(<"$statefile")
else
count=0
fi
# we timeout for 1 seconds outputting the lines
# the better timeout would be like 10 seconds for big file
# the `tail` command needs to jump `$count` lines inside the input file
timeout 1 tail -n +$count input_log_file |
# tee is used to pass the input to the updating part
tee >(
# read number of parsed lines with `wc -l`
# increment the count of parsed lines and save to statefile
echo $(( count + $(wc -l) )) >"$statefile"
) |
# grep for the searched string
grep --line-buffered string_to_search |
# do the action if string_to_search is found
do_some_action_example_send_mail
【讨论】:
tail -n +10 在有 10 行的文件上(第一次已经 10 行)将显示已经处理的第 10 行。
tail 将扫描稀薄的空气。