如何在BASH脚本中指定时间范围内的TAIL&EGREP

这个话题大都是这么说的。 我负责运行Apache2的一些运行Ubuntu 12.04的Web服务器,我想设置APC。

现在我明白,当处理有错误或怪癖的PHP代码时,APC可能会遇到分段错误问题。 因此,清理是明智的,但从人力angular度来看,并不是真正实用的。

所以我已经编写了一个脚本来监视主Apache2 error.log并计算它看到的分段错误数。 我运行它作为每2分钟运行的cron作业。 如果遇到指定数量的分段故障,应自动重启Apache2,清除APC并重新运行。 这个脚本的种子想法来自这个页面的评论,但我真的很重视这个概念,使其更多的生产准备满足我的需求和口味。

我对这个脚本通常感到满意,但是感觉一个主要的改进是这个片段的核心逻辑:

 if [[ `tail -n ${TAIL_NUMLINES} "${APACHE_ERROR_LOG}" | egrep -c "${TEXT_TO_WATCH}"` -ge ${FAIL_COUNT} ]]; then 

这基本上是核心逻辑,将日志文件拖尾到指定的行数,如果它看到指定数量的带有exit signal Segmentation fault的日志条目,则决定是时候做一些事情了。 在这种情况下,请logging事件,向某人发送有关事件的消息并重新启动Apache。

我希望这个逻辑能够及时考虑因素,因为错误可能很less。 所以有些情况下我的FAIL_COUNT简单地匹配,不pipe重新启动,因为主错误日志中没有新的条目,因为没有新的错误命中。 这将最终在服务器基本上重新启动每一个cron作业命中的情况下。 这太可怕了

因此,我现在的解决scheme是将FAIL_COUNTTAIL_NUMLINES设置为足够低的数量,以匹配Apache2重新加载时创build的条目的标准计数。 但是我还是不喜欢那个。

所以,如果有的话,可以添加一个时间框架到我的tail / egrep逻辑。 此外,我想避免创build一个时间戳或日志行的位置提示被保存到一个文件,如果可能的话。 我希望这个脚本是独立的,而不是依靠cron作业。

完整的脚本,因为我现在拥有它。

 #!/bin/bash LOCK_NAME="APACHE_LOGWATCHER" LOCK_DIR=/tmp/${LOCK_NAME}.lock PID_FILE=${LOCK_DIR}/${LOCK_NAME}.pid DATE=`date +%Y%m%d` TIME=`date +%H%M` # SUFFIX="-"${DATE}"-"${TIME}; SUFFIX="-"${DATE}; APACHE_ERROR_LOG="/var/log/apache2/error.log" APACHE_RESTART="/etc/init.d/apache2 restart" TEXT_TO_WATCH="exit signal Segmentation fault" HOSTNAME=$(hostname) MAIL_ADDRESS="[email protected]" MAIL_SUBJECT=${HOSTNAME}": Apache Segfault Notification" SCRIPT_NAME=$(basename "$0") SCRIPT_BASE_NAME=${SCRIPT_NAME%.*} LOG_DIR="/opt/segfault_logs/" LOG_FILENAME=${SCRIPT_BASE_NAME}${SUFFIX}".log" LOG_FULLPATH=${LOG_DIR}${LOG_FILENAME} TAIL_NUMLINES=5 FAIL_COUNT=4 # If the Apache log file doesn't exist, then exit. if [ ! -f ${APACHE_ERROR_LOG} ]; then exit fi # Main process. if mkdir ${LOCK_DIR} 2>/dev/null; then # If the ${LOCK_DIR} doesn't exist, then start working & store the ${PID_FILE} echo $$ > ${PID_FILE} STARTUP_MESSAGE="`date` Log watcher starting." if [ -d ${LOG_DIR} ]; then echo ${STARTUP_MESSAGE} >> ${LOG_FULLPATH} fi # Tail--but do not follow--a chunk of the LOG_FULLPATH if the number of instances is # greater than or equal to the FAIL_COUNT, act if [[ `tail -n ${TAIL_NUMLINES} "${APACHE_ERROR_LOG}" | egrep -c "${TEXT_TO_WATCH}"` -ge ${FAIL_COUNT} ]]; then # Create the log message. LOG_MESSAGE="`date` Segfault detected on "$HOSTNAME # Log the error to the file. if [ -d ${LOG_DIR} ]; then echo ${LOG_MESSAGE} >> ${LOG_FULLPATH} fi # Send e-mail notification. echo ${LOG_MESSAGE}$'\n\r'${FAIL_COUNT} | mail -s "${MAIL_SUBJECT}" ${MAIL_ADDRESS} # Restart Apache ${APACHE_RESTART} fi rm -rf ${LOCK_DIR} exit else if [ -f ${PID_FILE} ] && kill -0 $(cat ${PID_FILE}) 2>/dev/null; then # Confirm that the process file exists & a process # with that PID is truly running. # echo "Running [PID "$(cat ${PID_FILE})"]" >&2 exit else # If the process is not running, yet there is a PID file--like in the case # of a crash or sudden reboot--then get rid of the ${LOCK_DIR} rm -rf ${LOCK_DIR} exit fi fi 

