资讯详情

重启之后服务就没影了:开机自启写在哪、为什么没生效

📅 2026/10/13 8:52:34 | 华诺云谱 👁 阅读
重启之后服务就没影了:开机自启写在哪、为什么没生效
授权与合规声明本文全部操作对象均为自建隔离靶场本机容器或隔离虚拟机涉及安全测试的环节必须以取得合法授权为前提。未经授权的渗透测试违反《中华人民共和国网络安全法》与《刑法》相关条款须承担相应法律责任。本文只讲环境配置、版本对照与靶场隔离不含任何攻击步骤、利用载荷与绕过手法请勿将文中环境指向任何非自有系统。一、重启之后服务就没影了1.1 现象同一个命令重启前后两种结果在隔离虚拟机里把靶场服务拉起来启动命令一敲网页能打开、端口能连上一切正常。可机器一重启这个服务就不见了——不是启动失败是像从来没存在过一样安静你再去查它压根没跑。这种情况最容易被误判成服务本身有问题。但证据不支持这个判断同一份配置、同一个启动命令在重启前是好的。真正变了的只是这一次是谁把它拉起来的。1.2 本文只讲主机这一层先把范围划清。如果你的服务是跑在容器里的那由容器那一层自己的机制负责本文不做任何展开。本文讲的是服务直接跑在主机上这一层Linux 上归 systemd 管macOS 上归 launchd 管。另外本文讲的是开机之后就一直在那儿跑着的常驻服务不是到点跑一次的定时任务——后者是另一套机制不属于本文范围。1.3 支点这是两本独立的账本文的全部论证都压在一句话上「现在启动了」和「开机时会被启动」是两个独立的账。一本账记的是这一刻服务在不在跑另一本账记的是开机的时候有没有谁被安排来把它拉起来。这两本账互相不保证——现在跑着不代表开机有人管开机写好了不代表此刻它在跑。绝大多数的重启就没了不是服务坏了而是第二本账上根本没写你这条服务。你看到的现象它属于哪本账它回答的问题网页能打开、端口能连当前状态账这一刻服务在不在跑重启后服务消失开机状态账开机时有没有谁拉它两个现象都碰上了两本都要查先分清是哪一本没写本章可以带走的一句把现在在跑和开机会被跑当成两本独立的账是本文所有排查动作的前提重启就没了首先是第二本账没写而不是服务坏了。二、先把两本账拆开看2.1status里的 active 到底说了什么systemctl的Active:行手册给的口径是逐字的这一行显示的是 active state取值通常是active或inactive而active 的含义取决于单元类型可能是 started、bound、plugged in 等等原文 “could mean started, bound, plugged in, etc depending on the unit type”除这两者外还有activating、deactivating两个过渡态以及failed这个特殊态SD07。这句话的分量在于active是一个含义随单元类型变化的通用描述它并不是这个程序正在健康地跑着的同义词。2.2 active 的判定颗粒度比你想的粗再补一条更硬的systemd.service(5)说明当指定了ExecStart、而既没写Type也没写BusName时Type默认取simpleSD06。而simple的语义逐字是服务管理器会在主服务进程被 fork 出去之后立刻认为该单元已启动原文 “the service manager will consider the unit started immediately after the main service process has been forked off”——手册还特意注明这是在新进程调用execve()之前。合起来读active只说明管理器把进程 fork 出去了连程序真的成功跑起来没有都未必覆盖。拿这一行去证明开机一定会起来从一开始就不成立。2.3 启用态由另一组命令回答第二本账不属于Active:行。手册的另一处口径是启用状态由is-enabled报告并经list-unit-files与启用态一并列出SD07。因此这两个问题虽然长得像问法却完全不同你想问的问题该看哪里它回答的是现在在跑吗status的Active:行这一刻的状态开机时会起来吗is-enabled、list-unit-files启用状态⚠️代码待验证# 两本账分两次问照 systemctl(1) 手册口径记本文运行环境是 macOS未实测 systemctl# 当前状态账看 status 输出的 Active: 行# 取值通常 active / inactive另有过渡态 activating / deactivating以及特殊态 failed# 开机状态账is-enabled 报告启用状态list-unit-files 会把启用态一并列出本章可以带走的一句Active:行讲的是这一刻且它的含义随单元类型而变、判定颗粒度只到进程被 fork 出去开机状态要问的是is-enabled与list-unit-files——两本账要用两组不同的命令分别去问。三、单元文件该放在哪个目录3.1 手册给的是一组路径不是一个目录systemd 的搜索路径在编译期就已定下。systemd.unit(5)的 UNIT FILE LOAD PATH 一节写明了一条覆盖规则排在列表中靠前目录里的单元文件会覆盖列表靠后目录里同名的文件原文 “Unit files found in directories listed earlier override files with the same name in directories lower in the list”。记住是一组、且有序才能理解后面的分界线。3.2 四个位置两种来源systemd.unit(5)在 system 模式的加载路径表里给出了四处位置与各自的逐字描述SD01搜索路径手册逐字描述谁放进去的/etc/systemd/systemSystem units created by the administrator管理员自己加的/run/systemd/systemRuntime units运行时产生的/usr/local/lib/systemd/systemSystem units installed by the administrator管理员自己加的/usr/lib/systemd/systemSystem units installed by the distribution package manager发行版包管理器装的3.3 这条分界线决定了你的改动该落在哪把这四处按谁放的归类就只有两类而且它们是不同位置发行版包管理器装的→ 落在/usr/lib/systemd/system管理员自己加的→ 落在/etc/systemd/system或/usr/local/lib/systemd/system。这条分界线直接决定动作方式你自己新写的单元文件应当放进管理员那两处要改包管理器装的某一份不要去动/usr/lib/systemd/system里的原件——同名文件按优先级规则放到靠前的位置才是覆盖的正规落点原件留着给升级流程走而只把文件写进某个目录只解决了能不能被找到它和开机时会不会启动仍然是两件事这要交给下一章。⚠️代码待验证# 观察某个单元文件到底来自哪一处只读本文环境为 macOS未实测# 1) 是包管理器装的还是管理员加的看它落在下面哪一处# /usr/lib/systemd/system 发行版包管理器装的# /etc/systemd/system 管理员自己加的# /usr/local/lib/systemd/system 管理员自己加的# 2) 四处有序排在前面的目录里同名文件覆盖排在后面的# 3) 只把文件放进目录 ≠ 开机自启开机挂钩在 [Install] 段里写见第四章本章可以带走的一句systemd 从一个有序的目录列表里找单元文件靠前的覆盖靠后的发行版包管理器装的在/usr/lib/systemd/system管理员自己加的在/etc/systemd/system与/usr/local/lib/systemd/system——这是两处不同位置决定你的改动该落在哪一处。四、[Install]段为什么看起来没用4.1 运行的时候systemd 根本不读它[Install]段是最容易被误解的一段因为它的内容在随手测试时看不出任何效果。手册对此有一句毫不含糊的话systemd 在正常运行normal operation时完全不看[Install]段原文 “systemd does not look at the [Install] section at all during normal operation”因此写在那里的配置在运行时不会作用到该单元上它只通过启用enable时创建的软链起作用SD02。这句解释了那种很典型的手感你在[Install]里写了东西、运行起来毫无变化于是以为这段是废的。它不是废的只是服务的对象不是运行时而是安装/启用那一步。4.2WantedBy不能当普通设置用同一份手册在依赖关系表的注里把这条讲得更死WantedBy、RequiredBy、UpheldBy是在[Install]段里用来在.wants/、.requires/、.upholds/目录创建软链的它们不能直接被当作单元配置设置来使用原文 “They cannot be used directly as a unit configuration setting”SD03。配套的对照表Table 4还说明了每一对正向 / 反向属性分别住在哪一段正向属性写在哪一段反向属性写在哪一段Wants[Unit]段WantedBy[Install]段Requires[Unit]段RequiredBy[Install]段Upholds[Unit]段UpheldBy[Install]段注意左右两列的分工Wants和WantedBy是同一件事的两面但它们不住在同一段。把WantedBy挪进[Unit]段就等于把它当一个普通设置用——按上一小节的口径这条路本来就不通。⚠️代码待验证# 关于 [Install] 段只记三句照 systemd.unit(5) 手册口径记本文环境为 macOS未实测# 1) 正常运行时 systemd 完全不看 [Install] 段它只在 enable 时通过软链起作用# 2) WantedBy / RequiredBy / UpheldBy 只能写在 [Install] 段里# 不能当作普通单元设置直接使用# 3) 同一对属性的分工[Unit] 段放 Wants[Install] 段放 WantedBy4.3 开机时到底从哪儿接上那开机时是谁在拉这些单元systemd.special(7)对default.target的口径是它是开机时 systemd 启动的默认单元通常应当被别名软链到multi-user.target或graphical.targetSD05。同一页还给了一层兜底若default.target不在盘上、且内核命令行也没指定则使用编译期默认值若默认单元及其回退项都起不来systemd 会启动rescue.target。这些都是规范spec层面的口径。本文不写任何发行版的打包默认值——某个发行版默认把哪个 target 设成 default是打包问题与上面的规范不是一回事本批未核到。有了这条WantedBy的作用面就清楚了它不是设置而是给enable的一句指令——把我这条单元挂到某个 target 底下。挂上去之后开机流程走到那个 target才会顺带拉起你。本章可以带走的一句[Install]段在运行时完全不生效它只在enable时通过软链起作用WantedBy这类键不能当普通设置用它真正的含义是让enable把我挂到某个 target 底下——这才是开机自启的挂钩所在。五、enable到底做了什么5.1 一句话按[Install]建一组软链systemctl(1)对enable的逐字说明是启用一个或多个单元或单元实例这会按单元文件里[Install]段所编码的内容创建一组软链原文 “This will create a set of symlinks, as encoded in the [Install] sections of the indicated unit files”SD04。同一段里还有一句极容易被忽略的话它并不会同时启动被启用的单元如果要顺带启动得配合--now或者稍后再单独发一次启动动作。5.2 所以enable 了怎么还没跑是正常的把上面两句并起来读答案就出来了enable管的是开机状态账——建软链、把单元纳入开机流程启动动作管的是当前状态账——现在把它拉起来。两个动作、两本账谁都不替谁干活。反过来看那个经典困惑“我已经启用过了为什么这一刻还是没跑”——因为启用本来就不负责跑。这和他纠结的重启后没起来恰好是两本不同账上的两个问题。5.3 只读地检查这条单元到底能不能被启用is-enabled的输出就是启用状态本身。手册给了它一张取值表Table 3挑三行最有用的is-enabled输出手册逐字含义节选enabled已通过.wants/、.requires/或Alias软链启用disabled单元文件未被启用但含有一个带安装说明的[Install]段static单元文件未被启用且在[Install]段里没有任何可用于启用的内容最后一行是关键没有[Install]段或那段里没有可供建软链的内容的单元会显示成static——它压根没有被启用这一回事。所以如果你对着一条static反复启用却毫无变化方向就错了不是命令没生效而是这条单元的设计里就没有开机挂钩。此时该做的不是继续启用而是回到第四章给它补上正确的[Install]段。⚠️代码待验证# 三个只读动作照 systemctl(1) 手册口径记本文环境为 macOS未实测# 1) 看启用状态 is-enabled 单元 # enabled / disabled / static / masked / ...# 2) 看全部单元及其启用态list-unit-files # 启用态由 is-enabled 报告并一并列出# 3) 看单元文件内容 cat 单元 # 只读用来看 [Install] 段写了什么# 注意不启动任何服务不加 --now本章只需要读不需要改。本章可以带走的一句enable的动作就是按[Install]段建一组软链而且它不会顺带启动服务检查启用状态用is-enabled、list-unit-files、cat三个只读动作——一条显示static的单元本来就没有被启用这回事。完整版开机自启排障清单这一章的三个只读动作 is-enabled三种关键取值配合第三章的搜索路径表与第四章的[Install]口径一起收进资料包扫码即可获取六、macOS 一侧launchd 的三个键换到 macOS机制换了一套但要分清的东西没变身份、加载时跑一次、以及保活是三件不同的事。6.1Label身份而且是必填launchd.plist手册对Label的口径很短这是一个必需键用来在 launchd 面前唯一标识该任务原文 “This required key uniquely identifies the job to launchd.”。它还给了一条命名约定launchd 的 plist 文件按预期约定应当命名为Label.plist原文 “it is the expected convention for launchd property list files to be named.plist”并举例若任务 label 是com.apple.sshd那么 plist 文件就该叫com.apple.sshd.plist。这里必须把一件事说清楚因为它关系到写得对不对plist 需要放到 launchd 会读取的目录里。至于具体是哪个目录本文未逐字核到所以本篇不列出任何路径——凡是凭记忆写路径的版本都不要照抄。6.2RunAtLoad加载那一刻跑一次RunAtLoad的口径是它控制任务在被加载的那一刻是否启动一次默认值是 false手册还补了一句劝告——这个键最好避免使用因为猜测式的启动会对系统开机与用户登录场景产生不利影响原文 “as speculative job launches have an adverse effect on system-boot and user-login scenarios”。6.3KeepAlive保活而且隐含RunAtLoadKeepAlive的口径是它控制任务是被持续保活还是由需求与条件来决定何时被调用默认 false因此只有需求才会启动该任务也可以给一个条件字典让 launchd 按条件选择性地保活若并列多个键launchd 会对它们取或。手册最后补了关键一句使用这个键会隐含RunAtLoad使 launchd 猜测式地启动该任务原文 “The use of this key implicitly implies RunAtLoad, causing launchd to speculatively launch the job”。两个条件子键值得单列子键手册口径SuccessfulExit为 true 时只要程序以退出状态 0 退出任务就会被重启为 false 时按相反条件重启。这个键隐含RunAtLoad为 true因为任务至少要跑一次才谈得上退出状态PathState字典里每个键是一个文件系统路径值为 true 时只要该路径存在任务就被保活为 false 时按相反条件保活。手册的 IMPORTANT 逐字写道文件系统监控机制本质上是有竞态、且会漏的原文 “Filesystem monitoring mechanisms are inherently race-prone and lossy”并建议改用基于 IPC 的按需方案PathState这句劝告很值钱盯着一个文件在不在这种保活方式手册自己承认它会漏。所以碰到用PathState保活偶尔还是掉了这不是你配错了而是这条机制自带的性质。6.4 和 systemd 对照着记两套机制的名词不同但要表达的意图可以一一对上你想表达的意图systemd 的落点launchd 的落点给这条服务一个身份单元文件名Label必需键加载/安装时先跑一次启用本身不启动要另发启动动作或加--nowRunAtLoad默认 false掉了要拉起来由单元类型与重启相关设置决定本文不展开KeepAlive隐含RunAtLoad⚠️代码待验证# launchd 这一侧只记三个键的分工照 man 5 launchd.plist 口径记本批未实测 launchctl# Label 必需键唯一标识任务约定 plist 文件名为 Label.plist# RunAtLoad 加载那一刻跑一次默认 false# KeepAlive 保活默认 false且使用它会隐含 RunAtLoad# ├ SuccessfulExit 按退出状态决定是否重启隐含 RunAtLoad# └ PathState 按某路径是否存在保活手册自陈本质上有竞态、且会漏# plist 必须放到 launchd 会读取的目录具体目录本文未逐字核到故不列路径本章可以带走的一句macOS 侧把三件事分给了三个键——Label是必需的身份、RunAtLoad是加载时跑一次、KeepAlive是保活且会隐含RunAtLoad而 plist 必须放进 launchd 会读取的目录具体目录本文未逐字核到。七、把两本账一次问清六项自查7.1 顺序本身就是方法前面六章的事实可以收成一条固定顺序。顺序之所以重要是因为每一步都要在前一步成立之后才有意义先确定平台是哪一套才谈得上查什么命令先把当前和开机两本账分开才不会拿Active:行去证明开机行为先看文件落在哪一处才谈得上我改的是不是被读到的那一份再确认开机挂钩写没写最后才轮到启用/加载到底做没做。⚠️代码待验证# 六项自查对应的只读动作照本文所引手册口径记本文环境为 macOS全部未实测# 第 2 项 两个问题分开问现在在跑吗 - status 的 Active: 行开机会起来吗 - is-enabled# 第 3 项 文件落在哪一处在下面四处里找这条单元/这份 plist 的位置# /usr/lib/systemd/system 发行版包管理器装的# /etc/systemd/system 管理员自己加的# /usr/local/lib/systemd/system 管理员自己加的# macOS 侧plist 需放进 launchd 会读取的目录具体目录本文未逐字核到# 第 4 项 开机挂钩写没写看单元文件 [Install] 段里的 WantedBy# 第 5 项 启用/加载做过没有is-enabled 的输出是 enabled / disabled / static / ...# 以上全部只读不含任何启动、启用或修改动作。7.2 六项自查表#自查项看什么依据1平台是哪一套Linux 看 systemdmacOS 看 launchd第 1 章2两个问题是哪一个现在在跑吗与开机会起来吗分开问第 2 章3单元文件 / plist 落在哪管理员位置还是包管理器位置第 3 章4开机挂钩写在哪一段[Install]段里的WantedBy第 4 章5启用 / 加载做过没有is-enabled的输出launchd 侧的加载动作第 5、6 章6以上都成立仍起不来回到服务自己的输出日志只是这一条动作本文不展开观察顺序——第 6 项要克制只有前五项都成立问题才轮到服务自己。而去看服务自己的输出是一整套观察方法属于另一个题目本文明说不展开——放进这张表只是提醒你别在第三步就跳到第六步。7.3 回到标题那个问题回到最开始的现象重启之后服务就没影了。到这里可以按事实回答这不是服务坏了而是两本账中开机状态那一本没有写你。具体说Active:行只讲这一刻它的含义随单元类型而变判定颗粒度只到主进程被 fork 出去开机时的落点由[Install]段承担而[Install]段运行时完全不生效WantedBy也不能当普通设置用真正把它变成开机行为的是enable——它按[Install]建一组软链并且不会顺带启动服务macOS 侧同理Label、RunAtLoad、KeepAlive各管一段plist 还得放进 launchd 会读取的目录。还有一条边界要留在这里本文只讲**写在哪儿与谁去启动这套机制不写任何发行版的打包默认值不列 launchd 的目录路径也不给任何可复制的服务配置片段**。你手上的服务要怎么起、以什么身份起、坏了要不要自动拉起是配置决策不是本文的结论。本章可以带走的一句排查顺序是先分清两本账、再看文件落在哪、再确认[Install]段里的开机挂钩、最后才问启用做过没有前五项都成立仍起不来才轮到去看服务自己的输出——那已经是另一篇文章的题目。完整版开机自启排障清单这一章的六项自查表 固定排查顺序连同第六章 systemd 与 launchd 的对照记法汇总进资料包扫码即可获取附表 A本文引用事实与官方出处对照表#事实一句出处来源 具体位置核验日期本文位置SD01system 模式加载路径中/etc/systemd/system是管理员创建的 system 单元、/usr/local/lib/systemd/system是管理员安装的 system 单元、/usr/lib/systemd/system是发行版包管理器安装的 system 单元、/run/systemd/system是运行时单元且排在前面的目录会覆盖排在后面的同名文件systemd.unit(5)UNIT FILE LOAD PATHsystem 模式加载路径表2026-10-13第 3 章SD02逐字“systemd does not look at the [Install] section at all during normal operation”故该段配置只在enable建立的软链上起作用systemd.unit(5)[Install] Section Options 前言2026-10-13第 4 章SD03逐字WantedBy、RequiredBy、UpheldBy用于在[Install]段里创建.wants/.requires/.upholds/软链不能直接当作单元配置设置使用systemd.unit(5)Table 4 表注2026-10-13第 4 章SD04逐字enable“will create a set of symlinks, as encoded in the [Install] sections”并明确它不会顺带启动被启用的单元systemctl(1)enable2026-10-13第 5 章SD05default.target是开机时 systemd 启动的默认单元通常应被软链到multi-user.target或graphical.target另有编译期默认值与rescue.target兜底systemd.special(7)default.target2026-10-13第 4 章SD06Type在指定了ExecStart而无Type、无BusName时默认simple其语义是主服务进程被 fork 之后、execve()之前即视为已启动systemd.service(5)Type2026-10-13第 2 章SD07Active:行显示 active state取值通常activeinactiveactive 的含义取决于单元类型可能为 startedboundplugged in 等另有activatingdeactivatingfailed启用状态则由is-enabled报告并经list-unit-files一并列出systemctl(1)Active:口径与is-enabledlist-unit-files2026-10-13第 2 章SD07-b承 SD07 同一出处is-enabled取值表中enabled已通过.wants/.requires/Alias软链启用disabled未启用但含带安装说明的[Install]段static未启用且[Install]段中无任何可供启用的内容systemctl(1)Table 3is-enabledoutput2026-10-13第 5 章LD01逐字Label“This required key uniquely identifies the job to launchd.”并按约定 plist 文件应命名为Label.plist例com.apple.sshd→com.apple.sshd.plist本机man 5 launchd.plist2026-10-13第 6 章LD02RunAtLoad控制任务在被加载时是否启动一次默认 false手册建议避免因猜测式启动不利于开机与登录场景本机man 5 launchd.plist2026-10-13第 6 章LD03KeepAlive控制保活还是按需调用默认 false使用它会隐含RunAtLoad使 launchd 猜测式启动该任务本机man 5 launchd.plist2026-10-13第 6 章LD04SuccessfulExit按退出状态决定是否重启并隐含RunAtLoad为 true任务至少要跑一次才谈得上退出状态本机man 5 launchd.plist2026-10-13第 6 章LD05PathState按某路径是否存在保活手册 IMPORTANT 逐字“Filesystem monitoring mechanisms are inherently race-prone and lossy.”本机man 5 launchd.plist2026-10-13第 6 章边界-1本文涉及的全部命令systemctl、单元文件、launchctl本批均未在本机实测本机为 macOS无 systemd因此正文相应代码块一律保留⚠️ 代码待验证本批执行记录未实测2026-10-13全文边界-2launchd 的 plist 目录约定本批未逐字核到正文只写plist 需要放到 launchd 会读取的目录具体目录本文未逐字核到不列任何路径本批核验边界未核到2026-10-13第 6 章边界-3本文不写任何发行版的打包默认值某发行版默认把哪个 target 设为 default属打包问题本批未核本批核验边界未核2026-10-13第 4 章附表 B术语速查表术语一句话解释易混点systemdLinux 上的服务与系统管理器本文的主机层机制与容器那一层的机制不是一回事单元文件描述一个单元服务、target 等的配置文件“文件放对了不等于开机自启”[Unit]段单元文件里写依赖与通用行为的段Wants在这里[Install]段只在enable时被读取的段运行时不生效WantedBy在这里不是普通设置enable按[Install]建一组软链的启用动作它不会顺带启动服务is-enabled报告单元启用状态的只读命令它答的是开机会不会起来不是现在在不在跑staticis-enabled的一种取值[Install]里没有可供启用的内容不是命令没生效是压根没有开机挂钩default.target开机时 systemd 启动的默认单元规范口径与某发行版默认值不是一回事launchdmacOS 上的服务管理器与 systemd 名词不同但身份加载一次保活三件事要分开Labellaunchd plist 的必需键唯一标识任务它是身份不负责启动时机RunAtLoad加载那一刻跑一次默认 false与KeepAlive是两件事KeepAlive保活默认 false且隐含RunAtLoad别以为它只管挂了再拉写在最后这篇用到的资料写这篇文章时我一直在想那个反差——一个在重启前明明好好的服务重启后就彻底没了影而真正的答案不在服务本身而在现在启动了和开机时会被启动这两本账压根是分开记的文件放哪儿、[Install]段是给谁看的、enable到底做了什么少一环就会静静变成什么都没发生。顺手也整理了几份配套的东西靶场环境对照表DVWA、upload-labs 在 Windows / macOS / Linux 三平台的可行性与推荐路径Web 安全学习路线图从基础打牢到安全管理四个阶段各学什么常用靶场清单每个靶场练什么、适合哪个阶段资料是我自己整理的放在下面这个码上扫码即可获取添加时备注「靶场」优先通过。拿到之后建议先看环境对照表那一份把本文的六项自查对照着过一遍——下次再遇到重启之后服务就没影了按顺序问下去就知道该看哪一本账。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