概述
systemd是大多数发行版的PID 1初始化系统,负责按依赖并行启动 unit、用 cgroup 跟踪进程、把日志收进二进制存储核心组件:
systemd:管理器本体systemctl:控制 unit 的命令行前端journald:结构化日志守护进程logind、networkd、resolved等可选子系统
架构:
flowchart LR A["systemctl"] -->|"D-Bus"| B["systemd (PID 1)"] B --> C["service"] B --> D["timer"] B --> E["mount / socket / target"] C & D & E -->|"stdout stderr"| F["journald"] F --> G["journalctl"]
快速开始
console
$ systemctl status sshd # 看服务状态与最近日志
$ systemctl restart sshd # 重启服务
$ systemctl enable --now sshd # 设开机自启并立刻启动
$ journalctl -u sshd -e # 跳到该服务日志末尾
Unit
- unit 是 systemd 的管理对象,类型由文件扩展名区分:
.service守护进程或一次性命令,最常见.timer定时触发另一个 unit,现代替代cron的方案.socket按需激活:第一个连接到来才启动对应 service.target一组 unit 的汇聚点,如multi-user.target、graphical.target.mount挂载点、.path文件变化触发、.slice资源分组
- 查找顺序:
/etc/systemd/system>/run/systemd/system>/usr/lib/systemd/system,同名覆盖,自己的修改放/etc - 修改 unit 文件后必须
systemctl daemon-reload让 PID 1 重读,忘了这一步改了等于没改
systemctl
状态与列表:
console$ systemctl status UNIT # 状态加最近日志 $ systemctl list-units --type=service --state=running $ systemctl list-unit-files --state=enabled $ systemctl is-active UNIT # 输出 active/inactive,退出码可判断 $ systemctl cat UNIT # 看实际生效的 unit 文件 $ systemctl show UNIT -p ExecStart # 查单个属性 $ systemctl list-dependencies UNIT生命周期:
console$ systemctl start|stop|restart UNIT $ systemctl reload UNIT # 不中断地重读配置 $ systemctl reload-or-restart UNIT # 有 reload 用之,否则重启 $ systemctl enable|disable UNIT # 开机自启开关,不改变当前状态 $ systemctl mask|unmask UNIT # 彻底禁用,连手动 start 都不行电源与目标:
reboot、poweroff、suspend、hibernate,isolate multi-user.target立即切到无图形界面,set-default graphical.target改默认启动目标用户级:
systemctl --user管理当前用户的服务,unit 放~/.config/systemd/user/,随登录会话生命周期
编写 service
最小可用的
/etc/systemd/system/myapp.service:ini[Unit] Description=My App # 描述 Wants=network-online.target # 弱依赖,尽量拉起 After=network-online.target # 排序:网络就绪后再启动 [Service] Type=simple # ExecStart 前台进程即主进程 User=myapp # 降权运行 WorkingDirectory=/srv/myapp ExecStart=/usr/bin/myapp --config /etc/myapp.toml Restart=on-failure # 异常退出自动拉起 RestartSec=5 # 拉起间隔 [Install] WantedBy=multi-user.target # enable 时挂到哪个 targetType选择:simple:前台进程,默认值forking:进程会 fork 到后台,主进程退出后才算就绪oneshot:跑完即退出,配RemainAfterExit=yes显示 activenotify:进程自己调sd_notify报告就绪,systemd 自家服务多用
日志:service 默认把 stdout 与 stderr 收进 journal,不需要再重定向到文件
Timer
myapp.timer与同名myapp.service配对:ini[Unit] Description=Run myapp daily [Timer] OnCalendar=*-*-* 04:00:00 # 每天 04:00 Persistent=true # 关机错过的开机后补跑 RandomizedDelaySec=10m # 随机抖动,避免整点拥塞 [Install] WantedBy=timers.targetOnCalendar语法用systemd-analyze calendar "..."离线验证,相对定时用OnBootSec=与OnUnitActiveSec=相比
cron的优势:日志进 journal、依赖管理、错过补跑、失败自动重试,写计划任务的思路见用 Go 写 cronjob
journalctl
过滤维度:
console$ journalctl -u myapp # 只看某 unit $ journalctl -u myapp -f # 追加模式,类似 tail -f $ journalctl -e # 跳到末尾 $ journalctl -b # 本次开机以来 $ journalctl -b -1 # 上一次开机 $ journalctl -k # 仅内核消息 $ journalctl --since "2026-09-01" --until "2026-09-12 12:00" $ journalctl -p err # err 及更严重的优先级 $ journalctl -g "timeout" # 按正则过滤消息正文 $ journalctl -n 50 --no-pager # 最近 50 行且不分页输出格式:
-o short-precise微秒时间戳、-o cat仅消息正文、-o json-pretty结构化磁盘治理:
console$ journalctl --disk-usage $ journalctl --vacuum-time=7d $ journalctl --vacuum-size=500M默认日志重启即失,持久化要创建
/var/log/journal目录,长期留存的再配SystemMaxUse=限制体积
相关阅读
- Linux 发行版与包管理器:哪些发行版不用 systemd
- Linux 进程管理命令:服务背后就是普通进程