在基于systemd的Linux系统中,开机启动项不再由/etc/rc.local或init脚本统一管理,而是通过单元文件组织。单元文件定义了服务、挂载点、定时器等资源的行为,其中服务单元直接影响哪些进程会随系统启动。下面围绕查看、控制、自定义和优化四个角度展开。

一、查看启动项:从单元文件到运行状态
systemd把启动项抽象为单元,服务单元通常以.service结尾。默认扫描目录较多,用户自定义单元主要放在/etc/systemd/system/,软件包安装的单元通常位于/usr/lib/systemd/system/,运行时的临时单元在/run/systemd/system/。使用systemctl list-unit-files可以查看所有已安装单元及开机自启状态。
systemctl list-unit-files --type=service | grep enabled
输出中 STATE 列常见 enabled、disabled、static、masked。enabled 表示已建立开机启动软链接,disabled 表示没有开机自启,static 说明该单元不能被独立启用,只能作为其他单元的依赖存在,masked 则被指向/dev/null彻底屏蔽。如果只想查看当前正在运行的服务,使用systemctl list-units。用systemctl status查看服务的完整状态、进程树和最近日志。
systemctl list-units --type=service --state=running systemctl status nginx.service
需要看单元文件真实内容时,systemctl cat比直接去目录翻找更可靠,因为它会展示所有同名的覆盖文件片段。单元文件按依赖关系被加载,通过systemctl list-dependencies可以查看某个target之下会拉起哪些服务,反向查询则定位某个服务由哪个target引入。
systemctl cat sshd.service systemctl list-dependencies multi-user.target --reverse
二、控制开机自启:enable、disable与mask的差异
停止服务并不会取消开机自启,真正决定下次开机是否拉起的是enable/disable产生的符号链接。执行systemctl disable nginx.service会移除/etc/systemd/system/multi-user.target.wants/下的对应链接,但该单元文件本身仍保留在系统中,之后仍可通过其他单元的Requires或Wants依赖被激活。
sudo systemctl disable nginx.service sudo systemctl stop nginx.service
如果希望服务完全不能被启动,包括管理员手动start和依赖拉起,需要使用mask。mask会创建一个指向/dev/null的同名链接,任何启动请求都会直接失败。适合处理那些与桌面环境冲突或存在安全风险的旧服务。解除屏蔽用unmask。需要注意disable和mask不是同级操作,disable只移除自启链接,mask则禁止任何启动路径,二者可以组合使用。
sudo systemctl mask debug-shell.service systemctl is-enabled debug-shell.service
在某些发行版中,服务被设为static时,disable可能不会产生预期效果,因为static原本就没有独立wants链接。此时可以检查对应target下的文件手动删除,或者使用systemctl edit将Unit段中条件设为ConditionPathExists=/nonexistent来阻断。还有一种更稳妥的方式是使用systemctl preset命令恢复发行版默认策略。
三、自定义service单元与条件启动
当现有软件没有提供systemd单元时,可以在/etc/systemd/system/下创建自定义.service文件。文件分为Unit、Service和Install三个段落,Unit段描述元数据与依赖顺序,Service段定义执行命令、进程类型和重启策略,Install段指定安装到哪个target。
[Unit] Description=My App Worker After=network-online.target Wants=network-online.target [Service] Type=simple User=appuser Group=appuser WorkingDirectory=/opt/myapp ExecStart=/opt/myapp/bin/worker --config /etc/myapp/config.toml Restart=on-failure RestartSec=3 NoNewPrivileges=true PrivateTmp=true [Install] WantedBy=multi-user.target
Type=simple适合前台常驻程序,如果程序自身会fork到后台则需要使用Type=forking,一次性脚本则用oneshot。条件启动可以通过ConditionPathExists、ConditionACPower等参数控制服务是否在特定环境中运行。例如只有插电时才启动某个耗电的同步任务,或者目录存在时才触发清理脚本。
[Unit] ConditionACPower=true ConditionDirectoryNotEmpty=/var/cache/cleanup [Service] Type=oneshot ExecStart=/usr/local/bin/cleanup.sh
创建或修改单元文件后,需要执行systemctl daemon-reload让systemd重新扫描目录,再执行enable和start。如果语法有误,daemon-reload会直接报错,也可以通过systemd-analyze verify /etc/systemd/system/myapp.service提前校验。
四、使用systemd-analyze定位启动瓶颈
开机缓慢时,systemd-analyze blame可以按耗时从高到低列出各单元初始化耗时,但要注意并行启动的服务会互相影响,单个数值高不代表就是罪魁祸首。critical-chain则展示阻塞关键链,从systemd初始化到进入目标target之间的依赖路径。
systemd-analyze blame systemd-analyze critical-chain
常见的优化方向包括:将不必要的服务设为disable或mask、把After依赖调整得尽可能宽松、将耗时任务改为定时器延迟执行。还可以用systemd-analyze plot生成SVG图表,直观查看启动过程中各服务的时间线。对于桌面用户,减少蓝牙、打印、远程管理等后台自启服务通常能明显改善开机速度。
systemd-analyze plot > /tmp/boot.svg
需要特别留意的是,不要盲目禁用发行版预设的基础服务,比如dbus、systemd-logind、udev等。这些服务被其他进程深度依赖,禁用后可能导致登录、网络或设备管理异常。更合理的方式是先通过systemctl list-dependencies确认服务影响范围,再决定是否关闭自启。
systemd启动项Linux服务管理系统优化修改时间:2026-10-02 01:52:24