news 2026/2/13 12:11:29

手把手教你创建开机启动项,只需一个测试脚本

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手教你创建开机启动项,只需一个测试脚本

手把手教你创建开机启动项,只需一个测试脚本

你有没有遇到过这样的情况:写好了一个监控脚本、日志清理工具,或者一个简单的服务程序,每次重启服务器后都要手动运行一次?既麻烦又容易遗漏。其实,Linux系统早就为你准备好了标准机制——开机自启动脚本。它不依赖任何第三方工具,原生支持,稳定可靠,而且只需要几条命令就能搞定。

本文不是讲systemd的复杂单元文件,也不是堆砌一堆配置模板。我们聚焦最轻量、最通用、最易验证的方式:基于传统SysV init风格的开机启动项。无论你用的是CentOS 7(兼容模式)、Ubuntu 18.04或更早版本,甚至某些嵌入式Linux发行版,这套方法都完全适用。我们将从零开始,用一个真实可运行的测试脚本,带你走完“编写→注册→验证”的完整闭环。整个过程不需要安装额外软件,不修改核心配置,所有操作都在终端里敲几行命令,5分钟内就能看到效果。

最重要的是,这个方法足够“傻瓜”——即使你刚接触Linux一个月,只要能复制粘贴、看懂提示信息,就能成功。文中的每一步都配有清晰说明和典型输出示例,避免你卡在某个报错上反复查资料。现在,让我们开始。

1. 编写并部署测试脚本

我们要做的第一件事,是准备一个真正能被系统识别和执行的脚本。它不能只是简单打印一行字,而要具备标准启动脚本的基本结构:支持startstopstatus等子命令,并能正确返回退出码。这样系统在启动、关机或手动管理时才能准确判断它的状态。

下面是一个精简但完整的测试脚本,功能明确:启动时在/tmp下创建一个带时间戳的标记文件,停止时删除它,查询状态则检查该文件是否存在。它足够简单,便于你快速理解逻辑;又足够规范,能通过系统启动框架的校验。

#!/bin/bash # /etc/init.d/mytest.sh # chkconfig: 2345 99 01 # description: A simple test service for boot startup ### BEGIN INIT INFO # Provides: mytest # Required-Start: $local_fs $network # Required-Stop: $local_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Test startup script # Description: This script demonstrates how to add a service to system boot. ### END INIT INFO SCRIPT_NAME="mytest" MARKER_FILE="/tmp/mytest_boot_marker_$(date +%s)" case "$1" in start) echo "Starting $SCRIPT_NAME..." touch "$MARKER_FILE" 2>/dev/null if [ $? -eq 0 ]; then echo "$SCRIPT_NAME started successfully. Marker created: $MARKER_FILE" else echo "Failed to start $SCRIPT_NAME." exit 1 fi ;; stop) echo "Stopping $SCRIPT_NAME..." rm -f "$MARKER_FILE" echo "$SCRIPT_NAME stopped." ;; status) if [ -f "$MARKER_FILE" ]; then echo "$SCRIPT_NAME is running. Marker file exists." ls -l "$MARKER_FILE" else echo "$SCRIPT_NAME is not running. Marker file missing." fi ;; restart) $0 stop sleep 1 $0 start ;; *) echo "Usage: $0 {start|stop|status|restart}" exit 2 ;; esac exit 0

这段脚本的关键点在于:

  • Shebang行#!/bin/bash确保使用bash解释器执行,避免因默认shell不同导致语法错误。
  • 注释块chkconfig行和### BEGIN/END INIT INFO块是给系统启动管理器看的“说明书”。它告诉系统这个脚本应该在哪些运行级别(2345)启动,启动优先级(99),停止优先级(01),以及它的依赖关系。虽然现代系统可能不严格读取这些,但保留它们是最佳实践,能提升兼容性。
  • case结构:清晰分隔startstopstatus等动作,每个分支都有明确的输出和错误处理。
  • 标记文件:使用/tmp目录(系统重启后自动清空)和时间戳,确保每次启动都生成唯一文件,方便你直观验证是否真的执行了。

现在,把上面的代码保存为/etc/init.d/mytest.sh。你可以用nanovim编辑:

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

粘贴内容后,按Ctrl+O保存,Ctrl+X退出。接着,必须赋予它可执行权限,否则系统无法运行:

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