编辑:这是Apache2日志文件输出上面的脚本监视的一个例子。

 [Sat Mar 02 14:32:26 2013] [notice] child pid 14696 exit signal Segmentation fault (11) [Sat Mar 02 14:32:27 2013] [notice] child pid 13914 exit signal Segmentation fault (11) [Sat Mar 02 14:32:27 2013] [notice] child pid 15735 exit signal Segmentation fault (11) [Sat Mar 02 14:32:28 2013] [notice] child pid 14865 exit signal Segmentation fault (11) [Sat Mar 02 14:32:28 2013] [notice] child pid 15545 exit signal Segmentation fault (11) [Sat Mar 02 14:32:30 2013] [notice] child pid 13821 exit signal Segmentation fault (11) [Sat Mar 02 14:32:31 2013] [notice] child pid 15683 exit signal Segmentation fault (11) [Sat Mar 02 14:32:47 2013] [notice] child pid 15684 exit signal Segmentation fault (11) [Sat Mar 02 14:33:54 2013] [notice] child pid 15482 exit signal Segmentation fault (11) [Sat Mar 02 14:34:04 2013] [notice] caught SIGTERM, shutting down [Sat Mar 02 14:34:06 2013] [notice] ModSecurity for Apache/2.6.3 (http://www.modsecurity.org/) configured. [Sat Mar 02 14:34:06 2013] [notice] ModSecurity: APR compiled version="1.4.6"; loaded version="1.4.6" [Sat Mar 02 14:34:06 2013] [notice] ModSecurity: PCRE compiled version="8.12"; loaded version="8.12 2011-01-15" [Sat Mar 02 14:34:06 2013] [notice] ModSecurity: LUA compiled version="Lua 5.1" [Sat Mar 02 14:34:06 2013] [notice] ModSecurity: LIBXML compiled version="2.7.8" [Sat Mar 02 14:34:07 2013] [notice] Apache/2.2.22 (Ubuntu) mod_ssl/2.2.22 OpenSSL/1.0.1 configured -- resuming normal operations 

这听起来像是一个工作logtaillogtail的目的是记住上次读取文件时的起始位置,以便下一次重新开始。

像这样使用它:

 logtail -o /tmp/apache.offset ${APACHE_ERROR_LOG} | egrep -c "${TEXT_TO_WATCH}" 

这certificate了我的想法

should_restart.sh

 last_restart_line_number=$( grep restart sample_log_file.txt -n | tail -1 | cut -f1 -d: ) segfaults_since_restart=$( tail -n +$last_restart_line_number sample_log_file.txt | grep segfault -c ) if [ $segfaults_since_restart -gt 5 ]; then echo "Yes, restart apache" else echo "No, don't restart apache" fi 

sample_log_file.txt

 segfault segfault segfault restart segfault segfault segfault restart segfault segfault segfault restart segfault segfault segfault segfault