enable 与 disable 是什么
enable 与 disable 管的是开机自启:enable 会在启动目标的 .wants 目录里建立指向单元文件的软链接,让 systemd 在到达该目标时把单元拉起来;disable 则拆除这些链接。它完全不改变单元此刻的运行状态——正在跑的服务 disable 之后继续跑,直到下次重启才不再自启。把这两件事分清,能避免「已经 disable 了为什么还在跑」这类疑问。
基本信息
| 适用平台 | Linux(systemd 发行版) |
|---|---|
| 命令语法 | systemctl enable|disable [--now] [--runtime] 单元... |
| 常用选项 | --now 同时启动或停止、--runtime 只对当前运行期有效(重启后失效)、-f 覆盖已存在的链接、--user 操作用户级单元 |
| 状态取值 | is-enabled 可能返回 enabled、disabled、static、masked、indirect、generated、enabled-runtime |
| 权限要求 | 系统级单元需要 root 或 sudo;用户级单元用 systemctl --user 无需提权 |
典型使用场景
- 部署新服务:确认单元能正常启动后,用 enable --now 一步完成自启与启动
- 下线服务:disable --now 同时取消自启并停止服务
- 核对自启清单:is-enabled 与 list-unit-files 快速筛查哪些服务会随开机启动
- 临时实验:--runtime 只在本次运行期生效,重启自动恢复原状
- 排查启动顺序:list-dependencies 看某个 target 下会拉起哪些单元
- 彻底禁用:对不希望被任何依赖拉起的单元使用 mask
常用示例
常用示例
systemctl enable nginx
systemctl enable --now myapp # 设置自启并立刻启动
systemctl disable firewalld
systemctl disable --now myapp # 取消自启并停止服务
systemctl is-enabled nginx # enabled/disabled/static/masked
systemctl enable --runtime nginx # 只对当前运行期生效
systemctl list-unit-files --state=enabled | head -30
systemctl list-dependencies multi-user.target | head -n 40
systemctl mask telnet.socket; systemctl unmask telnet.socketis-enabled 取值读法
| 取值 | 含义 | 处理方式 |
|---|---|---|
| enabled | 已建立自启链接 | 开机时会被拉起 |
| disabled | 无自启链接,但仍可被依赖拉起 | 需要时手动 start |
| static | 单元没有 [Install] 段,不能被 enable | 通常由其他单元或 socket 激活 |
| masked | 链接到 /dev/null,彻底禁止启动 | 取消需要先 unmask |
| indirect | 由某个别名或依赖间接启用 | 需要连同上游单元一起看 |
| generated | 由生成器动态产生(如 fstab 生成的挂载单元) | 应修改源配置文件而不是单元本身 |
disable 与 mask 的强度不同:disable 只是取消自启,服务仍能在被依赖或手工 start 时运行;mask 把单元链接到 /dev/null,任何路径都无法启动它,连依赖它的单元也会因为依赖无法满足而启动失败。需要「彻底不要再被拉起」时使用 mask。另外,socket 激活型服务要连同对应的 .socket 单元一起处理,只 disable 服务单元时端口仍在监听,随时会把服务重新拉起来。
单元文件位置会影响自启结果:同名单元以 /etc/systemd/system 优先于 /usr/lib/systemd/system。把自定义单元放在 /etc 下并 enable 后,如果后来在别处又放了同名文件,容易出现「自启指向的不是我期望的那份定义」,排查时用 systemctl cat 单元名 确认实际加载的路径。巡检自启清单用 systemctl list-unit-files --state=enabled,再配合 list-dependencies 某个 target 看实际会拉起哪些单元。怀疑某服务被意外拉起时,先查它的上级依赖与对应的 .socket,而不是直接改单元定义。实验阶段使用 enable --runtime 只影响当前运行期,重启后自动恢复,能避免留下需要清理的配置。
不要用直接删除软链接或单元文件的方式代替 disable 与 mask:systemd 在内存中保留单元状态,手工操作容易留下不一致的引用;卸载软件后再手工删文件,还可能让残留的 .wants 链接指向不存在的单元,在启动时产生告警。
三种禁止方式的区别
| 方式 | 效果 | 适用 |
|---|---|---|
| 停止 | 立即停止,开机仍会启动 | 临时停服务 |
| 禁用 | 开机不再自启,当前继续运行 | 日常下线 |
| 屏蔽 | 彻底禁止启动,依赖它的单元会失败 | 确认不再使用 |
| 屏蔽并停止 | 屏蔽同时立即停止 | 彻底禁用 |
启用状态与运行状态是两件事:前者决定开机与依赖触发时是否拉起,后者是当前这一刻是否在跑。变更流程里两者都要验证,脚本判活也不能只看其中一项,否则会出现「以为停掉了其实还在跑」或反之的误判。