Как TAIL & EGREP за указанный временной интервал в скрипте BASH
Субъект в основном говорит все это. Я отвечаю за несколько веб-серверов под управлением Ubuntu 12.04 под управлением Apache2, и я бы хотел настроить APC.
Теперь я понимаю, что APC может столкнуться с ошибками сегментации при работе с кодом PHP, в котором есть ошибки или причуды. Поэтому очистка рекомендуется, но не очень практична с точки зрения рабочей силы.
Итак, я подготовил скрипт для мониторинга основного Apache2 error.log
и посчитайте, сколько ошибок сегментации он видит. Я запускаю его как работу cron, которая выполняется каждые 2 минуты. Если он сталкивается с указанным количеством ошибок сегментации, он должен автоматически перезапустить Apache2, чтобы очистить APC и снова запустить службы. Идея этого сценария основывается на комментариях на этой странице, но я действительно в значительной степени опирался на эту концепцию, чтобы сделать ее более готовой для удовлетворения моих потребностей и вкусов.
Я в целом доволен этим сценарием, но чувствую, что одним из основных улучшений является основная логика в этом фрагменте:
if [[ `tail -n ${TAIL_NUMLINES} "${APACHE_ERROR_LOG}" | egrep -c "${TEXT_TO_WATCH}"` -ge ${FAIL_COUNT} ]]; then
Это в основном основная логика, которая привязывает файл журнала к указанному количеству строк, и если он видит указанное количество записей журнала с exit signal Segmentation fault
в них то решает, что пора что-то делать. В этом случае зарегистрируйте инцидент, напишите кому-нибудь об инциденте и перезапустите Apache.
Я хотел бы, чтобы эта логика учитывала время, потому что ошибок может быть немного и далеко. Так что есть случаи, когда мой FAIL_COUNT
просто соответствует TAIL_NUMLINES
несмотря на перезапуск, потому что в основном журнале ошибок нет новых записей, потому что новых ошибок не было. Это может привести к ситуации, когда сервер в основном перезапускается каждый раз, когда запускается задание cron. Что ужасно
Таким образом, мое временное решение на данный момент состоит в том, чтобы установить FAIL_COUNT
& TAIL_NUMLINES
до достаточно низкого числа, чтобы соответствовать стандартному количеству записей, которые создаются при перезагрузке Apache2. Но мне все еще не нравится это.
Так что - если что-нибудь - можно сделать, чтобы добавить временные рамки к моему tail
/egrep
логика. Кроме того, я хотел бы избежать создания временной метки или подсказки положения строки журнала, сохраняемой в файл, если это возможно. Я хочу, чтобы этот скрипт был автономным, кроме как в зависимости от задания 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="myname@domain.name.here.com"
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
2 ответа
Это звучит как работа для logtail
, Цель logtail
это помнить, куда вы попали при чтении файла в прошлый раз, чтобы вы могли начать снова с этого момента в следующий раз.
Используйте это так:
logtail -o /tmp/apache.offset ${APACHE_ERROR_LOG} | egrep -c "${TEXT_TO_WATCH}"
Это демонстрирует мою идею
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