新手必看:快速上手测试开机启动脚本的完整指南
你是不是也遇到过这样的问题:写好了服务脚本,却不知道怎么让它在系统一开机就自动运行?改完配置不敢重启,怕进不去系统;查资料看到一堆rc0.d、rc5.d、runlevel,越看越迷糊?别急,这篇指南就是为你写的——不讲抽象概念,不堆术语,只说你现在就能照着做的每一步。无论你是刚接触Linux的新手,还是临时需要验证一个启动逻辑的开发者,只要你会用终端、能复制粘贴命令,10分钟内就能让自己的脚本稳稳跑在开机第一线。
本文基于通用Linux环境(CentOS与Ubuntu均适用),全程使用真实可执行命令,所有操作无需修改内核、不依赖第三方工具,纯系统原生机制。我们用一个最简但完整的例子——mytest.sh——带你从零走完“写脚本→设权限→挂链接→验效果”的全流程。过程中会明确告诉你:哪步不能跳、哪条命令必须回车确认、哪个提示说明成功、哪个报错可以忽略。
1. 先写一个能“说话”的测试脚本
别一上来就搞复杂服务。我们先做一个最简单的脚本:它开机时运行,往系统日志里写一行字。这样你不用打开图形界面、不用连网络、甚至不用登录桌面,只要重启后查一条日志,就能100%确认脚本是否真的执行了。
1.1 创建脚本文件
打开终端,执行以下命令(逐行复制,回车执行):
sudo nano /etc/init.d/mytest.sh在nano编辑器中,输入以下内容(注意:前三行是标准LSB头,必须保留,这是让系统识别它是合法启动脚本的关键):
#!/bin/bash ### 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: A simple script to log boot time ### END INIT INFO case "$1" in start) echo "[$(date)] mytest.sh started at boot" >> /var/log/mytest.log ;; stop) echo "[$(date)] mytest.sh stopped" >> /var/log/mytest.log ;; *) echo "Usage: /etc/init.d/mytest.sh {start|stop}" exit 1 ;; esac exit 0小白提示:这段代码里没有魔法。
start分支做的事,就是把当前时间+一句话写进/var/log/mytest.log这个文件里。你完全不用理解case语法——只要知道:它开机时会执行start部分,这就够了。
1.2 设置执行权限并测试手动运行
保存退出(Ctrl+O → Enter → Ctrl+X),然后赋予执行权限:
sudo chmod +x /etc/init.d/mytest.sh现在手动运行一次,确认脚本本身没问题:
sudo /etc/init.d/mytest.sh start再检查日志是否写入成功:
cat /var/log/mytest.log你应该看到类似这样的输出:
[Wed 12 Jun 2024 09:45:22 AM CST] mytest.sh started at boot这一步成功,说明脚本语法正确、路径可用、日志可写——这是后续所有步骤的前提。如果这里报错(比如“Permission denied”或“No such file”),请回头检查chmod和nano保存是否成功,不要继续往下走。
2. 看清你的系统“启动档位”:不是所有Linux都一样
Linux开机启动不是“一键全开”,而是分“档位”(专业叫法:运行级别,runlevel)。不同档位加载不同的服务。桌面系统通常用5级(带图形界面),服务器常用3级(纯命令行)。你的脚本要挂到哪个档位的启动目录下,取决于你想让它在哪种环境下运行。
2.1 用一条命令,立刻知道该挂哪
在终端中输入:
runlevel你会看到类似这样的输出:
N 5其中第二个数字(这里是5)就是你当前系统的默认运行级别。N表示“从无级别启动”,可以忽略。
关键结论:
- 如果显示
N 2或N 3→ 你的系统是服务器模式,脚本应挂到/etc/rc3.d/- 如果显示
N 5→ 你的系统是桌面模式(Ubuntu GNOME/CentOS KDE等),脚本应挂到/etc/rc5.d/- 绝大多数现代桌面版Ubuntu和CentOS默认都是
5,所以接下来我们以/etc/rc5.d/为例。如果你是服务器,请把下面所有rc5.d替换为rc3.d即可。
2.2 为什么是rc5.d?它到底存了什么?
/etc/rc5.d/目录里没有真正的脚本,只有大量以Sxx或Kxx开头的软链接(symbolic link)。它们像一个个“开关”,指向/etc/init.d/下的真实脚本。
S= Start(启动)K= Kill(停止)xx= 两位数字,代表执行顺序(01最早,99最晚)
例如,S20nginx表示:在运行级别5下,第20个启动nginx服务;而K80mysql表示:关机时第80个停止mysql。
新手避坑提醒:
不要手动去/etc/rc5.d/里创建文件!必须用ln -s命令建软链接。直接复制或移动文件会导致系统无法识别,甚至启动失败。
3. 把你的脚本“插”进开机流程:三步到位
现在,我们把刚才写的/etc/init.d/mytest.sh,通过软链接的方式,“插入”到/etc/rc5.d/的启动队列中。
3.1 进入目标目录
cd /etc/rc5.d/3.2 创建启动软链接
执行这条命令(注意空格和大小写):
sudo ln -s /etc/init.d/mytest.sh S99mytest解释一下参数含义:
sudo:需要管理员权限才能在系统目录建链接ln -s:创建软链接的命令/etc/init.d/mytest.sh:源文件(你写的脚本真身)S99mytest:链接名 ——S表示启动,99表示最后启动(确保它在其他服务都起来之后再跑,避免依赖问题),mytest是名字,可自定义但建议保持简洁
3.3 验证链接是否创建成功
ls -l S99mytest你应该看到类似这样的输出:
S99mytest -> /etc/init.d/mytest.sh箭头->出现,说明软链接创建成功。如果报错No such file or directory,请检查:
/etc/init.d/mytest.sh文件是否存在(用ls /etc/init.d/mytest.sh确认)- 当前是否在
/etc/rc5.d/目录下(用pwd查看)
4. 最终验证:重启不是目的,看到日志才是真相
现在,你的脚本已经正式“入职”开机启动序列。但别急着reboot——我们先做一件更安全的事:模拟一次启动过程,提前预演。
4.1 手动触发“启动”动作(推荐!新手必做)
在不重启的情况下,直接让系统按开机逻辑执行一遍你的脚本:
sudo systemctl daemon-reload sudo systemctl enable mytest sudo systemctl start mytest注意:上面三条命令适用于较新版本的systemd系统(Ubuntu 16.04+/CentOS 7+)。如果你用的是老系统(如CentOS 6),请改用:
sudo chkconfig --add mytest sudo service mytest start
无论哪种方式,执行后再次查看日志:
cat /var/log/mytest.log你应该看到两行记录:一行是之前手动start写的,另一行是这次systemctl start或service start新写的。这证明:脚本已被系统识别,且能被服务管理器正常调用。
4.2 重启测试(终极确认)
如果上一步成功,就可以放心重启了:
sudo reboot等待系统完全启动、登录后,立即执行:
cat /var/log/mytest.log如果看到第三行,且时间戳是本次重启后的时间,恭喜你——你的脚本已真正实现开机自启!
[Wed 12 Jun 2024 09:45:22 AM CST] mytest.sh started at boot [Wed 12 Jun 2024 09:48:15 AM CST] mytest.sh started at boot [Wed 12 Jun 2024 10:12:03 AM CST] mytest.sh started at boot ← 这一行就是开机自动写的!5. 常见问题与一句解决法(附真实报错对照)
实际操作中,90%的问题都出在这几个点。我们把最常卡住的地方列出来,每条都配一句“救命命令”和原因说明:
5.1 报错:“/etc/init.d/mytest.sh: line X: syntax error near unexpected token”
- 原因:脚本里混入了Windows换行符(
\r\n)或中文标点(如全角括号、冒号) - 一句解决:
然后重新sudo sed -i 's/\r$//' /etc/init.d/mytest.shchmod +x并测试。
5.2 报错:“Failed to execute /etc/init.d/mytest.sh: Permission denied”
- 原因:脚本没有执行权限,或
#!/bin/bash第一行缺失/有空格 - 一句解决:
确保输出是sudo chmod +x /etc/init.d/mytest.sh && head -1 /etc/init.d/mytest.sh#!/bin/bash,且前面没空格。
5.3 重启后日志没新增,但手动start能写
- 原因:软链接没挂对目录(比如系统是
rc3.d你挂了rc5.d),或Default-Start里没包含当前运行级别 - 一句解决:
确保两个数字有交集(如runlevel && grep "Default-Start" /etc/init.d/mytest.shrunlevel输出N 3,则Default-Start里必须有3)。
5.4 想取消开机启动,怎么删?
- 安全删除法(不删原脚本):
sudo rm /etc/rc5.d/S99mytest # 或如果是systemd系统: sudo systemctl disable mytest
6. 进阶小技巧:让脚本更可靠、更省心
掌握了基础,再加三个实用技巧,让你的启动脚本从“能用”升级为“好用”:
6.1 加个启动状态灯:一眼看出是否生效
在脚本的start分支末尾,加一行:
touch /tmp/mytest_started然后每次开机后,只需:
ls /tmp/mytest_started && echo " 已启动" || echo "❌ 未启动"比翻日志快10倍。
6.2 避免重复执行:同一脚本不允许多次启动
在start分支开头,加入防重逻辑:
if [ -f /tmp/mytest_started ]; then echo "mytest already running" exit 0 fi6.3 日志自动轮转:防止mytest.log越积越大
新建一个logrotate配置:
echo "/var/log/mytest.log { daily missingok rotate 7 compress delaycompress notifempty }" | sudo tee /etc/logrotate.d/mytest这样每天自动归档,保留7天,永不撑爆磁盘。
7. 总结:你已经掌握的核心能力
回顾一下,你刚刚亲手完成了一件很多老手都未必能清晰解释的事:
- 写出了符合LSB规范的可启动脚本(不是随便一个
.sh都能开机跑) - 准确判断了自己系统的运行级别,并找到对应启动目录
- 用
ln -s安全创建软链接,理解了S99命名背后的执行逻辑 - 通过日志验证而非“感觉”,获得了100%确定的成功反馈
- 掌握了3个高频报错的秒级定位与修复方法
这不仅是“让一个脚本开机运行”,更是打开了Linux服务管理的大门。下一步,你可以把任何Python服务、Node.js后台、数据库初始化脚本,都用同样方法接入系统启动流程——原理完全一致,只是脚本内容不同。
记住:Linux的优雅,不在于命令多炫酷,而在于每一步都有据可依、有错可查、有法可解。你现在,已经站在了这个起点上。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。