OpenWrt启动脚本分析

分类: 嵌入式

原文地址:http://blog.chinaunix.net/uid-26517122-id-4418083.html

 openwrt是通过一系列shell脚本进行启动流程的组织,下面是启动流程的提纲。如果想详细了解启动的过程,则需要仔细走读脚本文件。

1、在make menuconfig 选择target平台“ShenZhou Loongson”,在Subtarget选择“GSC3280 Develop Board”平台。 

2、linux内核的配置文件由下面两个文件组成
        target/linux/generic/base-files/etc/init.d
        target/linux/szloongson/base-files/etc/init.d

3、在配置文件中可以看到
        CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 init=/etc/preinit noinitrd console=ttyS0,115200",因此,linux内核启动后,首先运行/etc/preinit脚本

4、preinit脚本位置在
        package/base-files/files/etc/preinit

5、preinit脚本是一系列脚本的入口,这一系列脚本放在下面的目录:
        package/base-files/files/lib/preinit
        target/linux/szloongson/base-files/etc/init.d
        编译完成后,会统一放在rootfs的/lib/preinit目录下,
        03_init_hotplug_failsafe_brcm 40_init_shm
        05_failsafe_config_switch_brcm 40_mount_devpts
        05_init_interfaces_brcm 40_mount_jffs2
        05_mount_skip 40_run_failsafe_hook
        05_set_failsafe_switch_brcm 41_merge_overlay_hooks
        10_check_for_mtd 50_choose_console
        10_essential_fs 50_indicate_regular_preinit
        10_indicate_failsafe 60_init_hotplug
        10_indicate_preinit 70_initramfs_test
        15_mount_proc_brcm 70_pivot_jffs2_root
        15_set_preinit_interface_brcm 80_mount_root
        20_check_jffs2_ready 90_init_console
        20_device_fs_mount 90_mount_no_jffs2
        20_failsafe_net_echo 90_restore_config
        20_failsafe_set_boot_wait_brcm 99_10_failsafe_login
        30_device_fs_daemons 99_10_mount_no_mtd
        30_failsafe_wait 99_10_run_init
        由于脚本众多,因此openwrt的设计者将这些脚本分成下面几类:
        preinit_essential
        preinit_main
        failsafe
        initramfs
        preinit_mount_root
        每一类函数按照脚本的开头数字的顺序运行。

6、preinit则执行下面的两类脚本
        boot_run_hook preinit_essential
        boot_run_hook preinit_main

7、preinit执行的最后一个脚本为99_10_run_init,运行
        exec env - PATH=$pi_init_path $pi_init_env $pi_init_cmd
        pi_init_cmd="/sbin/init",因此开始运行busybox的init命令

8、busybox的init命令执行inittab的脚本,该脚本来自
        package/base-files/files/etc/inittab
        ::sysinit:/etc/init.d/rcS S boot
        ::shutdown:/etc/init.d/rcS K stop
        tts/0::askfirst:/bin/ash --login
        ttyS0::askfirst:/bin/ash --login
        tty1::askfirst:/bin/ash --login
        sysinit为系统初始化运行的“/etc/init.d/rcS S”boot脚本
        shutdown为系统重启或关机运行的脚本
        tty开头的是,如果用户通过串口或者telnet登录,则运行/bin/ash --login
        askfirst和respawn相同,只是在运行前提示"Please press Enter to activate this console."

9、当前启动转到运行 /etc/init.d/rcS S boot,该脚本来自package/base-files/files/etc/init.d/rcS和preinit类似,rcS也是一系列脚本的入口,其运行/etc/rc.d目录下S开头的的所有脚本(如果运行rcS K stop,则运行K开头的所有脚本)
        K50dropbear S02nvram S40network S50dropbear S96led
        K90network S05netconfig S41wmacfixup S50telnet S97watchdog
        K98boot S10boot S45firewall S60dnsmasq S98sysntpd
        K99umount S39usb S50cron S95done S99sysctl
        上面的脚本文件来自:
        package/base-files/files/etc/init.d
        target/linux/szloongson/base-files/etc/init.d
        还有一些脚本来自各个模块,在install时拷贝到rootfs,比如dropbear模块:package/dropbear/files/dropbear.init,这些脚本先拷贝到/etc/init.d下,然后通过/etc/rc.common脚本,将init.d的脚本链接到/etc/rc.d目录下,并且根据这些脚本中的START和STOP的关键字,添加K${STOP}和S${START}的前缀,这样就决定了脚本的先后的运行次序。

