使用 cron、bash 和 wget 监控 Web 服务器的状态

红薯 发布于 2012/03/26 13:26
阅读 3K+
收藏 28

我最近需要一个真正真正简单的远程监控工具,用来跟踪服务器的可用性,我不需要记录运行时间以及其他别的信息,只是想知道服务器有没有异常挂机之类的。没找到这样的工具,我只好自己写一个。

尽管有很多这样的工具,而且都是开源免费的,例如 NagiosCacti 等等,但这些都太重了。我不需要那么复杂的,下面是我的基本需求列表:

  • 要求是 bash, wget, 以及 “mail” 命令 (sendmail, exim, postfix, 之类)
  • 可监控任何 HTTP/HTTPS URL, 检查 “200″ 状态返回
  • 检查请求返回时间,用于监控一些慢响应
  • 通过 Email 发送异常状态提醒
  • 可定制的接收异常信息的邮箱
  • 可定制慢响应的时间
  • 避免重复发送相同的异常提醒
  • 使用简单文本文件作为数据存储,不需要数据库

这些都非常的基本,但很有效。

简单的 crontab 作业定义

*/5 * * * * root /home/username/sitemonitor.sh

sitemonitor.sh 脚本源码

#!/bin/bash

# Simple HTTP/S availability notifications script v0.1
# March 20, 2012 by Jeff Rowberg - http://www.sectorfej.net

HOSTS=( \
    "http://www.yahoo.com" \
    "https://www.google.com" \
    "http://www.amazon.com" \
    )

NOTIFY_FROM_EMAIL="Site Monitoring <monitoring@example.com>"
NOTIFY_TO_EMAIL="Server Admin <admin@example.com>"

STATUS_FILE="/home/username/sitemonitor.status"

SLOW_THRESHOLD=10
OK_STATUSES=( "200" )

################################################################
#        NO MORE USERMOD STUFF BELOW THIS, MOST LIKELY         #
################################################################

# thanks to stackoverflow!
# stackoverflow.com/questions/3685970/bash-check-if-an-array-contains-a-value
function contains() {
    local n=$#
    local value=${!n}
    for ((i=1; i < $#; i++)) {
        if [ "${!i}" == "${value}" ]; then
            echo "y"
            return 0
        fi
    }
    echo "n"
    return 1
}

rm -f /tmp/sitemonitor.status.tmp
for HOST in "${HOSTS[@]}"
do
    START=$(date +%s)
    RESPONSE=`wget $HOST --no-check-certificate -S -q -O - 2>&1 | \
                  awk '/^  HTTP/{print \$2}'`
    END=$(date +%s)
    DIFF=$(( $END - $START ))
    if [ -z "$RESPONSE" ]; then
        RESPONSE="0"
    fi
    if [ $(contains "${OK_STATUSES[@]}" "$RESPONSE") == "y" ]; then
        if [ "$DIFF" -lt "$SLOW_THRESHOLD" ]; then
            STATUS="UP"
        else
            STATUS="SLOW"
        fi
    else
        STATUS="DOWN"
    fi
    touch $STATUS_FILE
    STATUS_LINE=`grep $HOST $STATUS_FILE`
    STATUS_PARTS=($(echo $STATUS_LINE | tr " " "\n"))
    CHANGED=${STATUS_PARTS[2]}
    if [ "$STATUS" != "${STATUS_PARTS[5]}" ]; then
        #if [ -e "${STATUS_PARTS[5]}" ] || [ "$STATUS" != "UP" ]; then
            if [ -z "${STATUS_PARTS[5]}" ]; then
                STATUS_PARTS[5]="No record"
            fi
            TIME=`date -d @$END`
            echo "Time: $TIME" > /tmp/sitemonitor.email.tmp
            echo "Host: $HOST" >> /tmp/sitemonitor.email.tmp
            echo "Status: $STATUS" >> /tmp/sitemonitor.email.tmp
            echo "Latency: $DIFF sec" >> /tmp/sitemonitor.email.tmp
            echo "Previous status: ${STATUS_PARTS[5]}" >> /tmp/sitemonitor.email.tmp
            if [ -z "${STATUS_PARTS[2]}" ]; then
                TIME="No record"
            else
                TIME=`date -d @${STATUS_PARTS[2]}`
            fi
            echo "Previous change: $TIME" >> /tmp/sitemonitor.email.tmp
            `mail -a "From: $NOTIFY_FROM_EMAIL" \
                  -s "SiteMonitor Notification: $HOST is $STATUS" \
                  "$NOTIFY_TO_EMAIL" < /tmp/sitemonitor.email.tmp`
            rm -f /tmp/sitemonitor.email.tmp
        #else
             # first report, but host is up, so no need to notify
        #fi
        CHANGED="$END"
    fi
    echo $HOST $RESPONSE $CHANGED $END $DIFF $STATUS >> /tmp/sitemonitor.status.tmp
done

mv /tmp/sitemonitor.status.tmp $STATUS_FILE

异常提醒邮件的示例

Time: Fri Mar 23 17:20:02 UTC 2012
Host: http://www.example.com
Status: UP
Latency: 0 sec
Previous status: DOWN
Previous change: Fri Mar 23 15:05:20 UTC 2012

相当的简单,但工作的很好,你可以试试。

英文原文,OSCHINA原创翻译

加载中
0
暴君祥子
暴君祥子

盛赞。

非常喜欢这种手动打造给自己的小工具

0
LongRaindy
LongRaindy
呵呵,做运维这么多年我的感受是,这种自己写的小工具通常最顶用,也最容易控制和改动。
返回顶部
顶部