Тема в основном говорит сама за себя. Я отвечаю за несколько веб-серверов под управлением 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
Это похоже на работу для logtail
. Цель logtail
- помнить, где вы пришли при чтении файла в последний раз, чтобы в следующий раз начать заново с этого места.
Используйте это так:
logtail -o /tmp/apache.offset ${APACHE_ERROR_LOG} | egrep -c "${TEXT_TO_WATCH}"
Это демонстрирует мою идею
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
segfault
segfault
segfault
restart
segfault
segfault
segfault
restart
segfault
segfault
segfault
restart
segfault
segfault
segfault
segfault