10、可以看出,openwrt的启动主要是两个阶段,preinit主要是完成系统的初始化(如文件系统的准备、模块的加载),rcS主要依次启动各个模块。

附:脚本走读的一些技巧

a. rootfs目录在“/build_dir/target-mipsel-linux/root-szloongson”,可以直接在该目录下走读shell脚本。

b. OpenWrt的shell脚本比较复杂,因此看脚本时可以通过添加"set -x"和echo等命令,直接看shell脚本的结果,而不要花太多的时间硬看脚本,主要是理解其主要的意思和设计思路。

<think>我们正在讨论OpenWrt系统中的/tmp/main_restart文件在启动程序时的作用。根据之前引用的脚本(如引用[1][2])和OpenWrt的机制,我们可以分析:1.OpenWrt使用procd来管理守护进程,procd要求被管理的程序不能是守护进程(即不能fork到后台),否则procd会认为程序退出并尝试重启。2.在引用[1]的脚本中,通过设置USE_PROCD=1,并调用procd_set_param等函数来定义进程的启动方式,其中respawn参数表示进程退出后会自动重启。3.而用户提到的/tmp/main_restart并不是OpenWrt的标准机制,从我们讨论的上下文中没有直接出现,但我们可以推测它可能与自定义的进程管理或重启逻辑有关。根据引用[3],在OpenWrt中修改DHCP配置后需要重启dnsmasq服务,使用的是`/etc/init.d/dnsmasqrestart`命令,这里并没有出现/tmp/main_restart。我们考虑两种可能性:可能性1:/tmp/main_restart是用户自定义的脚本,用于实现某种特定的重启逻辑。例如,当一个程序需要重启时,可能通过写入一个标志文件(如/tmp/main_restart)来触发重启操作,然后在启动脚本中检查该文件是否存在,如果存在则执行重启。可能性2:/tmp/main_restart是某个特定应用程序(比如用户自己编写的程序)用来控制自己重启的机制。例如,程序在运行过程中,如果检测到需要重启,它可以创建这个文件,然后退出。而procd检测到程序退出后(因为设置了respawn)会重新启动它。同时,在启动脚本的start_service函数中,可能会先检查/tmp/main_restart是否存在,如果存在,则执行特定的重启初始化操作(比如清理状态)然后删除该文件。然而,在标准的OpenWrt启动脚本(如引用[1][2])中没有这样的用法。因此,这很可能是特定应用程序或自定义脚本的行为。如果我们参考引用[1]中的脚本,它使用procd来管理进程,并且通过`respawn`参数来重启进程。所以,如果程序退出,procd会自动重启它,不需要额外的文件。但是,有时应用程序可能需要完全重置内部状态,因此可能会在重启前要求删除某些文件或创建标记文件。这时,可以在启动脚本的start_service函数中检查并处理标记文件。例如,一个可能的实现方式:在start_service函数中,检查/tmp/main_restart文件是否存在。如果存在,则表明需要执行特殊的重启操作(比如删除一些临时文件或重置配置),然后删除该文件。最后再启动程序。示例代码片段:```shellstart_service(){if[-f/tmp/main_restart];then#执行特殊重启操作,比如清理旧的状态rm-f/tmp/main_restartfiprocd_open_instanceprocd_set_paramrespawnprocd_set_paramcommand/usr/bin/my_programprocd_close_instance}```这样,当用户想要程序重启并清除状态时,只需创建/tmp/main_restart文件并重启服务(如:`servicemy_programrestart`),那么服务重启时就会进行清理。因此,/tmp/main_restart的作用是作为一个标记,告诉启动脚本启动程序之前执行一些额外的清理操作。这种机制是自定义的,并不是OpenWrt的标准功能。注意:由于/tmp目录在重启后会被清除,所以/tmp/main_restart文件在系统重启后不会保留,它仅用于控制当前运行时的重启行为。总结:/tmp/main_restart在OpenWrt启动程序时并非标准机制,它可能是自定义脚本中用于触发特殊重启流程的标记文件。在启动脚本中检查该文件,如果存在则执行额外的重启初始化操作,然后删除该文件,最后正常启动程序。根据上述分析,我们可以回答用户的问题。注意:如果用户没有提供具体的脚本,我们无法确定其确切作用,但根据常见做法,我们可以给出上述解释。</think> 在OpenWrt系统中,`/tmp/main_restart` **不是系统标准文件路径**,通常是自定义脚本或应用程序实现的特殊控制机制。根据OpenWrt的procd进程管理机制和引用的启动脚本模式[^1][^2],它的主要作用和实现逻辑如下: --- ### /tmp/main_restart的作用 1. **服务重启触发标记** - 用作**软重启标志**文件,告知服务在启动时需要执行特殊初始化(如状态重置、配置重新加载) - 允许在不完全终止服务的情况下实现"热更新"[^3] ```bash # 创建重启标记(用户操作) touch /tmp/main_restart service my_service restart ``` 2. **自定义控制接口** - 通过检测文件存在性实现特定重启逻辑 - 区别于procd的标准`respawn`机制(仅进程崩溃自动重启)[^1] ```bash # 标准procd监控(自动崩溃重启) procd_set_param respawn ``` 3. **状态重置标记** - 清除缓存/临时文件 - 重新加载特定配置文件 - 跳过常规初始化步骤 --- ### 实现方式(代码示例) 在服务启动脚本中检测该文件并执行特殊逻辑: ```bash #!/bin/sh /etc/rc.common USE_PROCD=1 start_service() { # 检测重启标记 if [ -f "/tmp/main_restart" ]; then # 特殊重启逻辑 rm -f /var/run/app_state.cache # 清理缓存 cp /tmp/new_config.conf /etc/app.conf # 更新配置 rm /tmp/main_restart # 删除标记 else # 常规启动逻辑 cp /etc/default_config.conf /etc/app.conf fi procd_open_instance procd_set_param command /usr/bin/app_bin procd_close_instance } reload_service() { touch /tmp/main_restart # 创建重启标记 kill -SIGHUP $(cat /var/run/app.pid) # 通知应用重启 } ``` <center>▲ 图1:/tmp/main_restart在启动脚本中的典型实现</center> --- ### 工作流程 ```mermaid graph TD A[用户操作] -->|"service app restart"| B{检查/tmp/main_restart} B -->|存在| C[执行特殊初始化] B -->|不存在| D[执行标准初始化] C --> E[启动服务] D --> E F[reload操作] -->|"touch /tmp/main_restart"| G[发送SIGHUP信号] G -->|服务收到信号| H[重新加载配置] H --> I[部分状态重置] ``` <center>▲ 图2:/tmp/main_restart的工作流程图</center> --- ### 使用场景 1. **配置热更新** ```bash # 不中断服务更新配置 cp new_config.conf /tmp/new_config.conf touch /tmp/main_restart service app reload ``` 2. **状态复位** ```bash # 故障后复位应用状态 rm -f /var/run/app.lock touch /tmp/main_restart service app restart ``` 3. **AB版本切换** ```bash # 切换至备用版本 ln -sf /usr/bin/app_bin_bak /usr/bin/app_bin touch /tmp/main_restart service app restart ``` --- ### 注意事项 1. **临时性** - `/tmp`目录在设备重启后自动清空,标记不会持久化 2. **并发安全** - 需要添加文件锁避免竞争条件 ```bash lock /var/lock/main_restart.lock touch /tmp/main_restart unlock /var/lock/main_restart.lock ``` 3. **异常处理** - 应在脚本中实现超时和回退机制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值