86 lines
2.2 KiB
Markdown
Executable File
86 lines
2.2 KiB
Markdown
Executable File
# Systemd Timer 模式(2026-05-30)
|
||
|
||
## 适用场景
|
||
|
||
需要定期执行的后台任务(备份、清理、统计),且需要**无需 sudo**。
|
||
|
||
## 对比 cron
|
||
|
||
| | systemd timer | cron |
|
||
|---|---|---|
|
||
| sudo | 不需要(用户级) | 需要(系统级) |
|
||
| 环境变量 | 默认完整用户环境 | 需要手动设置 |
|
||
| 状态查询 | `systemctl --user list-timers` | `crontab -l` |
|
||
| 随机延迟 | `RandomizedDelaySec=` 防雪崩 | 手动加扰动 |
|
||
| 失败告警 | 可绑定到 service 的 OnFailure | 无内置 |
|
||
|
||
## 标准模板:每日备份(zhiyi-backup)
|
||
|
||
### zhiyi-backup.service
|
||
```ini
|
||
[Unit]
|
||
Description=ZhiYi Daily Backup
|
||
After=zhiyid.service
|
||
PartOf=zhiyid.service
|
||
|
||
[Service]
|
||
Type=oneshot
|
||
ExecStart=/usr/bin/curl -s -X POST http://localhost:7821/api/v1/admin/backup \
|
||
-H "X-API-Key: zhiyi-dev-key-2026"
|
||
StandardOutput=journal
|
||
StandardError=journal
|
||
|
||
[Install]
|
||
WantedBy=default.target
|
||
```
|
||
|
||
### zhiyi-backup.timer
|
||
```ini
|
||
[Unit]
|
||
Description=ZhiYi Daily Backup Timer (3:00 AM)
|
||
|
||
[Timer]
|
||
OnCalendar=*-*-* 03:00:00
|
||
Persistent=true
|
||
RandomizedDelaySec=30m
|
||
|
||
[Install]
|
||
WantedBy=timers.target
|
||
```
|
||
|
||
## 部署流程
|
||
|
||
```bash
|
||
# 1. 放 service 文件
|
||
mkdir -p ~/.config/systemd/user
|
||
cp zhiyi-backup.service ~/.config/systemd/user/
|
||
cp zhiyi-backup.timer ~/.config/systemd/user/
|
||
|
||
# 2. reload + enable + start
|
||
systemctl --user daemon-reload
|
||
systemctl --user enable --now zhiyi-backup.timer
|
||
|
||
# 3. 验证
|
||
systemctl --user list-timers
|
||
# 期望:Sun 2026-05-31 03:00:00 CST 24h 57min left - zhiyi-backup.timer zhiyi-backup.service
|
||
|
||
# 4. 手动触发(测试用)
|
||
systemctl --user start zhiyi-backup.service
|
||
```
|
||
|
||
## 常用 timer 表达式
|
||
|
||
| 表达式 | 含义 |
|
||
|--------|------|
|
||
| `*-*-* 03:00:00` | 每天 3:00 AM |
|
||
| `*-*-01 00:00:00` | 每月 1 日 |
|
||
| `Mon *-*-* 09:00:00` | 每周一 9:00 AM |
|
||
| `*-*-* *:0/15:0` | 每 15 分钟 |
|
||
| `*-*-* 03:00:00` + `RandomizedDelaySec=30m` | 每天 3:00-3:30 随机 |
|
||
|
||
## 关键点
|
||
|
||
- `Type=oneshot`:Timer 触发一次,service 执行一次(不保持 running 状态)
|
||
- `PartOf=xxx.service`:停止 timer 时自动停止 service
|
||
- `Persistent=true`:服务停机期间错过的执行时间,在恢复后补执行
|
||
- `RandomizedDelaySec`:防多服务同时触发(雪崩) |