用脚本高效检测网站是否在线(附代码实战)
目录导读
- 为什么要用脚本检测网站在线状态?
- 核心检测逻辑:HTTP请求与响应码解析
- 主流脚本语言实现对比(Python、Bash、Shell)
- Python脚本实战:从单站点检测到多站点并发
- Bash脚本实战:轻量级Cron定时检测方案
- 进阶功能:异常告警(邮件/钉钉/微信)
- 常见问题解答(FAQ)
- 总结与最佳实践建议
为什么要用脚本检测网站在线状态?
对于运维工程师、站长或开发者而言,网站宕机可能直接导致业务损失,手动刷新页面检查效率极低,且无法实现24小时监控,通过脚本自动化检测,可以:

- 实时发现宕机或响应超时
- 支持多站点批量监控
- 集成告警机制,第一时间通知负责人
- 生成历史数据,追踪网站稳定性趋势
核心检测逻辑:HTTP请求与响应码解析
脚本检测的核心是向目标URL发送HTTP请求,根据返回状态码判断:
| 状态码 | 含义 | 判断结果 |
|---|---|---|
| 200-299 | 请求成功 | 在线正常 |
| 301/302 | 重定向 | 需根据场景决定(可视为在线) |
| 401/403 | 访问受限 | 在线但需要权限 |
| 404 | 页面不存在 | 在线但资源缺失 |
| 500-599 | 服务器错误 | 在线但异常 |
| 超时/拒绝连接 | 网络不通 | 离线 |
关键参数:超时时间(通常设为10秒)、请求方法(HEAD比GET更轻量)、SSL验证(需考虑证书问题)。
主流脚本语言实现对比
| 语言 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| Bash | 系统自带,轻量无依赖 | 错误处理较弱 | Linux服务器基础监控 |
| Python | 强大的requests/urllib库 | 需安装环境 | 复杂逻辑、数据存储 |
| Node.js | 异步并发性能高 | 依赖npm | 高并发检测系统 |
| PowerShell | Windows原生支持 | 语法特性特定 | Windows运维环境 |
本文重点讲解Python和Bash两种最通用、易部署的实现方式。
Python脚本实战:从单站点检测到多站点并发
基础版本:单站点检测
import requests
from datetime import datetime
def check_url(url):
try:
response = requests.get(url, timeout=10, verify=False)
if response.status_code == 200:
return f"[{datetime.now()}] {url} 在线 (状态码: 200)"
else:
return f"[{datetime.now()}] {url} 异常 (状态码: {response.status_code})"
except requests.ConnectionError:
return f"[{datetime.now()}] {url} 离线 (连接失败)"
except requests.Timeout:
return f"[{datetime.now()}] {url} 超时 (10秒无响应)"
print(check_url("https://www.example.com"))
注意:替换example.com为实际域名;verify=False用于跳过SSL证书验证(生产环境建议配置证书)。
进阶版本:多站点并发检测
import concurrent.futures
import requests
sites = ["https://site1.com", "https://site2.com", "https://site3.org"]
def check_site(url):
try:
r = requests.head(url, timeout=10) # HEAD请求更节省带宽
return url, r.status_code, "在线" if 200 <= r.status_code < 400 else "异常"
except Exception as e:
return url, None, f"离线 - {str(e)}"
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
results = executor.map(check_site, sites)
for url, code, status in results:
print(f"{url} -> {status} (HTTP {code})")
使用ThreadPoolExecutor实现多站点并行检测,大幅缩短总耗时。
Bash脚本实战:轻量级Cron定时检测方案
对于Linux服务器,仅需一行核心命令:
#!/bin/bash
SITE="https://www.example.com"
HTTP_CODE=$(curl -o /dev/null -s -w "%{http_code}" --connect-timeout 10 $SITE)
if [ "$HTTP_CODE" -eq 200 ]; then
echo "网站 $SITE 运行正常"
else
echo "告警:网站 $SITE 异常!HTTP状态码: $HTTP_CODE" | mail -s "网站异常通知" admin@example.com
fi
部署到Cron定时任务:
crontab -e # 添加以下行,每5分钟检查一次 */5 * * * * /path/to/check_site.sh
优化建议:加入日志记录功能:
echo "[$(date)] $SITE -> $HTTP_CODE" >> /var/log/site_check.log
进阶功能:异常告警(邮件/钉钉/微信)
邮件告警(Python示例)
import smtplib
from email.mime.text import MIMEText
def send_alert(subject, body):
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = 'monitor@yourdomain.com'
msg['To'] = 'admin@yourdomain.com'
with smtplib.SMTP('smtp.yourmail.com', 587) as server:
server.starttls()
server.login('username', 'password')
server.send_message(msg)
注意:为安全考虑,密码应使用应用专用密码或环境变量存储。
钉钉/企业微信机器人(Webhook方式)
import requests
def send_dingtalk(text):
webhook_url = "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
data = {"msgtype": "text", "text": {"content": text}}
requests.post(webhook_url, json=data)
常见问题解答(FAQ)
Q1:检测时遇到SSL证书错误怎么办?
A:在Python中设置verify=False,在curl中使用-k参数,但注意这会降低安全性,生产环境建议使用有效证书。
Q2:检测结果出现误报(如网站真实在线但脚本判为离线)? A:常见原因有:①超时设置过短(建议10-20秒);②网站使用了CDN或SSL重定向;③请求头被拦截,解决办法:增加重试机制(如重试2次),并设置User-Agent模拟浏览器。
Q3:需要检测“页面内容是否包含特定关键词”怎么办? A:获取返回内容后使用正则匹配,例如Python中:
if "特定文字" in response.text:
print("内容正常")
Q4:脚本如何实现持续运行而非一次执行?
A:可以将检测逻辑放入无限循环,配合time.sleep(300)实现每5分钟检测一次,更推荐使用系统Cron或systemd timer管理。
Q5:检测域名更换后如何快速修改? A:将站点列表存入外部配置文件(如JSON/YAML/纯文本),在脚本中读取。
import json
with open("sites.json") as f:
sites = json.load(f)
总结与最佳实践建议
- 尽量使用HEAD请求:比GET更节省服务器资源,且能有效检测在线状态。
- 设置合理的超时与重试:建议超时10秒,重试1-2次以过滤临时网络抖动。
- 统一输出格式:使用JSON结构化日志,便于后续存入数据库或对接监控平台(如Prometheus)。
- 告警分级:仅对连续多次检测失败的站点触发告警,减少干扰(如“连续3次离线才告警”)。
- 考虑国际化场景:检测海外站点时,选择地理位置接近的云服务器执行检测,避免误判。
- 定期更新UA和请求头:部分网站会屏蔽无浏览器特征的请求,伪装为Chrome/Firefox更稳定。
通过上述脚本方案,您可以快速搭建一个适合中小型项目的网站监控系统,若需处理数千站点的高并发场景,建议使用异步框架(如Python的asyncio+aiohttp)或专门的监控工具(如UptimeRobot、Prometheus+Blackbox Exporter)。