用 systemd timer 给 VPS 做每日自动快照与清理:一次配置长期省心

举报
yd_290186593 发表于 2026/10/29 13:52:08 2026/10/29
【摘要】 用 systemd timer 固化 VPS 日常运维:清理 apt 缓存、旧内核、journal 日志,并每日快照 /etc 配置。含完整脚本、service/timer 配置和五个踩坑点。

手上这台 40G 的云服务器跑了几个月,最烦的不是性能,而是「不知不觉磁盘就满了」:apt 缓存、旧内核、journal 日志、临时文件,每样都不大,加起来能把根分区吃到 80%。手动 `df -h` 看一眼再清理,隔两周就忘。

这篇记录怎么用 systemd timer 把「每日体检 + 自动清理 + 关键数据快照」固化下来,配置一次,之后不用管。

一、为什么不直接用 cron

cron 能用,但 systemd timer 有几个实际优势:

- 支持 `Persistent=true`,机器关机错过的时间点,开机后会补跑一次;cron 直接跳过。

- 日志统一进 journald,`journalctl -u xxx` 就能看,不用自己重定向到文件。

- 可以声明依赖、资源限制、运行超时,出问题不会卡死。

- 随机延迟 `RandomizedDelaySec` 避免整点一起跑。

对个人 VPS 来说,`Persistent=true` 这一条就够值了。

二、清理脚本

先写清理逻辑,放在 `/usr/local/bin/vps-daily-clean.sh`:

#!/bin/bash
set -euo pipefail
LOG_TAG="vps-clean"

log() { echo "[$(date '+%F %T')] $*"; }

# 1. apt 缓存
apt-get clean
log "apt cache cleaned"

# 2. 无用的自动依赖
apt-get -y autoremove --purge >/dev/null 2>&1 || true
log "autoremove done"

# 3. journal 日志压到 200M 以内
journalctl --vacuum-size=200M >/dev/null 2>&1 || true
log "journal vacuumed"

# 4. /tmp 下超过 7 天的文件
find /tmp -type f -atime +7 -delete 2>/dev/null || true
log "/tmp cleaned"

# 5. 旧内核:保留当前运行的 + 最新一个
CURRENT=$(uname -r)
dpkg -l 'linux-image-*' 2>/dev/null \
  | awk '/^ii/{print $2}' \
  | grep -v "$CURRENT" \
  | grep -v 'linux-image-cloud-amd64' \
  | tail -n +2 \
  | xargs -r apt-get -y purge
log "old kernels purged (kept $CURRENT)"

# 6. 报告磁盘
df -h / | tail -1 | while read -r line; do log "disk: $line"; done

几个注意点:

- `set -euo pipefail` 让脚本出错就退出,但每步清理都加了 `|| true`,避免某一步失败中断整个流程。

- 旧内核那段 `tail -n +2` 是关键:先排除正在运行的内核,再从剩下的里跳过最新的一个,只删更老的。删错内核会导致无法启动。

- `linux-image-cloud-amd64` 是元包,必须排除。

赋权:

chmod +x /usr/local/bin/vps-daily-clean.sh

先手动跑一遍确认没问题:

/usr/local/bin/vps-daily-clean.sh
journalctl -n 20 --no-pager

三、配置 timer

`/etc/systemd/system/vps-daily-clean.service`:

[Unit]
Description=Daily VPS cleanup
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/vps-daily-clean.sh
Nice=10
IOSchedulingClass=idle
TimeoutStartSec=600

`/etc/systemd/system/vps-daily-clean.timer`:

[Unit]
Description=Run VPS cleanup daily

[Timer]
OnCalendar=*-*-* 04:30:00
RandomizedDelaySec=30m
Persistent=true
Unit=vps-daily-clean.service

[Install]
WantedBy=timers.target

`Nice=10` 和 `IOSchedulingClass=idle` 让清理任务在低优先级跑,不会和业务抢资源。

启用:

systemctl daemon-reload
systemctl enable --now vps-daily-clean.timer
systemctl list-timers --all | grep vps

`list-timers` 会显示下次触发时间和上次运行结果,这是最直接的验证方式。

四、加一个配置快照

光清理不够,配置改坏了想回滚得有备份。加一段每天打包 `/etc` 里的关键配置:

BACKUP_DIR=/var/backups/vps
mkdir -p "$BACKUP_DIR"
tar czf "$BACKUP_DIR/etc-$(date +%F).tar.gz" \
  /etc/ssh /etc/systemd/system /etc/nginx 2>/dev/null || true
# 只保留最近 14 份
ls -1t "$BACKUP_DIR"/etc-*.tar.gz 2>/dev/null | tail -n +15 | xargs -r rm -f

放在清理脚本末尾即可。这样每天有一份 `/etc` 快照,保留 14 天,出问题直接解包对照。

五、踩过的坑

**1. timer 不触发**:`systemctl enable` 了但没 `--now`,或者只 enable 了 service 没 enable timer。检查 `systemctl list-timers` 里有没有条目。

**2. `Persistent=true` 依赖时间戳文件**:在 `/var/lib/systemd/timers/` 下。如果手动删了这个目录,补跑功能会失效,重新 `daemon-reload` 会重建。

**3. 删内核把系统搞挂**:一定要用 `uname -r` 排除当前内核,别用 `dpkg -l | head -1` 这种粗暴写法。

**4. journal 占用比想象大**:默认上限是磁盘的 10%,40G 盘就是 4G。`--vacuum-size=200M` 收得比较狠,但排查问题时 200M 够用了。

**5. 脚本在 timer 里跑失败但手动能跑**:多半是 PATH 不同。systemd 的 PATH 很精简,脚本里用绝对路径最稳。

小结

整套配置不到 50 行,解决的是「日常运维容易忘」这个真问题。核心就三件事:清理脚本 + service + timer,加上 `Persistent=true` 保证不漏跑。

配好之后每天 4:30 左右自动跑一次,磁盘长期稳定在 20% 以下,再也不用惦记。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。