四段 Shell 脚本:自动备份、清日志、每日巡检、宕机拉起,挂 crontab 的排坑记录
日常备份、清理过期日志、定时巡检、服务宕机自动拉起,这几类重复操作我整理了一套简化版 Shell 脚本,CentOS/Ubuntu 都能跑,放 crontab 里可以无人值守。
统一约定
- 脚本统一放
/usr/local/scripts/,加执行权限; - 脚本内一律用绝对路径;
- 第一行
#!/bin/bash; - 先手动跑通,再进 crontab;
- 备份、清理这类重要操作写日志;
- 目录权限不要给 777;
- 删除前先列出来确认,生产路径不要裸
rm。
1. 项目自动备份
#!/bin/bash
PROJECT_PATH=/opt/project
BACKUP_PATH=/home/backup
DATE=$(date +%Y%m%d)
BACKUP_FILE="$BACKUP_PATH/project-$DATE.tar.gz"
mkdir -p "$BACKUP_PATH"
tar -zcvf "$BACKUP_FILE" "$PROJECT_PATH" >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo "$DATE 项目备份成功,文件:$BACKUP_FILE" >> "$BACKUP_PATH/backup_log.log"
else
echo "$DATE 项目备份失败" >> "$BACKUP_PATH/backup_error.log"
fi
# 要清理 N 天前的旧备份,追加一行:
# find "$BACKUP_PATH" -mtime +7 -name "project-*.tar.gz" -delete
成功和失败日志分开写,后续看错误日志就能判断备份有没有出问题。
2. 清理过期日志
#!/bin/bash
find /var/log /tmp /opt/project/log -name "*.log" -mtime +15 -delete
find /tmp -type f -mtime +15 -delete
echo "$(date +%Y-%m-%d) 过期日志清理完成" >> /var/log/clean_log.log
-mtime +15 表示修改时间距离现在超过 15 天。第一次跑先去掉 -delete 执行一遍,确认列出的文件都能删再放开。
第二条会把 /tmp 下所有超过 15 天的普通文件清掉,不只有 .log,如果 /tmp 里有需要保留的文件,第二行要自己加过滤条件。
3. 每日巡检
#!/bin/bash
LOG_FILE=/var/log/server_check.log
exec >> "$LOG_FILE" 2>&1
echo "===== $(date '+%Y-%m-%d %H:%M:%S') 巡检开始 ====="
df -h | grep -v tmpfs
free -h
grep -i error /var/log/messages
echo "===== 巡检结束 ====="
/var/log/messages 是 CentOS/RHEL 的路径,Ubuntu 上要改成 /var/log/syslog。整段输出追加进巡检日志,cron 执行时也不会把结果发到邮箱。
4. 服务宕机自动拉起
先用 ps + grep 的写法:
#!/bin/bash
SERVICE_NAME=nginx
if ! ps -ef | grep "$SERVICE_NAME" | grep -v grep >/dev/null; then
systemctl restart "$SERVICE_NAME"
echo "$(date '+%Y-%m-%d %H:%M:%S') nginx 进程不存在,已触发重启" >> /var/log/service_monitor.log
fi
取舍:ps -ef | grep 对单个主进程够用,但 nginx 这类进程会连带子进程一起被 grep 匹配,偶有误判。更严谨的做法是直接问 systemd:
#!/bin/bash
if [ "$(systemctl is-active nginx)" != "active" ]; then
systemctl restart nginx
echo "$(date '+%Y-%m-%d %H:%M:%S') nginx 状态非 active,已触发重启" >> /var/log/service_monitor.log
fi
crontab 示例
# 每天 02:00 项目备份
0 2 * * * /usr/local/scripts/backup.sh
# 每天 03:00 清理过期日志
0 3 * * * /usr/local/scripts/clean_log.sh
# 每小时整点巡检
0 * * * * /usr/local/scripts/server_check.sh
# 每 10 分钟检查一次服务保活
*/10 * * * * /usr/local/scripts/service_monitor.sh
脚本文件名按实际存放位置和命名替换。
常见的坑:手动能跑,定时任务不执行
- PATH 不全:cron 不加载 shell 的 PATH,命令最好写绝对路径,或者在脚本开头
source /etc/profile。 - 相对路径:cron 的工作目录默认是用户 home(root 就是
/root),脚本里的路径必须写全。 - 没加执行权限或属主不对:
chmod +x /usr/local/scripts/*.sh,属主改成 root:chown root:root /usr/local/scripts/*.sh - Windows 换行符:在 Windows 上编辑过的脚本会带
\r,报错很怪。先转一遍:dos2unix /usr/local/scripts/*.sh
排查步骤:先在交互 shell 里手动跑通,再用 bash -x script.sh 跟踪,看哪条命令在 cron 环境下不认。
CentOS / Ubuntu 差异
- 服务命令:CentOS 还兼容老
service命令,Ubuntu 下统一用systemctl。 - 系统日志:CentOS 在
/var/log/messages,Ubuntu 在/var/log/syslog,巡检脚本要按系统分开。 - 安装命令:CentOS 用
yum,Ubuntu 用apt。 - Ubuntu 对脚本里的空格和换行符校验更严,从别处拷贝的脚本先过一遍
dos2unix再跑。
这套脚本覆盖备份、日志清理、巡检、服务拉起四个基础场景。多节点生产环境还是得靠 Ansible/SaltStack 或 CI/CD 编排,Shell 脚本适合留在单台机器的“最后一公里”,做兜底保活和每日巡检。