参考自:OpenWRT编译 – 用户自定义添加app的开机自启动
OpenWRT 学习笔记-19 OpenWRT开机自启动服务
一、概述
OpenWRT开机自启动服务通过 procd
来管理,ubuntu通过systemd管理。
通常的嵌入式系统均有一个守护进程,该守护进程监控系统进程的状态,如果某些系统进程异常退出,将再次启动这些进程。
procd
就是这样一个进程,它是使用C语言编写的,一个新的 OpenWrt 进程管理服务。它通过 init 脚本来将进程信息加入到 procd 的数据库中来管理进程启动,这是通过ubus总线调用来实现,可以防止进程的重复启动调用。
OpenWrt开机启动服务实现和普通Linux发行版并无明显差异,基本上就是 /etc/init.d
和 /etc/rc.d
两个目录在起关键作用。/etc/init.d
目录存放的是 所有的开机启动脚本(包含启动和未启用的服务),/etc/rc.d
存放的是 启用的(Enabled)开机启动脚本。只有 enabled 的 service 才可以通过软链接放到/etc/rc.d。
服务的启用和禁用可以通过 service enable/disable
命令来实现。
1、在 openwrt 系统内 init 进程被 procd 取代,procd作为父进程可以监控子进程的状态。一旦子进程退出后即可在某一个时刻尝试进行重启进程。
2、如果应用软件需要在 boot 时自动运行,则需要在 /etc/init.d
中增加相应的脚本文件。脚本文件需要 START
参数, 说明在 boot 时的优先级, 如果在 boot 过程启动后再关闭, 则需要进一步设置 STOP
参数。如果 STOP 参数存在, 其值必须大于 START。
3、脚本文件需要 start()
和 stop()
两个函数,start() 是执行程序, stop() 是关闭程序。当存在 boot() 方法时, 系统启动时会调用 boot() 而不是 start()。
4、由 /etc/rc.d/S10boot
知道,装载內核驱动模块的优先级为 10,需要使用自己设计的內核驱动模块的程序其 START 的值必须大于 10。
5、同样由 /etc/rc.d/S40network
知道, 使用网络通信的程序其 START 的值必须大于 40。
二、自启动实现方式一
在原来的app应用程序的基础上实现自启动,详见:【OpenWRT编译 – 添加用户自定义app】
1、package/myapp/目录下创建一个目录 root/,用来存放启动脚本
$ mkdir package/myapp/root
然后在 package/myapp/root/ 目录下创建procd启动脚本文件 mycode,其内容如下:
#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2011 OpenWrt.org
START=90 # 启动的顺序,越大越靠后,按照字符串顺序排序并不是数字排序。START=90 代表该脚本的启动顺序为90(注意,不是第90个执行的脚本,而是一个级别)。(数字越小,启动的越早)
STOP=92 # 停止的顺序, 越小越靠前
USE_PROCD=1 # 声明使用procd启动
SERVICE=app
PROG=/app/mycode
# start_service 函数必须要重新定义
start_service()
{
echo service mycode start
procd_open_instance # 创建一个实例, 在 procd 看来一个应用程序可以多个实例
# ubus call service list 可以查看实例
procd_set_param command $PROG # mycode执行的命令是"/app/mycode"
procd_append_param command para1 # 启动参数的追加,如果有多个参数可以对此追加
procd_append_param command para2 # 启动参数的追加,如果有多个参数可以对此追加
procd_set_param respawn # 定义respawn参数,告知procd当mycode程序退出后尝试进行重启
procd_close_instance # 关闭实例
}
# service_triggers 重新定义,没有操作那么可以删掉,但是不能为空
service_triggers()
{
procd_add_reload_trigger mycode
}
#reload_service重新定义,没有操作那么可以删掉,但是不能为空
reload_service()
{
echo service mycode reload
}
# stop_service重新定义,退出服务后需要做的操作,没有操作那么可以删掉,但是不能为空
stop_service()
{
echo service mycode stop
}
#restart重新定义,没有操作那么可以删掉,但是不能为空
restart()
{
stop
start
}
脚本分析:
-
#!/bin/sh /etc/rc.common
固定在第一行,指定了执行该脚本的方式(必须),shebang #! 使用 /bin/sh 作为脚本解释器,/etc/rc.common 作为启动脚本执行前的检查脚本,可以检测出非法的参数。其实就是将整个shell的控制权交到了 /etc/rc.comon 这个脚本,从第2行开始的所有shell语句只能被动地被 rc.common 中的语句所调用。例如该脚本名为 mycode,如果执行命令为
mycode parameters
,即为运行/etc/rc.common mycode parameters
。从上可以看出,script本身并不解析命令行参数,而是由/etc/rc.common来完成。
-
START=
和