最后,手动测试一下脚本是否工作正常:

# 启动脚本 sudo /etc/init.d/mytest.sh start # 检查状态 sudo /etc/init.d/mytest.sh status # 停止脚本 sudo /etc/init.d/mytest.sh stop

你应该能看到类似“Marker created”、“is running”等提示。如果一切顺利,说明脚本本身没有问题,可以进入下一步。

2. 确认系统运行级别与启动目录

在Linux中,“开机启动”并不是一个笼统的概念,而是精确绑定到系统的“运行级别”(Runlevel)。不同的运行级别代表系统不同的工作状态,比如单用户模式、多用户文本模式、图形界面模式等。系统启动时,会根据默认的运行级别,去加载对应目录下的启动脚本。

因此,我们必须先搞清楚你的系统默认运行级别是什么,然后才能知道该把启动链接放在哪个目录里。

最直接的方法是使用runlevel命令:

runlevel

这条命令会输出两个数字,例如N 5。第一个数字(N)表示上次的运行级别(N代表“None”,即系统刚启动),第二个数字(5)才是当前的运行级别。对于绝大多数桌面版Ubuntu和带GUI的CentOS,这个数字通常是5;而对于纯服务器环境(无图形界面),则很可能是32

小知识:运行级别0是关机,1是单用户维护模式,2-5是多用户模式,6是重启。其中2345通常都配置为多用户模式,区别在于是否启用网络、NFS等服务。所以,我们的脚本一般会同时注册到2345这几个级别。

确认了运行级别,接下来就是找到对应的启动目录。系统约定俗成,所有运行级别x的启动脚本链接,都存放在/etc/rcx.d/目录下。例如:

  • 运行级别3/etc/rc3.d/
  • 运行级别5/etc/rc5.d/

这些目录里的文件,其实都是指向/etc/init.d/中真实脚本的软链接。它们的名字有严格格式:以S开头表示“Start”(启动),以K开头表示“Kill”(停止),后面紧跟两位数字(01-99)表示执行顺序,最后是服务名。

例如,S20network表示在网络服务启动序列中排第20位,K80apache2表示在关机序列中排第80位停止Apache。

所以,如果你的runlevel输出是N 5,那么你就需要进入/etc/rc5.d/目录。执行:

cd /etc/rc5.d/ ls -l

你会看到一长串以SK开头的链接。现在,你的任务就是在这里添加一个新的链接,指向我们刚刚创建的/etc/init.d/mytest.sh

3. 创建启动软链接

进入正确的rcx.d目录后,就可以用ln -s命令创建软链接了。命令格式非常简单:

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

这里有几个关键细节需要你注意:

  • sudo:因为/etc/rc5.d/是系统目录,普通用户没有写入权限,必须加sudo
  • -s:表示创建“符号链接”(软链接),而不是硬链接。这是必须的,因为软链接可以跨文件系统,且能正确指向原始脚本。
  • /etc/init.d/mytest.sh:这是你脚本的绝对路径,必须写全,不能省略。
  • S99mytest:这是链接的名字S表示启动,99是启动序号,mytest是服务名。序号99意味着它会在绝大多数其他服务之后启动。这很安全,因为你的测试脚本不依赖数据库或网络服务,晚一点启动完全没问题。如果你的服务有强依赖(比如必须等MySQL先启动),就把序号调小,比如S20mytest

执行完这条命令后,用ls -l再查看一遍目录内容:

ls -l S99mytest

你应该能看到类似这样的输出:

lrwxrwxrwx 1 root root 22 Jun 10 14:30 S99mytest -> /etc/init.d/mytest.sh

这行输出清晰地告诉你:S99mytest是一个符号链接(l开头),它指向了/etc/init.d/mytest.sh。至此,注册工作就完成了。

为什么不用update-rc.d或chkconfig?
Ubuntu系统常用update-rc.d,CentOS常用chkconfig,它们是更高层的封装工具,能自动帮你处理所有运行级别的链接。但本文选择手动ln -s,是因为它最透明、最可控、最“底层”。你一眼就能看清链接在哪、指向哪、名字是什么,没有任何黑盒。当出现问题时,排查起来也最直接——删掉那个链接就行,无需记忆复杂的工具命令。

4. 验证启动项是否生效

