综合 四段 Shell 脚本:自动备份、清日志、每日巡检、宕机拉起,挂 crontab 的排坑记录

2026-09-04 21:32:51

四段 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 脚本适合留在单台机器的“最后一公里”,做兜底保活和每日巡检。

复制全文 生成海报 Shell 运维 Linux crontab systemd 巡检

推荐文章

程序员茄子在线接单