从init进程逐步到/etc/init.d,整体分析Openwrt的软件启动机制

一、init进程介绍

  • init进程是所有系统进程的父进程,它被内核调用起来并负责调用所有其他的进程。 如果任何进程的父进程退出,init进程将成为它的父进程。但是init进程是如何将其他进程调用起来的呢?接下来介绍。

二、OpenWrt软件启动机制

第一步
  • 内核启动完成后读取/etc/inittab文件,然后执行inittab中的sysinit所指的脚本(/etc/init.d/rcS)。
  • OpenWrt的inittab文件内容如下:

第二步
  • 如果按照通常的简单做法:我们会将每一个待启动的程序启动命令按行放入rcS文件中,并顺序执行。这种实现方法在软件启动进程列表不变时工作得非常好,如果需要动态修改,则不容易以程序来控制(在OpenWrt下,使用ls命令查看不到/etc/init.d/rcS这个文件)。OpenWrt引入了一个便于控制的启动机制,这种机制是在/etc/rc.d目录下创建每个软件的软链接方式,由rcS脚本在该目录读取启动命令的软链接, 然后启动软链接所指向的程序,由于每一个软链接均包含一个数字,这样就可以按照数字顺序读取并进行启动了。
  • 具体执行流程:执行/etc/init.d/rcS脚本时,给脚本传递两个参数(分别为S何boot),接着rcS脚本通过run_scripts函数来启动软件,将每一个以/etc/rc.d/S开头的脚本按照数字传递boot参数并调用。
    • S:表示软件启动模块,是和 K(软件关闭)相对应的。
    • boot:表示首次启动。

  • 例如从/etc/rc.d目录下的脚本可以看出,就是先执行../init.d/sysfixtime,再执行../init.d/boot,以此类推......。几个比较重要的程序如下:
    • S10boot:调用uci_apply_defaults执行第1此开机时的UCI配置初始化,该函数执行/etc/uci-defaults/下的所有脚本,执行成功后就删除,因此该目录下的脚本只有第一次开机才会执行。
    • S10system:根据UCI配置文件/etc/config/system配置系统,具体可参考该配置文件。
    • S11sysctl:根据/etc/sysctl.conf配置系统([-f  /etc/sysctl.conf]  && sysctl -p -e >&-)。
    • S19filewall:启动防火墙fw3,该工具来自openwrt软件包package/network/config/firewal。
    • S20network:根据UCI配置文件/etc/config/network,使用守护进程/sbin/netifd来配置网络。

