每日自动化安全巡检脚本住宅服务器
为什么要给住宅服务器做每日安全巡检?
很多朋友用旧电脑或树莓派搭建家庭服务器,跑NAS、博客、下载机或内网服务。
这类服务器长期开机,如果系统更新不及时、磁盘爆满、服务意外停止或遭到暴力破解,都会影响使用甚至导致数据丢失。每日自动化安全巡检脚本可以帮你每天固定时间检查关键指标,一旦发现问题就发通知,让你及时处理。
本文面向零基础用户,一步步教你写出属于自己的巡检脚本,并配置成定时任务自动运行。
准备条件:系统环境与基本工具
绝大多数住宅服务器运行的是 Debian / Ubuntu 系统。
请确保你已通过 SSH 或直接连接服务器终端,并拥有 sudo 权限。
检查系统版本:
cat /etc/os-release
如果输出显示 Debian 或 Ubuntu 即可。
另外需要安装 mailutils 或 curl(用于后续通知),如果只想先用本地日志,可以暂时不装。
建议先准备一个文本编辑器(nano 或 vim),本文用 nano 演示。
编写巡检脚本:核心步骤
1. 创建脚本文件
在 /usr/local/bin/ 下创建一个名为 daily_check.sh 的脚本:
sudo nano /usr/local/bin/daily_check.sh
2. 写入检查逻辑
把下面内容粘贴进去(根据你的实际需要可增删):
#!/bin/bash
# 每日安全巡检脚本 - 适用于 Debian/Ubuntu
# 检查时间:每天 8:00
# 定义日志文件(可改为邮件或 Webhook)
LOG_FILE="/var/log/daily_check_$(date +%Y%m%d).log"
echo "===== 巡检时间: $(date) =====" > $LOG_FILE
# 1. 系统更新检查
echo "[1] 检查可用更新..." >> $LOG_FILE
sudo apt update -qq 2>/dev/null
apt list --upgradable 2>/dev/null | grep -v "Liste..." >> $LOG_FILE
if [ $? -eq 0 ]; then
echo "有可用更新,请及时升级。" >> $LOG_FILE
else
echo "系统已是最新。" >> $LOG_FILE
fi
# 2. 磁盘使用率检查
echo "[2] 磁盘使用情况..." >> $LOG_FILE
DISK_USAGE=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')
if [ $DISK_USAGE -gt 85 ]; then
echo "警告: 根分区使用率已达 ${DISK_USAGE}%!" >> $LOG_FILE
else
echo "根分区使用率: ${DISK_USAGE}% (正常)" >> $LOG_FILE
fi
# 3. 关键服务检查(以 nginx 和 sshd 为例)
for service in nginx sshd; do
if systemctl is-active --quiet $service; then
echo "[3] $service 运行正常" >> $LOG_FILE
else
echo "[3] 警告: $service 未运行!" >> $LOG_FILE
fi
done
# 4. 检查异常登录(查看 lastb 或 /var/log/auth.log)
FAILED_LOGINS=$(lastb | wc -l)
if [ $FAILED_LOGINS -gt 0 ]; then
echo "[4] 最近有 ${FAILED_LOGINS} 次失败登录尝试,请检查安全。" >> $LOG_FILE
echo "详细信息如下:" >> $LOG_FILE
lastb | head -10 >> $LOG_FILE
else
echo "[4] 无失败登录记录" >> $LOG_FILE
fi
# 5. 防火墙状态(如果使用 ufw)
if command -v ufw &>/dev/null; then
if ufw status | grep -q active; then
echo "[5] UFW防火墙已启用" >> $LOG_FILE
else
echo "[5] 警告: UFW防火墙未启用!" >> $LOG_FILE
fi
fi
# 输出结束
echo "===== 巡检完成 =====" >> $LOG_FILE
# 如果想通过邮件发送结果,取消下面注释并配置 mailutils
# cat $LOG_FILE | mail -s "$(hostname) 每日巡检报告 $(date)" your@email.com
# 如果想通过钉钉/微信机器人发送,参考避坑指南部分
注意:将 your@email.com 替换为你的邮箱,并确认已安装 mailutils(sudo apt install mailutils)。
也可改用 Webhook 发送到钉钉或企业微信。
3. 赋予执行权限
sudo chmod +x /usr/local/bin/daily_check.sh
设置定时任务自动化运行
使用 crontab 让脚本每天早上 8:00 执行:
sudo crontab -e
第一次运行会让你选择编辑器,选 nano(编号1)。
在文件末尾添加一行:
0 8 * * * /usr/local/bin/daily_check.sh
保存退出(Ctrl+X,Y,回车)。
确认定时任务已添加:
sudo crontab -l
你会看到刚才添加的行。
此时脚本将在每天 8:00 自动运行,日志文件保存在 /var/log/ 下,文件名带有日期。
结果通知:如何及时知道异常?
方法一:邮件通知(配置最简单)
如果服务器能发邮件(推荐使用 mailutils + 本地 postfix 或 ssmtp),取消脚本中邮件发送行的注释,并配置好发件账号。注意:住宅服务器公网 IP 可能被邮件服务商拦截,建议使用第三方 SMTP(如 QQ邮箱/163邮箱)。
具体配置:安装 ssmtp,编辑 /etc/ssmtp/ssmtp.conf,填入邮箱账号密码。
方法二:钉钉/企业微信机器人
如果你有钉钉群,创建自定义机器人获取 Webhook 地址。
在脚本末尾增加调用 curl 的代码:
# 钉钉机器人示例
WEBHOOK="https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
MESSAGE=$(cat $LOG_FILE | python3 -c "import json,sys; print(json.dumps({'msgtype':'text','text':{'content':sys.stdin.read()}}))")
curl -s -H "Content-Type: application/json" -d "$MESSAGE" $WEBHOOK > /dev/null
替换 YOUR_TOKEN。
避坑指南与常见问题
Q1: 脚本执行时提示 sudo: no tty present?
A: 因为 crontab 运行时不带交互终端。解决方法:在 crontab 中指定使用 sudo 并配置免密码,或者在脚本内对需要 sudo 的命令使用 sudo -n 参数(前提是已在 /etc/sudoers 中为该用户设置 NOPASSWD)。建议将脚本中的 sudo 命令都改为带 -n,然后通过 visudo 添加:username ALL=(ALL) NOPASSWD: /usr/local/bin/daily_check.sh。
Q2: 日志文件太大怎么办?
A: 脚本每天生成一个日志文件,可以添加日志轮转(logrotate),或者脚本内只保留最近7天的日志:在脚本开头增加 find /var/log/daily_check_* -mtime +7 -delete。
Q3: 检查项不够用,如何扩展?
A: 在脚本的相应位置增加 checks。例如检查内存使用:free -m | awk 'NR==2{printf "%.0f", $3*100/$2 }';检查 Docker 容器状态:docker ps -q | wc -l。
Q4: 能不能把结果直接写到控制台而不用文件?
A: 可以。在脚本最后用 cat $LOG_FILE 覆盖文件追加,但 crontab 默认会将标准输出通过邮件发给用户(如果配置了 MAILTO)。更简单:保留日志文件,方便回溯。
验证效果:确认巡检脚本正常工作
手动执行一次脚本看输出:
sudo /usr/local/bin/daily_check.sh
执行后检查日志文件:
cat /var/log/daily_check_$(date +%Y%m%d).log
你应该看到类似“系统已是最新”“根分区使用率: 45% (正常)”“nginx 运行正常”等信息。
如果配置了通知,等待定时任务到点触发,或手动测试 crontab(可以临时把时间改成 */1 * * * * 每1分钟执行一次,测试完再改回来)。
从今天起,你的住宅服务器就能自动每天做一次安全体检,帮你省下手动查看的精力。
遇到异常时优先检查日志文件和通知渠道是否正确配置。
如果你想进一步优化,可以增加硬盘健康状态(smartctl)或证书到期检查,让脚本更贴合你的实际环境。