现在,脚本已就位,链接已创建,万事俱备,只欠东风。但别急着重启!在重启之前,我们可以用一个更安全、更快捷的方式来模拟验证:手动触发系统启动流程。

Linux系统在启动时,会依次执行/etc/rcx.d/目录下所有以S开头的脚本。我们可以模仿这个过程,手动运行一遍:

# 切换到rc5.d目录(根据你的运行级别调整) cd /etc/rc5.d/ # 手动执行所有S开头的脚本(包括我们刚加的) sudo ./S99mytest start

如果输出显示“started successfully”,并且/tmp下确实生成了标记文件,那就说明链接和脚本都工作正常。

但这还不够。真正的考验是系统启动时的自动执行。为了不中断你的工作,我们不建议立刻reboot。一个更优雅的验证方式是:切换运行级别

Linux允许你在不重启的情况下,临时切换到另一个运行级别。例如,从图形界面(级别5)切换到多用户文本模式(级别3),系统会先执行所有K开头的停止脚本,再执行S开头的启动脚本。这是一个完美的“微型重启”测试。

执行以下命令:

# 切换到运行级别3(多用户文本模式) sudo telinit 3 # 等待几秒,然后切回5(图形界面) sudo telinit 5

在切换过程中,系统会自动执行/etc/rc3.d//etc/rc5.d/下的脚本。如果你的脚本被正确注册到了rc5.d,那么在telinit 5时,它就会被再次启动。

切换回来后,立即检查:

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

如果状态显示“is running”,恭喜你,你的开机启动项已经成功注册!它会在每一次系统启动时,自动运行。

5. 故障排查与常见问题

即使严格按照步骤操作,有时也会遇到意外。别担心,下面列出几个最常遇到的问题及其解决方法,帮你快速定位和修复。

问题1:/etc/rc5.d/目录不存在

现象cd /etc/rc5.d/报错No such file or directory
原因:你的系统可能使用的是systemd,并且默认没有创建传统的rcx.d目录(尤其是较新的Ubuntu 20.04+或CentOS 8+)。
解决方案:首先确认你的系统是否真的用systemd。运行ps -p 1,如果输出中包含systemd,那你就处于systemd时代。此时,rcx.d目录可能被废弃,但好消息是,systemd提供了向后兼容的sysv-generator,它会自动将/etc/init.d/下的脚本转换为systemd服务。你只需要确保脚本有正确的### BEGIN INIT INFO块(我们已经在第一步写好了),然后执行:

sudo systemctl daemon-reload sudo systemctl enable mytest

enable命令会自动为你创建一个mytest.service的软链接,效果等同于rcx.d链接。

问题2:脚本启动失败,status显示“not running”

现象:手动运行start没问题,但telinit 5status却显示未运行。
原因:最常见的是脚本权限问题。/etc/init.d/下的脚本必须对root可执行,但有时chmod没生效,或者脚本被保存成了Windows格式(CRLF换行符)。
解决方案

  1. 再次检查权限:ls -l /etc/init.d/mytest.sh,确保有x标志。
  2. 检查换行符:file /etc/init.d/mytest.sh。如果输出包含CRLF,说明是Windows格式。用dos2unix命令修复:sudo dos2unix /etc/init.d/mytest.sh

问题3:ln -s命令报错“File exists”

现象ln -s ... S99mytest提示S99mytest: File exists
原因:你可能不小心重复执行了命令,或者之前已经创建过同名链接。
解决方案:直接删除旧链接,再重新创建:

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

问题4:重启后脚本依然没运行

现象reboot后,/tmp下没有标记文件。
原因runlevel命令显示的当前级别,未必是系统启动时的默认级别。有些系统(如Ubuntu)的默认目标是graphical.target,它可能映射到级别5,但也可能被覆盖。
解决方案:最保险的办法是,为所有常见的多用户级别都创建链接:

sudo ln -s /etc/init.d/mytest.sh /etc/rc2.d/S99mytest sudo ln -s /etc/init.d/mytest.sh /etc/rc3.d/S99mytest sudo ln -s /etc/init.d/mytest.sh /etc/rc4.d/S99mytest sudo ln -s /etc/init.d/mytest.sh /etc/rc5.d/S99mytest

这样,无论系统默认启动到哪个级别,你的脚本都会被加载。

6. 总结与进阶思考