三、“/etc/init.d/*”脚本分析

  • 上面那些最终调用的软件启动shell脚本,包含变量定义和函数定义(start、stop和restart等函数)。
  • 备注:因为/etc/rc.d/下面文件是/etc/int.d/下脚本的软链接,根据软链接的特性,我们查看软链接文件也就可以访问到/etc/int.d/下面的脚本文件。
  • 另外使用 opkg 命令安装软件时一般均有执行权限,如果是自己手动新增脚本,不要忘记确认脚本是否有执行权限(通过运行 chmod +x /etc/init.d/hello命令来增加执行权限)。
脚本分析

  • /etc/rc.common:这个脚本没有解析自己的命令行参数,这是通过“/etc/rc.common”脚本回调来完成的。第一行是特殊的注释行,表示使用“/etc/rc.common”来提供一些基本函数,包含主函数及默认功能以及检查脚本执行等。
  • START、STOP变量:脚本的执行顺序通过START和 STOP变量来定义。
    • 如果这两个变量被更改了,再次运行/etc/init.d/hello enable才会再次生效,并且这将删除以前创建的启动链接,然后再根据新的变量定义创建链接(创建的启动链接保存在“/etc/rc.d”目录下)。
    • 如果多个初始化脚本有相同的启动优先值,则调用顺序取决于启动脚本名称的字母顺序(在上上张图中S10boot与S10system文件中的START变量值相同,但是他们按照脚本名称的字母排序启动)。
  • start()、stop()函数:脚本中最重要的函数是 start 和 stop,这两个函数决定如何启动和停止服务。
rc.common函数含义
  • 备注:其中的start()、stop()函数实现为空,供应用软件重新实现,相当于C++语言中的虚函数。
  • enable、disable 和 enabled函数提供自启动状态的设置和查询。
  • help函数提供命令帮助信息,如果你不带参数运行软件命令,将会自动调用help函数输出帮助信息。
  • boot函数与start函数的关系:命令在启动时取代 start 函数而执行 boot 函数,如果 boot 函数没 有被重新定义,将执行 rc.common 中预定义的 boot 函数,boot 函数再次调用 start 函数。
  • 详情见下表:
函 数含 义
start启动服务。相当于 C++语言中的虚函数,通常情况下每一个服务均需重写该函数
stop关闭服务。相当于 C++语言中的虚函数,通常情况下每一个服务均需重写该函数
restart重启服务。调用 stop 函数退出进程,然后再调用 start 函数启动进程
reload重新读取配置,如果读取配置失败则调用 restart 函数重启进程
enable打开服务自启动,即将启动脚本软链接文件放在/etc/rc.d 目录下
disable关闭服务自启动,删除在/etc/rc.d 的软链接文件
enabled提供服务自启动的状态查询
boot调用 start 函数
shutdown调用 stop 函数
help输出帮助信息
软链接特性
  • ①当我们使用enable设置一个软件为开机自启动时,将自动在/etc/rc.d/目录下创建一个软链接指向/etc/init.d/目录下的软件。
  • ②当我们使用disable关闭一个软件开机自启动时,软件在/etc/rc.d/目录下的软链接将删除。

四、自定义软件的启动脚本设计案例


  • 我是小董,V公众点击"笔记白嫖"解锁更多OpenWrt资料内容。

<think> 我们正在处理一个OpenWrt系统中uhttpd服务无法启动的问题。根据用户提供的引用内容,我们知道用户之前可能操作过用户添加和权限设置,但当前问题是关于uhttpd启动失败。 由于引用中提到了用户添加和sudo权限设置,但uhttpd启动失败可能与这些操作没有直接关系,我们需要从uhttpd服务本身入手。 常见原因和解决方法: 1. 端口冲突:uhttpd默认使用80端口,如果其他服务(如lighttpd, nginx)占用了80端口,则uhttpd无法启动。 2. 配置错误:检查/etc/config/uhttpd配置文件是否有语法错误。 3. 权限问题:uhttpd服务需要以root用户运行,检查运行权限。 4. 缺少依赖:确保uhttpd及其依赖包已正确安装。 5. 日志查看:通过日志定位错误原因。 步骤: 1. 检查端口占用:使用netstat命令查看80端口是否被占用。 2. 检查配置文件:使用uci命令检查uhttpd配置,并验证配置文件语法。 3. 查看日志:使用logread命令查看系统日志,或者直接运行uhttpd看输出错误。 由于OpenWrt系统资源有限,建议逐一排查。 具体操作: 步骤1:检查端口占用 执行命令:`netstat -tuln | grep ':80'` 如果输出显示80端口被其他进程占用,需要停止该进程(或者修改uhttpd的监听端口)。 步骤2:检查uhttpd配置 使用uci导出配置:`uci show uhttpd` 检查配置项,特别是监听地址和端口。也可以尝试重置配置文件(如果之前修改过): `rm /etc/config/uhttpd` `cp /rom/etc/config/uhttpd /etc/config/` `/etc/init.d/uhttpd restart` 步骤3:手动启动uhttpd并查看输出 停止服务:`/etc/init.d/uhttpd stop` 然后手动运行:`uhttpd -f` (-f参数表示前台运行,这样可以看到错误输出) 观察终端输出,根据错误信息解决问题。 步骤4:检查依赖 确保uhttpd已安装:`opkg list-installed | grep uhttpd` 如果没有安装,则安装:`opkg update && opkg install uhttpd` 步骤5:检查权限 确保uhttpd的执行文件有可执行权限:`ls -l /usr/sbin/uhttpd`,正常应为-rwxr-xr-x。 步骤6:检查日志 使用`logread`查看系统日志,或者查看/var/log/uhttpd.log(如果存在)。 此外,如果之前修改过用户权限,尤其是修改了root用户的环境或者sudo配置,但uhttpd服务通常是以root身份通过init脚本启动,所以一般不受影响。但是,如果init脚本本身被修改,也可能导致启动失败。可以检查init脚本:`cat /etc/init.d/uhttpd`,确保其正确。 如果以上步骤无法解决,可以考虑重新安装uhttpd: `opkg --force-reinstall install uhttpd` 注意:操作前备份重要配置。 根据用户引用中提到的内容,用户添加了用户并设置了sudo权限,但并未提及修改uhttpd相关配置,因此可能不是直接原因。建议从端口冲突和配置入手。 最后,由于用户引用中提到了禁止root远程登录,但uhttpd是一个Web服务,与登录无关,所以应该不会影响。 生成相关问题: 1. 如何修改OpenWrt中uhttpd的监听端口? 2. 如何在OpenWrt中查看系统日志? 3. 如何重新安装OpenWrt软件包? </think> 在OpenWrt系统中执行`/etc/init.d/uhttpd start`后服务无法启动,可能是由以下原因导致。请按顺序排查: ### 🔍 故障排查步骤 1. **检查端口冲突** uhttpd默认监听80端口,运行: ```bash netstat -tuln | grep ':80' ``` 若其他进程(如lighttpd)占用端口,需停止冲突服务或修改uhttpd端口: ```bash uci set uhttpd.main.listen_http=8080 # 修改端口 uci commit uhttpd ``` 2. **验证配置文件语法** 使用uci工具检查配置: ```bash uci show uhttpd ``` 若输出包含错误(如未闭合括号),需修复配置: ```bash rm /etc/config/uhttpd # 删除错误配置 cp /rom/etc/config/uhttpd /etc/ # 恢复默认配置 ``` 3. **检查依赖组件** uhttpd依赖`libustream-*`和`libuhttpd-*`: ```bash opkg list-installed | grep -E 'libustream|libuhttpd' ``` 若缺失依赖,重新安装: ```bash opkg update opkg --force-reinstall install uhttpd ``` 4. **查看错误日志** 关键日志路径: ```bash logread | grep uhttpd # 系统日志 cat /var/log/uhttpd.log # 专用日志(如有) ``` 常见错误示例: > `uhttpd: failed to bind to 0.0.0.0:80 (Address in use)` 5. **检查文件权限** 确保二进制文件可执行: ```bash chmod +x /usr/sbin/uhttpd /etc/init.d/uhttpd ``` 6. **测试直接启动** 前台运行观察输出: ```bash uhttpd -f -v ``` 若提示`error: ...`则为具体失败原因。 --- ### ️ 注意特殊情况 - **自定义证书问题**:若配置了HTTPS但证书路径错误,会导致崩溃。检查: ```bash uci get uhttpd.main.cert uci get uhttpd.main.key ``` - **内存不足**:低配设备可能因OOM(Out of Memory)失败,通过`free -m`确认内存余量。 - **脚本损坏**:对比默认脚本检查`/etc/init.d/uhttpd`完整性: [默认uhttpd脚本参考](https://github.com/openwrt/openwrt/blob/master/package/network/services/uhttpd/files/uhttpd.init) --- ### ✅ 解决方案总结 | 步骤 | 命令/操作 | 预期结果 | |------|-----------|----------| | 1. 释放端口 | `killall lighttpd; /etc/init.d/uhttpd start` | 80端口解除占用 | | 2. 重置配置 | `cp /rom/etc/config/uhttpd /etc/config/` | 配置恢复默认 | | 3. 重装服务 | `opkg --force-reinstall install uhttpd` | 修复损坏文件 | | 4. 手动调试 | `uhttpd -f` | 显示具体错误原因 | > 💡 若以上步骤无效,建议[备份配置](https://openwrt.org/docs/guide-user/configuration/sysupgrade.backup)后执行系统升级: > ```bash > sysupgrade -i /tmp/openwrt-sysupgrade.bin > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值