news 2026/2/3 21:49:59

为什么要用S开头命名?测试开机启动脚本告诉你答案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
为什么要用S开头命名?测试开机启动脚本告诉你答案

为什么要用S开头命名?测试开机启动脚本告诉你答案

你有没有遇到过这样的情况:写好了一个服务脚本,放进/etc/init.d/目录,也加了执行权限,还手动运行测试没问题,可一重启系统,脚本却压根没跑起来?
或者更奇怪的是——它倒是运行了,但比数据库、网络服务还早启动,结果因为依赖没就绪,直接报错退出?

这个问题背后,藏着 Linux 系统启动机制里一个看似简单、实则关键的约定:为什么开机自启脚本的软链接必须以S开头?

今天我们就用「测试开机启动脚本」这个轻量级镜像,从零开始走一遍真实流程,不讲抽象概念,只看命令、目录、文件名和实际效果。你会发现,那个小小的S,不是随意写的字母,而是系统启动顺序的“交通指挥员”。


1. 先搞清楚:系统启动时到底在做什么?

Linux 启动不是一股脑儿把所有脚本全拉起来,而是分阶段、按顺序、有依赖地加载服务。这个机制叫SysV init(虽然现代发行版多用 systemd,但/etc/init.d/+rc*.d这套逻辑仍在兼容层广泛存在,尤其在 CentOS 7 之前、Ubuntu 16.04 及更老版本中仍是默认行为)。

核心逻辑就两点:

  • 每个运行级别(runlevel)对应一个启动目录,比如rc3.d(多用户无图形)、rc5.d(带图形界面);
  • 这些目录里不放脚本本身,只放指向/etc/init.d/中脚本的软链接
  • 而这些软链接的名字,决定了它们是“启动”还是“停止”,以及“什么时候启动”。

所以,S不是“Start”的缩写那么简单——它是整个启动序列的开关标识符。


2. 动手验证:看看你的系统在哪个运行级别

我们先确认当前系统的运行级别,这是后续操作的前提。

runlevel

输出类似:

N 5

说明:上次启动后进入的是运行级别 5(即带桌面环境的完整多用户模式)。
那系统启动时,就会自动去读取/etc/rc5.d/目录下的所有软链接,并按名字顺序执行。

小知识:N表示“None”,代表系统刚启动,还没切换过运行级别;第二个数字5才是当前级别。

你也可以用who -r命令再次验证:

who -r

输出中会明确显示run-level 5


3. 揭秘/etc/rc5.d/:一个全是SK的目录

现在,我们进到这个关键目录看看里面到底有什么:

ls -l /etc/rc5.d/

你会看到一堆类似这样的文件名:

S01rsyslog S10network S20ssh S25mysql S99myapp K01apache2 K10docker

注意观察命名规律:

  • 所有以S开头的,都是启动脚本(Start);
  • 所有以K开头的,都是关闭脚本(Kill),用于系统关机或切换运行级别时停止服务;
  • 后面的两位数字(如012099)表示执行顺序:数字越小越早执行,越大越晚。

举个真实例子:S10networkS25mysql之前运行,确保网络就绪后,MySQL 才能连接外部配置或远程存储;而S99myapp排在最后,说明它依赖前面几乎所有基础服务。

这正是S的真正价值:它不只是“要启动”,更是“在什么时机启动”。


4. 实操:创建你的第一个S开头软链接

假设你已经写好一个测试脚本/etc/init.d/mytest.sh,内容如下(仅作演示,无需复杂逻辑):

#!/bin/bash # /etc/init.d/mytest.sh case "$1" in start) echo "mytest.sh started at $(date)" >> /var/log/mytest.log ;; stop) echo "mytest.sh stopped at $(date)" >> /var/log/mytest.log ;; *) echo "Usage: $0 {start|stop}" exit 1 ;; esac exit 0

给它加上执行权限:

chmod +x /etc/init.d/mytest.sh

现在,我们为它创建一个软链接,放在/etc/rc5.d/下,并命名为S99mytest

ln -s /etc/init.d/mytest.sh /etc/rc5.d/S99mytest

注意:这里必须是S99mytest,不能写成myteststart-mytest99mytest—— 缺少S,系统启动时根本不会识别它为启动项。

再检查一下是否成功:

ls -l /etc/rc5.d/S99mytest

输出应类似:

lrwxrwxrwx 1 root root 22 Apr 5 10:20 /etc/rc5.d/S99mytest -> /etc/init.d/mytest.sh

成功!这个链接已就位,只等下次启动。


5. 为什么不能用S00S99随便选?顺序真的重要吗?

答案是:极其重要。我们来用一个对比实验说明。

场景模拟:两个脚本,不同启动序号

  • S10db.sh:模拟数据库服务,启动耗时约 3 秒,启动后监听3306端口;
  • S20app.sh:模拟应用服务,启动时尝试连接localhost:3306

如果把应用脚本命名为S05app.sh(比数据库还早),会发生什么?

[启动日志片段] Apr 05 10:30:01 S05app.sh: connecting to localhost:3306... Apr 05 10:30:01 S05app.sh: connection refused → exit with error Apr 05 10:30:04 S10db.sh: MySQL started, listening on 3306

应用失败了,不是代码问题,而是时机错了

而如果你把它改成S20app.sh,日志就会是:

Apr 05 10:30:01 S10db.sh: MySQL started, listening on 3306 Apr 05 10:30:04 S20app.sh: connected to database → app ready

所以,S后面的数字不是编号游戏,而是服务依赖关系的显式表达
这也是为什么文档里特别提醒:“如果进程需要访问数据库或者有其他依赖项,最好把启动序号调大”。


6. 验证效果:重启不是唯一方式,还有更安全的测试法

