小白也能学会!用测试开机启动脚本实现程序自动运行
你有没有遇到过这样的情况:服务器重启后,自己写的监控脚本、数据采集程序或者Web服务没跟着一起启动,得手动登录上去再执行一遍?每次都要重复操作,既费时间又容易忘记。其实,Linux系统早就为我们准备好了成熟的机制——开机自启动脚本。今天这篇内容,不讲复杂原理,不堆术语,就用最直白的方式,带你从零开始,亲手配置一个能随系统一起启动的脚本。哪怕你刚接触Linux不久,只要会复制粘贴、敲几条命令,就能搞定。
整个过程只需要五步,每一步我都配了清晰说明和可直接运行的命令。不需要你懂init、systemd或runlevel的底层逻辑,只需要知道“做什么”和“为什么这么做”。我们用的是通用方法,CentOS和Ubuntu都适用,不用纠结版本差异。准备好终端,咱们现在就开始。
1. 先写一个能跑起来的测试脚本
别急着改系统配置,第一步永远是:确保你的程序本身能正常运行。
我们先在/etc/init.d/目录下创建一个简单的测试脚本,名字叫mytest.sh。这个位置是传统SysV init系统存放服务脚本的标准路径,兼容性最好,新手也最容易理解。
打开终端,执行以下命令:
sudo nano /etc/init.d/mytest.sh把下面这段内容完整复制进去(注意保留每一行):
#!/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: 测试开机启动脚本 # Description: 一个用于验证自动启动功能的简单脚本 ### END INIT INFO case "$1" in start) echo "mytest 脚本已启动" >> /var/log/mytest.log echo "$(date): 启动成功" >> /var/log/mytest.log ;; stop) echo "$(date): 正在停止" >> /var/log/mytest.log ;; restart) $0 stop $0 start ;; *) echo "用法: $0 {start|stop|restart}" exit 1 ;; esac exit 0保存并退出(nano里按Ctrl+O回车确认保存,Ctrl+X退出)。接着给它加上可执行权限:
sudo chmod +x /etc/init.d/mytest.sh现在你可以手动测试一下它能不能工作:
sudo /etc/init.d/mytest.sh start执行完后,检查日志是否生成:
cat /var/log/mytest.log你应该能看到类似这样的输出:
mytest 脚本已启动 2024-06-15 10:23:45: 启动成功这说明脚本本身没问题,可以进入下一步了。
2. 看一眼系统当前的“启动档位”
Linux系统启动时,并不是一股脑把所有服务全拉起来,而是按“运行级别”(runlevel)分批加载。你可以把它想象成汽车的档位:不同档位对应不同的服务组合。桌面系统通常用的是第5档(图形界面),服务器常用第3档(多用户文本模式)。
我们先查查自己的系统现在挂在哪一档:
runlevel你会看到类似这样的输出:
N 5前面的N表示“未切换”,后面的5就是当前运行级别。这意味着系统启动时,会去/etc/rc5.d/这个目录里找要执行的脚本。
小贴士:如果你用的是Ubuntu桌面版,大概率是5;如果是CentOS服务器,默认可能是3。没关系,我们后面会根据实际结果来操作,不用提前猜。
那这些rc5.d目录到底是干啥的?简单说:
/etc/init.d/是“服务脚本仓库”,所有脚本都放这儿;/etc/rc5.d/是“启动任务清单”,它里面不存脚本本身,只存指向/etc/init.d/里脚本的快捷方式(软链接);- 系统启动时,就按这个清单里的顺序,一个个去执行。
3. 找到属于你的那个“启动清单”目录
既然runlevel告诉我们当前是第5档,那就直接进对应的目录:
cd /etc/rc5.d/然后列出里面的内容:
ls -l你会看到一堆以S或K开头的文件,比如S10sysklogd、S20ssh、K90network……它们都是软链接,指向/etc/init.d/下的真实脚本。
重点来了:
- 所有以
S开头的,代表“Start”,也就是开机时要启动的服务; - 所有以
K开头的,代表“Kill”,也就是关机或切换级别时要停止的服务; - 后面的两位数字(比如
S20的20)表示执行顺序:数字越小越早执行,越大越晚。比如数据库服务一般要等网络先起来,所以它的序号就会设得大一点(如S99mysql)。
我们的目标,就是在这个目录里,加一个属于自己的Sxx链接,告诉系统:“开机时,请记得执行我的脚本”。
4. 给你的脚本加一个“开机闹钟”
现在,我们为刚才写的mytest.sh创建一个软链接,让它出现在/etc/rc5.d/目录里。
执行这条命令(注意:99是序号,你可以改成98、97,只要在1–99之间就行):
sudo ln -s /etc/init.d/mytest.sh /etc/rc5.d/S99mytest这条命令的意思是:“在/etc/rc5.d/目录下,创建一个名叫S99mytest的快捷方式,它指向/etc/init.d/mytest.sh”。
创建完后,再用ls确认一下:
ls -l S99*你应该能看到:
S99mytest -> /etc/init.d/mytest.sh这就成功了。系统下次启动时,就会在所有S99级别的任务中,执行你的脚本。
为什么选99?
因为它排在最后,意味着你的脚本会在绝大多数基础服务(网络、文件系统等)都就绪之后才运行。这样能避免“脚本想连数据库,但数据库还没启动”的尴尬。如果你的程序依赖特别强,99是稳妥选择;如果只是简单打印日志,80、70也完全没问题。
5. 验证效果:重启试试看
配置完成,现在就差最后一步——验证它真的能自动运行。
执行重启命令:
sudo reboot等待系统重新启动并登录后,检查日志:
cat /var/log/mytest.log如果看到不止一行记录,比如:
mytest 脚本已启动 2024-06-15 10:23:45: 启动成功 2024-06-15 10:35:12: 启动成功恭喜你!第二行的时间戳,就是系统重启后自动执行的结果。你的脚本已经真正实现了“开机自启”。
你还可以再手动触发一次启动,看看日志是否追加:
sudo /etc/init.d/mytest.sh start再查日志,应该又多了一行。说明脚本既能被系统自动调用,也能被你随时手动管理,非常灵活。
6. 日常维护小技巧:怎么停、怎么删、怎么改
配置不是一劳永逸的。日常使用中,你可能还需要:
暂时关闭自启(不删除脚本)
如果你某次不想让它开机运行,不用删文件,只要把S99mytest改个名,比如加个下划线:
sudo mv /etc/rc5.d/S99mytest /etc/rc5.d/_S99mytest下次重启它就不会执行了。想恢复?把下划线去掉就行。
彻底删除自启配置
如果确定不再需要,两步走:
# 1. 删除软链接 sudo rm /etc/rc5.d/S99mytest # 2. (可选)删除原始脚本 sudo rm /etc/init.d/mytest.sh修改启动顺序
比如你觉得99太靠后,想让它早点运行,只需删掉旧链接,新建一个序号更小的:
sudo rm /etc/rc5.d/S99mytest sudo ln -s /etc/init.d/mytest.sh /etc/rc5.d/S20mytest查看所有自启服务状态
想快速知道哪些服务设置了开机启动?可以用这个命令:
sudo systemctl list-unit-files | grep enabled虽然我们用的是传统SysV方式,但现代系统也会把/etc/init.d/下的脚本自动映射为systemd服务,所以这个命令也能看到mytest.sh的状态(显示为enabled)。
7. 常见问题与解决思路
刚上手时,几个高频问题我帮你列出来,附上一句话解决方案:
Q:执行runlevel提示命令不存在?
A:某些新版Ubuntu默认不装sysvinit-utils包。直接运行systemctl get-default,如果输出graphical.target,就等同于 runlevel 5;输出multi-user.target,就等同于 runlevel 3。你按这个结果进/etc/rc5.d/或/etc/rc3.d/即可。
Q:重启后日志没更新,脚本没运行?
A:先检查软链接是否真的存在且指向正确:ls -l /etc/rc5.d/S99mytest;再确认脚本有执行权限:ls -l /etc/init.d/mytest.sh;最后看/var/log/mytest.log文件权限是否允许写入(一般不会错,但值得一看)。
Q:脚本里想运行Python程序,但提示找不到命令?
A:在脚本里不要只写python script.py,而要写绝对路径,比如/usr/bin/python3 /home/user/myscript.py。因为开机时环境变量很精简,$PATH可能不包含你常用的路径。
Q:能不能让脚本开机后延迟10秒再运行?
A:可以。在脚本的start)分支里,把echo前面加一行:sleep 10。不过要注意,这会让整个启动流程卡住10秒,建议只在必要时使用。
8. 进阶思考:这个方法适合什么场景?什么时候该换别的方案?
这套基于/etc/init.d/和rcx.d/的方法,最大优势是简单、稳定、跨发行版。它像一把老式螺丝刀,没有花哨功能,但拧紧任何一颗标准螺丝都稳当可靠。
它最适合:
- 你写的是一段Shell脚本,逻辑不复杂;
- 你用的是CentOS 7以前、Ubuntu 14.04–16.04这类较老系统;
- 你追求最小依赖,不想引入新概念;
- 你只是临时加个监控或数据同步任务,不需要精细的状态管理。
但如果你遇到这些情况,建议后续了解 systemd:
- 脚本需要监听某个端口,失败时自动重启;
- 你想精确控制服务之间的依赖关系(比如“必须等MySQL启动完再启动我的程序”);
- 你用的是 Ubuntu 18.04+、CentOS 8+ 等新系统;
- 你需要通过
systemctl status mytest实时查看运行状态。
不过别担心——今天你掌握的这套方法,不仅够用,而且是理解更高级方案的基础。所有复杂的自动化,都是从一个能开机就跑的脚本开始的。
9. 总结:你刚刚完成了什么?
回顾一下,我们只用了五步,就让一个普通脚本拥有了“生命感”:
- 写了一个带标准头的Shell脚本,并验证它能手动运行;
- 用
runlevel确认了系统启动档位,知道了该往哪个目录里加任务; - 理解了
rc5.d/目录的作用——它不是存脚本的地方,而是存“执行清单”的地方; - 用
ln -s创建软链接,给脚本安排了一个明确的启动序号和时机; - 通过重启真实验证,看到日志里多出的那一行时间戳,就是你亲手赋予的自动化能力。
这不是魔法,只是Linux几十年沉淀下来的成熟约定。你不需要成为系统专家,只需要理解这几个关键节点,就能把重复劳动交给机器。
下一步,你可以把任何你想自动化的任务——备份数据库、拉取最新代码、发送启动通知——都套用这个模板,稍作修改,立刻生效。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。