从入门到精通的自动化运维指南
目录导读
- 为什么需要磁盘清理脚本 – 磁盘告警的痛点与自动化需求
- 清理脚本的核心设计原则 – 安全、可追溯、可配置
- 基础清理命令解析 –
rm、find、du、df的实战组合 - 进阶技巧:按时间/大小/类型精准筛选 – 摆脱“一刀切”删除
- 日志与安全机制 – 防止误删的五大防护策略
- 完整脚本实例与逐行解读 – 可直接部署的生产级代码
- 计划任务与监控集成 – Crontab、Systemd Timer 与告警联动
- 常见问题答疑(FAQ) – 针对高频率疑问的精准回答
为什么需要磁盘清理脚本?
运维人员的日常中,最让人心跳加速的告警之一就是:Disk space has reached 90%,手动清理不仅耗时,且容易误操作,编写一个磁盘清理脚本的核心目的有三:

- 自动化:在无人工干预下,定时释放磁盘空间。
- 精准化:只删除“过期”或“临时”文件,绝不触碰系统关键数据。
- 可审计:每次清理行为留有日志,方便追责与回滚。
根据统计,合理的清理脚本能减少 70% 的磁盘满告警事件,并且大幅缩短故障恢复时间。
清理脚本的核心设计原则
在动手写代码前,必须明确四个原则:
- 白名单机制:明确“只删什么”,而非“除了什么不删”。
- 干跑模式(Dry-run):正式执行前,必须先输出“将要删除的文件列表”,人工确认。
- 时间阈值可选:如
-30代表删除30天前的文件,但必须支持参数传入。 - 错误处理:磁盘空间不足时容易引发命令中断,需捕获错误码并发送告警。
基础清理命令解析
下面是最常用的命令组合,建议先掌握再写脚本:
| 命令 | 用途 | 关键参数 |
|---|---|---|
df -h |
查看磁盘分区使用率 | -h 人性化显示 |
du -sh * |
统计目录大小 | -s 汇总,-h 可读 |
find |
按条件查找文件 | -mtime、-size、-type |
rm -rf |
强制删除 | 慎用,需与 find 配合 |
基础组合示例(删除 /tmp 下7天前的 .log 文件):
find /tmp -type f -name "*.log" -mtime +7 -exec rm -f {} \;
进阶技巧:按时间/大小/类型精准筛选
1 按时间维度
-mtime(修改时间)与 -atime(访问时间)的选择很重要:
- 备份文件用
-mtime +30(30天前修改过)。 - 缓存文件用
-atime +7(7天前未被访问)。
2 按大小维度
find /var/log -type f -size +100M -delete
> 会删除大于100MB的任何文件,需谨慎确认。
3 按类型与目录排除
find /home -type f \( -name "*.tmp" -o -name "*.cache" \) -not -path "/home/public/*" -delete
支持逻辑运算符与排除目录,实战中几乎必用。
日志与安全机制
误删是磁盘清理脚本最大的风险,以下策略必须至少实现3条:
- 重建回收站:删除前将文件
mv到/tmp/recycle_$(date +%F)目录,保留7天。 - 检查变量非空:务必判断目录变量是否为空,防止
rm -rf /。 - 软链接防护:用
-type f限制,避免删除链接目标。 - 并发锁:防止脚本被重复执行,使用
flock或mkdir锁文件。 - 执行前备份列表:
find ... > /var/log/clean_list_$(date +%F).txt,便于恢复。
完整脚本实例与逐行解读
以下是一个生产环境级脚本,请按需修改路径与阈值:
#!/bin/bash
# =============================================
# Author: OpsMaster
# Description: Safe disk cleanup with dry-run & logging
# Usage: ./disk_cleaner.sh [--dry-run] [--days=30] [--dir=/var/tmp]
# =============================================
# 初始化变量
DRY_RUN=false
DAYS=30
TARGET_DIR="/var/tmp"
LOG_FILE="/var/log/disk_cleaner.log"
RECYCLE_BIN="/tmp/recycle_$(date +%F)"
# 参数解析
while [[ "$#" -gt 0 ]]; do
case $1 in
--dry-run) DRY_RUN=true ;;
--days) DAYS="$2"; shift ;;
--dir) TARGET_DIR="$2"; shift ;;
*) echo "Unknown option: $1"; exit 1 ;;
esac
shift
done
# 安全检测
if [ -z "$TARGET_DIR" ] || [ ! -d "$TARGET_DIR" ]; then
echo "ERROR: Invalid target directory." | tee -a "$LOG_FILE"
exit 1
fi
# 日志函数
log_info() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] INFO: $1" | tee -a "$LOG_FILE"
}
# 干跑与正式执行
if $DRY_RUN; then
log_info "DRY-RUN mode. Files to be deleted (older than ${DAYS} days):"
find "$TARGET_DIR" -type f -mtime +"$DAYS" -name "*.tmp" -o -name "*.log" -print
else
log_info "Starting cleanup for ${TARGET_DIR} (older than ${DAYS} days)"
mkdir -p "$RECYCLE_BIN"
# 移动到回收站而非直接删除
find "$TARGET_DIR" -type f \( -name "*.tmp" -o -name "*.log" \) -mtime +"$DAYS" \
-exec mv {} "$RECYCLE_BIN/" \; -exec touch "$RECYCLE_BIN/$(basename {}).moved" \;
log_info "Moved files to ${RECYCLE_BIN}"
fi
# 磁盘空间报告
df -h | tee -a "$LOG_FILE"
逐行深度解析(关键四行):
find ... -exec mv {} "$RECYCLE_BIN/"– 安全删除,非rm。touch ... .moved– 记录原路径的痕迹,便于回溯。$DRY_RUN分支 – 先打印结果,避免盲目删除。tee -a– 日志双写(控制台+文件)。
计划任务与监控集成
1 Crontab 定时执行
# 每天凌晨2点执行,并输出日志 0 2 * * * /usr/local/bin/disk_cleaner.sh --days=30 --dir=/var/tmp >> /var/log/disk_cleaner_cron.log 2>&1
2 Systemd Timer(推荐)
创建 cleaner.service(执行命令)和 cleaner.timer(定时触发):
# /etc/systemd/system/disk-clean.timer [Unit] Description=Run disk cleaner daily [Timer] OnCalendar=*-*-* 02:00:00 Persistent=true [Install] WantedBy=timers.target
3 与监控告警联动
在脚本开头判断 df -h / | awk 'NR==2 {print $5}' 的百分比,若超过90%,直接通过 curl 发送webhook告警到钉钉/企业微信。
常见问题答疑(FAQ)
Q1:脚本误删了重要文件,可以恢复吗?
A: 如果你使用了上述“回收站”机制(mv 而非 rm),可以进入 /tmp/recycle_$(date) 恢复,否则,建议立刻停止写入磁盘,并使用 extundelete 尝试恢复(不保证100%成功)。
Q2:清理日志文件后,服务报错“无法写入日志”,怎么办?
A: 这是常见坑,原因通常是删除后未重开文件描述符,推荐用 logrotate 而非纯 find+rm,它能在清理后执行 postrotate 脚本(如 systemctl reload rsyslog)。
Q3:为什么我的 find 命令在云服务器上很慢?
A: 云服务器磁盘(常用SDD)随机读取查询慢,优化技巧:find 指定目录层级 -maxdepth 2;优先使用 -name 匹配;避免遍历整个 。
Q4:能否递归清理 Docker 的残留日志?
A: 可以,Docker容器日志默认在 /var/lib/docker/containers/*/*-json.log,加上 -name "*.log" 并配合 truncate -s 0(清空而非删除,防止容器句柄丢失)即可。
Q5:如何判断脚本是否执行成功?
A: 检查 退出码(0为成功),同时查看日志末尾是否有 ERROR 关键词,建议在脚本结尾加上 if [ $? -eq 0 ]; then exit 0; else exit 1; fi。
延伸阅读: 若想进一步优化,可研究 tmpwatch 工具(针对 /tmp 的专属清理),或者利用 ZFS/Btrfs 文件系统的快照功能,实现秒级“时间点”回滚。
希望这篇磁盘清理脚本编写指南能让你告别“磁盘告警综合症”,务必先在小规模环境测试至少一周,再部署到生产。充分验证过的脚本,才是好脚本。