用户级定时任务的定位
不占 root 的定时任务可以交给用户级 systemd:单元放在 ~/.config/systemd/user/ 下,用 systemctl --user 管理,日志进用户 journal。它适合服务账号(例如 deploy)维护自己的同步、清理与检查任务。需要特别注意的是用户级单元会随登录会话结束而停止,要长期运行必须执行 loginctl enable-linger,否则会出现“任务只在有人登录时才跑”的困惑。
基本信息
| 适用平台 | Linux(systemd 用户实例) |
|---|---|
| 单元路径 | ~/.config/systemd/user/*.timer 与 *.service |
| 常驻开关 | loginctl enable-linger 用户名 |
| 日志 | journalctl --user -u 单元名 |
| 与系统级的差异 | 以该用户身份运行、默认不能绑低端口、生命周期跟随会话 |
| 相关命令 | systemctl --user daemon-reload/list-timers、loginctl show-user |
典型使用场景
- 服务账号自助维护数据同步与清理任务,不申请 root
- 开发机上个人任务的定时执行
- 多用户共享机器上各自隔离调度
- 把原本写在个人 crontab 里、又希望有日志和失败重试的任务规范化
- 需要按用户维度隔离日志与权限的场景
创建与常驻
创建与常驻
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/hello.timer <<'EOF'
[Unit]
Description=user hello
[Timer]
OnCalendar=*-*-* *:00:00
[Install]
WantedBy=timers.target
EOF
cat > ~/.config/systemd/user/hello.service <<'EOF'
[Unit]
Description=user hello job
[Service]
Type=oneshot
ExecStart=/home/deploy/bin/hello.sh
EOF
systemctl --user daemon-reload
systemctl --user enable --now hello.timer
systemctl --user list-timers --no-pager
sudo loginctl enable-linger deploy # 退出登录后仍运行
journalctl --user -u hello.service -n 20 --no-pager # 查看任务日志用户级与系统级差异
| 维度 | 用户级 | 系统级 |
|---|---|---|
| 单元位置 | ~/.config/systemd/user/ | /etc/systemd/system/ |
| 运行身份 | 该登录用户 | 单元内 User= 指定,默认 root |
| 生命周期 | 随会话结束停止(除 linger) | 系统运行期间持续 |
| 开机自启 | WantedBy=timers.target 之类 | 通常 multi-user.target |
| 日志查看 | journalctl --user -u | journalctl -u |
| 权限边界 | 默认不能绑低端口、不能改系统单元 | 以 root 运行时能力更完整 |
用户级 timer 与 service 必须同名成对(hello.timer 对应 hello.service):排查“timer 不触发”时先确认同名 service 存在且 ExecStart 路径可执行。
没有开启 linger 时用户会话退出会终止全部用户级单元:表现是任务只在有人登录时执行,长期任务必须显式 enable-linger 并复核其状态是否生效。
管理其他用户的用户级单元要先切到对应身份:用 sudo -iu deploy 进去再执行 systemctl --user,否则操作的是 root 自己的用户实例,很容易误判成配置没生效。
大量开启 linger 会让 systemd 为每个用户常驻 user@UID 实例,占用内存与文件描述符:只给确实需要长期运行的服务账号开启,并用 loginctl list-users 定期复查。