我有一个 Java 程序在 Ubuntu 16.04 上作为服务运行。可能我从中获得的唯一输出是日志(错误、常规打印等)。因此,我想要做的是,每当我的程序中抛出异常时,我都想重新启动它(执行 systemctl restart myjavaservice)。
我已经尝试过的是使用tea -a
(-a 因为我想保留非常旧的日志)将日志写入文件并使用 tail 和 awk 像这样:
tail -F /home/myuser/myservice/output.log | awk '/Exception/ {system("systemctl restart myjavaservice")}'
但这会使服务重新启动多次并且基本上服务无法正确重新启动。
我假设我可以将一个脚本放入 cron 作业中(大约每 5 分钟运行一次),该脚本将检查我的服务日志,如果遇到单词“Exception”(或任何其他单词),我想重新启动服务(但也不会清除日志文件)。有没有合适的方法可以做到这一点?我应该使用什么工具?
PS:目前我正在考虑tail -n 200 /home/myuser/myservice/output.log | awk '{if (/Exception/) {system("systemctl restart myjavaservice"); exit;}}'
我是否正确,这会将最后 200 行日志传送到 awk,然后 awk 将检查传递的文本中是否出现单词 Exception,如果出现,它将运行 systemctl restart myjavaservice 并在找到第一个出现后立即退出?提前感谢您的建议!
答案1
您需要一种机制来确保您不会重复阅读相同的行。以下是您可以实现所需目的的一种方法。
1 #!/bin/sh 2 3 export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin 4 5 PATTERN="Exception string" 6 LOGFILE=/home/myuser/myservice/output.log 7 8 #-- 在与日志文件相同的位置创建标志文件 9 FLAG= dirname "$LOGFILE"
/ basename "$LOGFILE"
.flag 10 11 if [ ! -s "$FLAG" ] ; then 12 LAST_LINE_NBR=0 13 LAST_LINE="" 14 else 15 LAST_LINE_NBR= sed 's/:.*$//' "$FLAG"
16 LAST_LINE= sed 's/^[0-9]*: //' "$FLAG"
17 18 #-- 验证文件是否相同 19 CURR_LINE= sed -n $LAST_LINE_NBR,${LAST_LINE_NBR}p "$LOGFILE"
20 21 if [ "$LAST_LINE" != "$CURR_LINE" ] ;然后 22 #-- 日志文件不再与之前检查过的相同,重新开始 23 LAST_LINE_NBR=0 24 LAST_LINE="" 25 fi 26 fi 27 28 #-- 在之前检查过的行后选择一行 29 LAST_LINE_NBR= expr $LAST_LINE_NBR+1
30 31 #-- 更新标志 32 NEW_LAST_LINE_NBR= sed -n '$=' "$LOGFILE"
33 NEW_LAST_LINE= sed -n $NEW_LAST_LINE_NBR,${NEW_LAST_LINE_NBR}p "$LOGFILE"
34 echo "$NEW_LAST_LINE_NBR: $NEW_LAST_LINE" > "$FLAG" 35 36 sed -n $LAST_LINE_NBR,\$p "$LOGFILE" \ 37 | egrep "$PATTERN" > /dev/null 38 39 if [ $? -eq 0 ] ; then 40 #-- 发现异常,执行操作 41 systemctl restart myjavaservice 42 fi 43 44 # 文件结束 #