到这里,你已经亲手完成了一个Linux开机启动项的全部创建流程。从编写一个结构规范的脚本,到确认系统运行级别,再到创建精准的软链接,最后通过安全的telinit命令验证效果——每一步都清晰、可控、可复现。这不仅仅是一个“测试脚本”的部署,更是你深入理解Linux系统初始化机制的一次实战演练。

回顾整个过程,有三个核心要点值得你牢牢记住:

  • 脚本是基石:一个合格的启动脚本,必须有明确的start/stop/status接口和正确的注释头。它不是一段随意的Shell代码,而是一个被系统“认可”的服务单元。
  • 链接是桥梁/etc/rcx.d/目录下的软链接,是连接你的脚本与系统启动流程的唯一通道。名字中的S/K和数字,决定了它何时、以何种顺序被调用。
  • 验证是关键:永远不要跳过验证环节。telinit命令提供了一种零风险的测试方式,比盲目重启高效得多。

当然,这只是一个起点。当你熟悉了这套基础机制后,可以自然地向更现代、更强大的方向演进。比如,学习如何编写systemd.service文件,它提供了更精细的依赖管理、资源限制和日志集成;或者探索cron @reboot这种轻量级替代方案,适合那些不需要完整服务生命周期管理的简单任务。

但无论如何,今天你掌握的这套基于init.drcx.d的方法,依然是Linux世界中最经典、最通用、最值得信赖的启动机制之一。它不炫技,不依赖新特性,却能在任何一台标准Linux服务器上稳定运行数十年。

现在,是时候让你的脚本,在每一次系统苏醒时,都准时亮起它的第一盏灯了。


获取更多AI镜像

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

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

Qwen3-4B Instruct-2507多场景落地:支持私有化交付的6类行业模板包

Qwen3-4B Instruct-2507多场景落地:支持私有化交付的6类行业模板包 1. 为什么需要一款“专注纯文本”的轻量大模型? 你有没有遇到过这样的情况: 想快速写一段产品介绍文案,打开一个AI工具,等了8秒才出第一行字&#…

作者头像 李华
网站建设 2026/2/11 6:25:25

Qwen3-VL-8B多轮对话系统搭建指南:上下文维护+OpenAI API兼容详解

Qwen3-VL-8B多轮对话系统搭建指南:上下文维护OpenAI API兼容详解 1. 为什么你需要一个真正好用的本地多轮对话系统? 你是不是也遇到过这些问题: 在线大模型网页版响应慢、经常卡顿,关键时候掉链子;想在公司内网或私…

作者头像 李华
网站建设 2026/2/6 14:41:27

Qwen3-Reranker-0.6B性能评测:对比bge-reranker-base的吞吐与精度

Qwen3-Reranker-0.6B性能评测:对比bge-reranker-base的吞吐与精度 1. 模型背景与定位 你有没有遇到过这样的问题:在RAG系统里,检索模块返回了10个文档,但真正有用的可能只有第3个和第7个,前两名反而是干扰项&#xf…

作者头像 李华
网站建设 2026/2/6 13:14:17

工业智能毕设入门实战:从零搭建一个可落地的边缘推理系统

工业智能毕设入门实战:从零搭建一个可落地的边缘推理系统 做毕设最怕什么? “算法跑通那一刻以为自己要优秀毕业生了,结果到现场演示,模型加载三分钟、风扇狂转、画面卡成PPT。” 别笑,这就是工业智能选题的常态&…

作者头像 李华
网站建设 2026/2/7 2:26:36

[ZYNQ]开发之基于AN108模块的DMA高速ADC数据采集与以太网传输优化

1. 项目背景与核心需求 在工业监测、医疗成像等实时性要求高的场景中,高速ADC数据采集与低延迟传输是关键挑战。ZYNQ SoC凭借其ARM处理器与FPGA协同架构,结合AN108模块的8位高速ADC(32MSPS采样率),能够实现PS端通过DM…

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

一键部署mPLUG视觉问答:图片内容分析工具快速体验

一键部署mPLUG视觉问答:图片内容分析工具快速体验 1. 为什么你需要一个本地化的图片理解工具? 你有没有遇到过这样的场景:手头有一张产品截图,想快速确认图中包含几个关键部件;或者收到一张会议现场照片,…

作者头像 李华