当然,你可以直接reboot,但频繁重启既慢又影响工作。其实有更高效的方式验证:

方法一:手动触发启动(推荐)

sudo /etc/init.d/mytest.sh start

然后检查日志:

tail -n 1 /var/log/mytest.log # 输出应为:mytest.sh started at ...

方法二:模拟 rc5.d 启动流程

# 进入 rc5.d 目录,只执行所有 S 开头的脚本(跳过 K) cd /etc/rc5.d/ for i in S*; do [ -x "$i" ] && sudo ./"$i" start; done

这个命令会按字母顺序(也就是数字顺序)依次执行所有Sxx*脚本的start参数,效果和开机时完全一致。

提示:执行前确保脚本里case "$1"分支正确处理了start,且没有硬编码路径错误。


7. 常见误区与排错指南

很多同学卡在这一步,不是不会操作,而是被几个“看起来合理、实则致命”的错误绊住。我们一一拆解:

❌ 误区 1:脚本放在/etc/init.d/就自动启动了

→ 错。/etc/init.d/只是“脚本仓库”,系统启动时只扫描rc*.d/下的软链接,不读取init.d/里的文件。

❌ 误区 2:软链接名写成S99-mytestS99_mytest

→ 错。SysV init 严格匹配SXXname格式(XX是纯数字,name是任意字符,中间不能有短横线、下划线或空格)。否则会被忽略。

❌ 误区 3:忘记给脚本加#!/bin/bash或执行权限

→ 错。即使软链接存在,若原脚本不可执行,启动时会报Permission denied或静默失败。

❌ 误区 4:在 Ubuntu 20.04+ 或 CentOS 8+ 上强行套用这套逻辑

→ 需谨慎。这些系统默认使用systemdrc*.d仅为兼容保留。若需长期使用,建议改写为.service文件。但本镜像定位明确:专为 SysV init 环境设计,适用于 CentOS 6/7、Ubuntu 14.04/16.04 等经典场景

快速排错三步法:

  1. ls -l /etc/rc5.d/S*mytest*→ 确认软链接存在且指向正确;
  2. sudo /etc/init.d/mytest.sh start→ 确认脚本本身可手动运行;
  3. sudo systemctl is-active mytest(如支持)或查/var/log/syslog→ 看启动时是否有报错。

8. 总结:那个S,到底在说什么?

回看标题——“为什么要用 S 开头命名?”
现在答案很清晰了:

  • SStart 的强制标识符,没有它,系统根本不认为这是一个启动项;
  • S后的数字是启动优先级的声明,不是编号,而是对依赖关系的承诺;
  • 整个rc5.d/目录是一张启动时序图,每个Sxx链接都是图上的一个节点;
  • 你写的每一个S99xxx,都在向系统说:“请在我依赖的所有服务之后,再启动我。”

这不是古董机制,而是稳定、透明、可审计的启动哲学。哪怕今天你用的是 Docker 或 Kubernetes,理解这套逻辑,依然能帮你快速诊断容器内 init 进程行为、调试嵌入式设备启动脚本,甚至读懂老系统的运维手册。

所以,下次再看到S20nginxS99custom-monitor,别只把它当个文件名——那是 Linux 启动交响乐中,属于它的节拍器。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/3 5:13:11

Glyph镜像快速上手:三步完成网页推理设置

Glyph镜像快速上手:三步完成网页推理设置 1. 为什么你需要Glyph——不是又一个大模型,而是“看得更远”的新方式 你有没有遇到过这样的问题: 想让大模型读一份50页的PDF合同,它却卡在“上下文太长”; 上传一份带表格…

作者头像 李华
网站建设 2026/2/3 3:18:39

从半加器到全加器:FPGA实现完整示例

以下是对您提供的博文《从半加器到全加器:FPGA实现完整技术分析》进行的 深度润色与专业重构版本 。本次优化严格遵循您的全部要求: ✅ 彻底去除AI痕迹 :摒弃模板化表达、空洞总结与机械过渡,代之以工程师真实口吻、实战语境…

作者头像 李华
网站建设 2026/2/3 4:18:00

用科哥镜像做的批量录音转写项目,效果远超预期

用科哥镜像做的批量录音转写项目,效果远超预期 最近接手了一个内部知识沉淀项目:把过去半年的200场客户技术交流会录音全部转成文字稿。这些录音格式不一、时长各异、背景噪音明显,传统外包转写成本高、交付慢、专业术语识别差。试过几个在线…

作者头像 李华
网站建设 2026/2/3 10:15:55

YOLOE开放词汇检测,再也不怕新类别了

YOLOE开放词汇检测,再也不怕新类别了 你有没有遇到过这样的尴尬:模型在训练时见过“猫”“狗”“汽车”,上线后用户却上传了一张“水豚”照片——系统直接返回“未识别”。传统目标检测就像一位只背过教材的学生,面对考卷上没出现…

作者头像 李华
网站建设 2026/2/3 17:30:40

5分钟启动Qwen2.5-7B微调环境,RTX4090D实测体验分享

5分钟启动Qwen2.5-7B微调环境,RTX4090D实测体验分享 你是否也经历过这样的困扰:想快速验证一个大模型微调想法,却卡在环境配置上——装依赖、调版本、改路径、查显存……一上午过去,连第一行训练日志都没看到?这次&am…

作者头像 李华
网站建设 2026/2/3 17:20:49

Qwen3-0.6B汽车电子实战,一汽集团已装机10万+

Qwen3-0.6B汽车电子实战,一汽集团已装机10万 你有没有想过,一辆车的智能语音助手,不需要联网、不依赖云端服务器,就能在毫秒级响应你的指令,还能理解“把空调调到24度,顺便查下附近充电桩”这种复合语义&a…

作者头像 李华