参考 Openwrt Init Scripts官方文档

在 procd 执行/etc/rc.d/S*时,其参数为"boot"(例如:/etc/rc.d/S00sysfixtime boot),这样就会执行
每个脚本里面的 boot 函数,也可能是间接执行 start 函数。/etc/rc.d/下的所有脚本都是链接到/etc/init.d/下的脚本。

系统启动脚本
  • 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 >&-)。  S19firewall
    启动防火墙 fw3。该工具来自 Openwrt 软件包 package/network/config/firewall
  • S20network
    根据 UCI 配置文件/etc/config/network,使用守护进程/sbin/netifd 来配置网络。
添加启动脚本

启动脚本存放在/etc/init.d 目录,首先创建一个启动脚本/etc/init.d/example

#!/bin/sh /etc/rc.common
# Example script
# Copyright (C) 2007 OpenWrt.org 
START=10
STOP=15
start() {        
        echo start
        # commands to launch application
}                 
stop() {          
        echo stop
        # commands to kill application 
}

然后给/etc/init.d/example 添加可执行权限chmod a+x /etc/init.d/example并执行

openwrt 执行python openwrt执行脚本_符号链接


按照提示执行命令出现以下情况:

openwrt 执行python openwrt执行脚本_符号链接_02

因为/etc/rc.common 中已经定义了所有默认的函数,当我们没有重新实现这些函数时,程序会执行/etc/rc.common中的默认函数,比如在这个 example 中,我们没有定义 restart 函数,我们跟参数 restart 时,程序执行/etc/rc.common中的 restart 函数,该函数首先调用 stop 函数,再调用 start 函数。而一旦我们重新实现了这些函数,在执行时,程序就会调用我们自己实现的函数。

脚本中的 START= 和 STOP= 分别决定了该脚本会在系统启动过程和系统关机过程的哪个点执行,数字越小越先执行。
当我们以 enable 参数调用启动脚本时,系统会创建一个该脚本文件的符号链接(例如 S10example、K15example),放在/etc/rc.d/目录下,而当以 disable 参数调用脚本时,系统会删除该符号链接。

  • START=10:意味着该脚本文件会被/etc/rc.d/S10example 链接。也就是说,该脚本会在 START=10 及之下这样的脚本后面执行,而在 START=11 及之上这样的脚本前面执行。
  • STOP=15:意味着该脚本文件会被/etc/rc.d/K15example 链接。也就是说,该脚本会在 STOP=14 及之下这样的脚本后面执行,而在 STOP=16 及之上这样的脚本前面执行

    注:
    如果多个初始化脚本具有相同的起始值,则调用顺序由初始化脚本名称的字母顺序确定。

还可以添加boot()函数
这些命令将在启动时运行,而不是在start()部分中运行,后者通常在未定义boot()时在启动时运行。这对于需要在启动时执行的操作很方便,但不是每次调用程序时都必须重新启动。

boot() {
        echo boot
        # commands to run on boot
}
添加自定义命令
EXTRA_COMMANDS="custom"
EXTRA_HELP="        custom  Help for the custom command"
 
custom() {
        echo "custom command"
        # do your custom stuff
}

openwrt 执行python openwrt执行脚本_配置文件_03

实现 helloworld 开机自启动

在之前的helloworld(点击进入)基础上,mkdir package/helloworld/files创建files目录存放启动脚本helloworld。此时结构:

openwrt 执行python openwrt执行脚本_启动脚本_04


helloworld启动脚本内容:

#!/bin/sh /etc/rc.common

START=50
STOP=10
start() {
	/bin/helloworld &
}
stop() {
	killall helloworld
}

修改helloworld目录下的Makefile

define Package/$(PKG_NAME)/install
	$(INSTALL_DIR) $(1)/bin $(1)/etc/init.d/
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/
	$(INSTALL_BIN) ./files/helloworld $(1)/etc/init.d/
endef
#以上修改Makefile不同的地方
#以下粘贴到最后一行上面
define Package/$(PKG_NAME)/postinst
	#!/bin/sh
	# check if we are on real system
	if [ -z "$${IPKG_INSTROOT}" ]; then
		echo "Enabling rc.d symlink for helloworld"
		/etc/init.d/helloworld enable
	fi
exit 0
endef

define Package/$(PKG_NAME)/prerm
	#!/bin/sh
	# check if we are on real system
	if [ -z "$${IPKG_INSTROOT}" ]; then
		echo "Removing rc.d symlink for helloworld"
		/etc/init.d/helloworld disable
	fi
exit 0
endef

$IPKG_INSTROOT 这个变量如果为空,则表示在目标设备运行,否则在主机运行

然后编译就ok了。

烧写重启看到:

openwrt 执行python openwrt执行脚本_符号链接_05


openwrt 执行python openwrt执行脚本_openwrt 执行python_06


也可以选择单独编译拷贝再opkg install 安装。

要查询所有init脚本的自启动状态,可以使用以下命令:

for F in /etc/init.d/* ; do $F enabled && echo $F on || echo $F **disabled**; done
重点补充

从前面知识了解到/etc/rc.d/中存放的都是K+数字+/etc/init.d/对应的脚本名字或者S+数字+/etc/init.d/对应的脚本名字 当我们以 enable 参数调用启动脚本时,系统会创建一个该脚本文件的符号链接(例如 S10example、K15example),放在/etc/rc.d/目录下,而当以 disable 参数调用脚本时,系统会删除该符号链接。
这些对应的脚本中的 START= 和 STOP=(就是K或者S后面的数字) 分别决定了该脚本会在系统启动过程和系统关机过程的哪个点执行,数字越小越先执行。
也就是开机的时候会按照数字从小到大执行S开头的脚本来启动对应的程序,
而关机的时候会按照数字从小到大执行K开头的脚本来关闭对应的程序。

但是!!!!
发现同一个服务带S的和带K的链接到init.d目录下的同一个脚本,也就是说他俩的内容是一样的,那为什么在开关机的时候执行同一个脚本会到达开启或者关闭服务程序的目的呢?

神奇的地方就在这两个名字中的KS了。他们并不止是用来看起来分的清楚而已。S和K还分别给init.d下面的脚本传递了startstop的参数!