cron添加一个定时任务,每小时执行一次。
0 * * * * /root/testServer.sh >> /root/testServer.log 2>&1
检查服务器启动了,并每天检查一次证书是不是过期,提前7天发送
#!/bin/bash
# 日志函数 - 带时间戳
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
# 配置参数
TARGET_URL="https://jaxer.cc"
EMAIL_RECEIVER="jaxer@163.com" # 替换为收件人邮箱
# 锁文件目录(用于控制证书检查频率)
LOCK_DIR="/tmp/check_service"
mkdir -p "$LOCK_DIR"
CERT_CHECK_LOCK="$LOCK_DIR/cert_check_$(date +%Y%m%d).lock"
# 获取域名(去掉 https:// 前缀)
DOMAIN=$(echo "$TARGET_URL" | sed -E 's|https?://||' | sed -E 's|/.*||')
# 检查证书过期时间的函数
check_certificate_expiry() {
local domain=$1
# 获取证书过期时间(Unix 时间戳)
expiry_date=$(echo | openssl s_client -servername "$domain" -connect "$domain:443" 2>/dev/null | \
openssl x509 -noout -enddate 2>/dev/null | \
sed -n 's/notAfter=//p')
if [ -z "$expiry_date" ]; then
echo "无法获取证书信息"
return 1
fi
# 将过期时间转换为 Unix 时间戳
expiry_timestamp=$(date -d "$expiry_date" +%s 2>/dev/null || date -j -f "%b %d %H:%M:%S %Y %Z" "$expiry_date" +%s 2>/dev/null)
if [ -z "$expiry_timestamp" ]; then
echo "无法解析证书过期时间"
return 1
fi
# 当前时间戳
current_timestamp=$(date +%s)
# 计算剩余天数
days_until_expiry=$(( (expiry_timestamp - current_timestamp) / 86400 ))
echo "$days_until_expiry"
return 0
}
# 发送邮件的函数
send_email() {
local subject=$1
local body=$2
echo -e "$body" | mailx -s "$subject" "$EMAIL_RECEIVER"
if [ $? -eq 0 ]; then
log "邮件发送成功"
else
log "邮件发送失败"
fi
}
# ==================== 主程序 ====================
# 1. 检查 HTTPS 证书过期时间(仅对 HTTPS URL,每天只检查一次)
if [[ "$TARGET_URL" == https://* ]] && [[ ! -f "$CERT_CHECK_LOCK" ]]; then
# 创建今日锁文件
touch "$CERT_CHECK_LOCK"
# 清理旧的锁文件(保留最近7天)
find "$LOCK_DIR" -name "cert_check_*.lock" -mtime +7 -delete 2>/dev/null
log "检查 HTTPS 证书过期时间..."
days_left=$(check_certificate_expiry "$DOMAIN")
check_result=$?
if [ $check_result -eq 0 ]; then
log "证书将在 $days_left 天后过期"
# 如果证书将在 7 天内过期,发送提醒邮件
if [ "$days_left" -le 7 ] && [ "$days_left" -ge 0 ]; then
log "警告:证书即将过期!"
CERT_SUBJECT="SSL证书即将过期提醒 - $DOMAIN"
CERT_BODY="域名 $DOMAIN 的 SSL 证书将在 $days_left 天后过期。\n请及时更新证书以避免服务中断。\n\n过期日期: $(date -d "+$days_left days" "+%Y-%m-%d")"
send_email "$CERT_SUBJECT" "$CERT_BODY"
elif [ "$days_left" -lt 0 ]; then
log "错误:证书已过期 ${days_left#-} 天!"
CERT_SUBJECT="SSL证书已过期警告 - $DOMAIN"
CERT_BODY="域名 $DOMAIN 的 SSL 证书已过期 ${days_left#-} 天!\n请立即更新证书!"
send_email "$CERT_SUBJECT" "$CERT_BODY"
fi
else
log "证书检查失败: $days_left"
fi
else
if [[ "$TARGET_URL" == https://* ]]; then
log "证书检查今日已执行,跳过"
fi
fi
# 2. 使用 curl 获取 HTTP 状态码
echo "检查服务可用性..."
response=$(curl -o /dev/null -s -w "%{http_code}" "$TARGET_URL")
status_code=$?
# 检查curl是否成功执行
if [ $status_code -ne 0 ]; then
log "请求失败: curl 执行错误"
# 发送邮件通知服务不可用
SUBJECT="服务不可用 - $TARGET_URL"
BODY="目标网页 $TARGET_URL 无法访问。\ncurl 执行错误,请检查服务是否正常运行。"
send_email "$SUBJECT" "$BODY"
exit 1
fi
# 检查状态码是否为404
if [ "$response" -eq 404 ]; then
log "检测到 404 错误,正在发送邮件通知..."
# 邮件主题和正文
SUBJECT="网页请求失败 - $TARGET_URL"
BODY="目标网页 $TARGET_URL 返回状态码 404。\n请检查服务是否正常运行。"
send_email "$SUBJECT" "$BODY"
else
log "请求成功,状态码: $response"
fi