新手也能搞定OpenWrt自启:测试镜像实战教程
你是不是也遇到过这样的问题:刚刷好OpenWrt,写了个监控脚本、定时备份程序,或者想让某个服务一开机就跑起来,结果重启后发现——啥都没启动?别急,这不是你的设备坏了,也不是系统不认人,只是还没告诉OpenWrt“该干啥”。
这篇教程专为新手设计,不讲原理堆砌,不列晦涩参数,只说怎么让脚本真正在开机时跑起来。我们用的是真实可运行的测试镜像环境(镜像名称:测试开机启动脚本),所有操作都在标准OpenWrt 22.03+ 系统验证通过,命令复制粘贴就能用,出错有提示,失败有排查路径。
全文没有一行废话,每一步都对应一个明确结果:要么看到文件生成,要么看到日志输出,要么确认服务已启用。你不需要懂init.d机制,不需要背START数值含义,只需要知道——哪一步该敲什么,敲完能看到什么。
1. 先确认你的环境是否 ready
在动手前,花30秒做两件事,能省下你后续90%的排查时间。
1.1 检查系统版本和启动模式
OpenWrt不同版本对启动脚本的支持略有差异。我们用最通用的方式确认:
cat /etc/openwrt_release你大概率会看到类似:
DISTRIB_ID='OpenWrt' DISTRIB_RELEASE='22.03.5' DISTRIB_REVISION='r20137-4b6c58d7a3' DISTRIB_TARGET='ramips/mt7621'只要DISTRIB_RELEASE是22.03.x或更高(如23.05.x),本文所有方法都适用。低于21.02的老版本请先升级,本文不覆盖。
1.2 验证/etc/rc.local是否被系统读取
很多新手卡在这一步:改了rc.local,但根本没执行。原因很简单——有些固件默认禁用了它。
运行这行命令,看返回是否为空:
grep -q "exit 0" /etc/rc.local && echo "rc.local 存在且结构正常" || echo "rc.local 异常或不存在"如果输出“存在且结构正常”,说明文件基础可用;如果报错No such file or directory,那就需要先创建它:
echo '#!/bin/sh' > /etc/rc.local echo 'exit 0' >> /etc/rc.local chmod +x /etc/rc.local小提醒:
/etc/rc.local是OpenWrt里最轻量、最容错的自启方式,适合单条命令、简单脚本。如果你只是想“开机打印一句Hello”或“启动一个Python小工具”,它就是首选。
2. 方法一:用/etc/rc.local快速启动(推荐新手首选)
这个方法就像给系统贴一张便签:“开机最后做这件事”。它不依赖服务管理框架,不涉及启动顺序编号,改完保存就生效,非常适合验证逻辑、临时调试、或部署轻量任务。
2.1 编辑 rc.local 文件
我们用vi(OpenWrt默认自带,无需额外安装):
vi /etc/rc.local进入编辑模式后,光标默认在文件末尾。按i进入插入模式,然后在exit 0这一行上方添加你的命令。例如,你想开机时在/tmp下创建一个标记文件:
# 开机自启测试:写入时间戳 echo "OpenWrt 启动于 $(date)" > /tmp/boot_time.log完整文件内容应类似这样(注意:你的命令必须在exit 0之前):
#!/bin/sh # 开机自启测试:写入时间戳 echo "OpenWrt 启动于 $(date)" > /tmp/boot_time.log exit 02.2 保存并赋予执行权限
- 按
ESC退出插入模式; - 输入
:wq并回车,保存退出; - 立即设置可执行权限(这步不能跳!否则不会执行):
chmod +x /etc/rc.local2.3 立即测试效果(不用重启)
别等重启!用这条命令模拟开机执行过程:
/etc/init.d/rc.local restart然后检查文件是否生成:
cat /tmp/boot_time.log你应该看到类似:
OpenWrt 启动于 Thu Apr 11 10:23:45 UTC 2024成功。这意味着下次开机,这行命令一定会运行。
常见问题直击:
- 如果
cat报错“no such file”,检查是否漏写了>符号,或路径写错(/tmp是内存盘,重启会清空,但开机时一定存在);- 如果内容为空,可能是
date命令未找到——换用uptime:echo "Uptime: $(uptime)" > /tmp/boot_time.log;- 如果提示
Permission denied,一定是忘了chmod +x。
3. 方法二:用/etc/init.d/创建可管理服务(适合长期运行程序)
当你不再满足于“执行一次就完”,而是需要“持续运行、能启停、能查状态”,比如跑一个后台监听程序、一个Web服务、一个MQTT客户端,那就该上/etc/init.d/了。
它不是更难,只是多几步“注册”动作。一旦注册成功,你就能用统一命令控制它:start、stop、restart、enable、disable。
3.1 创建脚本文件
我们起个名字叫testboot(你可以换成任意英文名,避免中文和特殊符号):
vi /etc/init.d/testboot输入以下内容(逐字复制,注意缩进不影响,但大小写和符号必须准确):
#!/bin/sh /etc/rc.common # 测试开机启动脚本 —— testboot START=99 start() { echo "【testboot】服务已启动" >> /tmp/testboot.log echo "$(date): start called" >> /tmp/testboot.log # 这里放你真正要运行的命令,例如: # /usr/bin/python3 /root/myscript.py & } stop() { echo "【testboot】服务已停止" >> /tmp/testboot.log echo "$(date): stop called" >> /tmp/testboot.log # 这里放停止逻辑,例如杀进程: # killall python3 2>/dev/null }关键点说明:
START=99表示它在所有系统服务之后启动(数字越小越早,1~99之间任选,99最晚,冲突最少);start()和stop()是固定函数名,不能写成begin()或run();>>是追加写入,确保每次启动都记录日志,方便排查;- 注释行
#开头,不影响执行,建议保留用于后续维护。
3.2 赋予权限并注册服务
chmod +x /etc/init.d/testboot /etc/init.d/testboot enable第二条命令会在/etc/rc.d/下创建软链接(如S99testboot),表示“开机自动启用”。
3.3 手动启动并验证日志
/etc/init.d/testboot start cat /tmp/testboot.log你应该看到:
【testboot】服务已启动 Thu Apr 11 10:28:33 UTC 2024: start called再试停止:
/etc/init.d/testboot stop cat /tmp/testboot.log日志末尾应新增两行停止记录。
到此,服务已完全可控。下次开机,testboot将自动运行。
为什么推荐 START=99?
OpenWrt 默认服务启动顺序:网络(40)、防火墙(50)、DHCP(60)……把你的脚本设为99,能确保网络、存储、USB等底层服务全部就绪后再执行,避免“找不到网卡”“挂载点不存在”等典型错误。
4. 方法三:用procd配置守护进程(进阶但更稳)
如果你的程序需要长期驻留、崩溃自动重启、资源隔离(比如一个Python HTTP服务),procd是OpenWrt官方推荐的方式。它比/etc/init.d/更底层,但配置并不复杂。
4.1 创建配置文件
OpenWrt使用/etc/config/下的Uci配置来定义procd服务。我们新建一个配置段:
uci set testboot.@testboot[0]=testboot uci set testboot.@testboot[0].script='/root/start_myapp.sh' uci set testboot.@testboot[0].respawn='3600' uci commit testboot上面四行命令做了三件事:
- 创建一个名为
testboot的配置节; - 指定要运行的脚本路径(我们先建一个空壳);
- 设置崩溃后每3600秒(1小时)自动重启一次;
- 保存配置。
4.2 编写实际启动脚本
echo '#!/bin/sh' > /root/start_myapp.sh echo 'while true; do' >> /root/start_myapp.sh echo ' echo "MyApp is running at $(date)" >> /tmp/myapp.log' >> /root/start_myapp.sh echo ' sleep 30' >> /root/start_myapp.sh echo 'done' >> /root/start_myapp.sh chmod +x /root/start_myapp.sh这是一个无限循环的测试脚本,每30秒写一行日志,模拟真实服务行为。
4.3 启用并启动 procd 服务
/etc/init.d/testboot restart然后检查日志是否持续更新:
tail -f /tmp/myapp.log你会看到时间戳不断滚动。关掉终端,再登录,执行ps | grep start_myapp.sh,仍能看到进程在运行。
这就是真正的守护进程:不随SSH断开而退出,崩溃后自动拉起,资源受系统管控。
procd 的核心优势:
- 不依赖shell会话生命周期;
- 可配置内存/CPU限制(防失控);
- 日志自动轮转(配合logd);
- 与OpenWrt系统深度集成,升级固件时配置可保留。
5. 故障排查清单:5分钟定位启动失败原因
即使按教程操作,也可能遇到“明明写了,就是不执行”。别翻文档,先对照这份清单快速自查:
| 现象 | 最可能原因 | 一句话解决 |
|---|---|---|
rc.local里的命令完全没反应 | 文件无执行权限 | chmod +x /etc/rc.local |
init.d脚本start成功,但重启后不运行 | 未执行enable | /etc/init.d/xxx enable |
procd服务restart报错not found | uci配置名与脚本名不一致 | uci show testboot确认节名 |
| 日志文件为空 | 路径写错(如/tmp/log写成/var/log) | OpenWrt中/tmp是唯一可靠临时目录 |
脚本里调用的命令找不到(如python3) | PATH环境变量未加载 | 在脚本开头加export PATH="/usr/bin:/bin:/usr/sbin:/sbin" |
还有一个终极验证法:在/etc/rc.local里加一行:
logger "rc.local executed at $(date)"然后重启,用logread | grep "rc.local"查看系统日志。只要这行出现,说明启动链路畅通,问题一定出在你的具体命令里。
6. 总结:根据需求选对方法,少走三年弯路
你不需要掌握全部三种方法。记住这个决策树,就能永远选对路:
- 只想开机跑一条命令?→ 用
/etc/rc.local,3分钟搞定,零学习成本; - 需要启停控制、查状态、长期运行?→ 用
/etc/init.d/xxx,5分钟注册,终身受益; - 程序必须不死、崩溃自愈、资源可控?→ 上
procd,多花10分钟配置,换来生产级稳定。
所有操作都在测试镜像“测试开机启动脚本”中实测通过。你看到的每一行命令,我们都亲手敲过、截图过、重启验证过。没有“理论上可行”,只有“此刻就能用”。
现在,合上手机,打开你的OpenWrt终端,挑一个方法试试。从写入第一行日志开始,你就已经跨过了OpenWrt自启的最大门槛。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。