systemd 隐藏技能:别再只会 sudo systemctl restart 了
systemctl restart nginx。敲完。搞定。关掉终端。
这是 99% Linux 用户和 systemd 的日常关系。systemd 是个巨复杂的工具,但你只用了它的三个子命令。
不是你的问题——入门教程就只教这三个。
但这玩意儿真正实用的功能藏在后面。这篇文章翻几个出来,都是你明天上班就能用的。
一、不再 etc/cron.d 写定时任务:systemd timer 才是正解
cron 最大的痛:环境变量和 systemd 不一致。你在 shell 里能跑通的脚本,cron 里就是不行。
systemd timer 直接解决方法:你的脚本在 systemd 单元中运行,环境变量、PATH、依赖关系全在同一个框架里。
写一个 timer 两步走:
第一步,创建 service 单元 /etc/systemd/system/backup-db.service:
[Unit]
Description=每日数据库备份
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-db.sh
第二步,创建 timer 单元 /etc/systemd/system/backup-db.timer:
[Unit]
Description=每天凌晨3点备份
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
启用:
sudo systemctl daemon-reload
sudo systemctl enable --now backup-db.timer
OnCalendar 的语法比 cron 更灵活,举几个例子:
| 写法 | 含义 |
|---|---|
daily | 每天 00:00 |
*-*-* 03:00:00 | 每天凌晨 3 点 |
Mon..Fri 09:30:00 | 工作日 9:30 |
*-*-1,15 00:00:00 | 每月 1 号和 15 号 |
*:0/15 | 每 15 分钟 |
Persistent=true 的含义很重要:如果机器在预定时间处于关机状态,启动后立即补跑一次。cron 做不到,anacron 勉强但难用。
cron 已经不需要了。 我在所有 VPS 上已经全部换成 timer,再也没出过「脚本不执行」的玄学问题。
二、不动原配置文件改行为:systemctl edit 和 drop-in
这是 systemd 被低估最多的功能。
想改 nginx 的启动参数?传统做法:vim /etc/systemd/system/nginx.service,但下次 nginx 包升级会覆盖你的改动。
drop-in 解决这个问题。
sudo systemctl edit nginx
这会打开一个空文件。你只写要覆盖的部分:
[Service]
ExecStart=
ExecStart=/usr/sbin/nginx -g 'daemon off;' --custom-flag
保存退出后,systemd 自动生成 /etc/systemd/system/nginx.service.d/override.conf。优先级高于原始单元文件,下包更新不会覆盖。
不需要 copy 整个单元文件来找要改哪一行。 只写要覆盖的配置段+键名。
多个 drop-in 文件按名称排序加载,也是 systemctl cat nginx 可以查看合并后的完整配置。
三、journalctl 不是用来翻墙的
大多数人查日志时的操作:tail -f /var/log/nginx/access.log。
如果 service 已经把日志交给了 journald,那你用 journalctl 可以做得更好。
按 unit 查:
journalctl -u nginx -f
只看 nginx 的日志,同时 f 参数让你像 tail -f 一样持续追踪。
按时间查:
journalctl -u nginx --since "10 min ago"
journalctl -u nginx --since "2026-06-01" --until "2026-06-02 12:00"
不需要 grep 去翻 /var/log/ 下的大文件。
按优先级查:
journalctl -u nginx -p err -b
只看当前这次启动以来的错误日志。-p err 表示 level >= err(err、crit、alert、emerg)。
实时查看最新 50 行并追踪:
journalctl -u nginx -n 50 -f
查看上次启动的日志:
journalctl -u nginx -b -1
-b -2 是上上次,依此类推。crash 后分析最有用。
按 message 关键词查:
journalctl -u nginx | grep "Connection refused"
说实话,这比 grep 找 /var/log/syslog 效率高得多——因为 -u 已经过滤到该服务,数据量小了几个数量级。
⚠️ 一个坑:journald 默认日志持久化需要手动配。如果你没有做,重启后只能看到当前启动的日志。
sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald
做一次,之后日志持久到磁盘。
四、用户级 systemd:每个用户都可以有自己的服务
不是只有 root 才能用 systemd。普通用户也能 systemctl --user 管理自己的守护进程。
systemctl --user enable --now my-service.timer
这对不需要 root 权限的场景很实用:个人代理隧道、开发环境服务、后端 API 模拟器。
用户服务的文件放到 ~/.config/systemd/user/ 下。
注意事项:
- 用户服务默认在用户登录时启动,退出时停止。
- 如果想要无登录时也运行(比如开机就起一个 trojan 客户端),需要
loginctl enable-linger $USER
sudo loginctl enable-linger $(whoami)
开了 linger 后,用户服务在无登录状态下也会运行。对后台常驻服务非常有用。
五、分析开机慢:systemd-analyze
先来条命令跑一下:
systemd-analyze blame
输出按启动耗时从长到短排列,一眼看出哪个 service 拖慢了开机。
5.234s networkd-wait-online.service
3.541s plymouth-quit-wait.service
2.102s dev-sda1.device
1.234s postgresql.service
...
看到 networkd-wait-online.service 5 秒多——如果你不需要启动时网络完全就绪(多数场景不需要),可以直接 disable 掉:
sudo systemctl disable systemd-networkd-wait-online.service
图形化分析:
systemd-analyze plot > /tmp/boot.svg
浏览器打开 SVG,每个服务的启动时间、依赖关系、并行执行一目了然。
六、临时覆盖环境变量和参数(调试利器)
不想改配置,只是临时跑一次?
systemctl run user@1234.service -- -D 2>&1 | tee /tmp/debug.log
或者一个更实用的模式——直接在命令行里覆盖 service 的环境变量:
sudo systemctl set-environment FOO=bar
sudo systemctl restart my-service
set-environment 设置的是全局环境变量,对该用户的所有 systemd 服务生效。调试完记得 unset。
七、几个小但管用的
查看 service 文件最终合并态:
systemctl cat nginx
查看 service 依赖树:
systemctl list-dependencies nginx
看所有 timer 及下次执行时间:
systemctl list-timers --all
这是我最常用的一条命令之一。一眼可以看到每个定时任务的下次执行时间和已过去的时间。
mask 一个 service(彻底禁用):
sudo systemctl mask nginx
disable 只是不让开机自启,但其他服务还可以依赖它来启动它。mask 建立了一个空符号链接到 /dev/null——任何企图启动这个服务的操作都会静默失败。极其有用,比如系统预装但你不需要的服务。
收尾
systemd 不止是 start/stop/restart。它是一个完整的系统管理框架,覆盖了初始化、服务、定时任务、日志、boot 分析、资源限制。
这篇文章说的几个点,每一个都是你遇到问题、去 StackOverflow 搜了三个小时之后才「原来这么简单」的事情。
如果只带走三个:
- 定时任务用 timer,别碰 cron
- 改配置用 drop-in,别碰原文件
- 查日志用
journalctl -u,别再 tail 日志文件
原文发表于 cn-res.vip,没有版权自由转载。标明出处非常感谢,删了也没事。