openwrt系统 sysupgrade 命令执行过程分析

2023-11-03 18:10

本文主要是介绍openwrt系统 sysupgrade 命令执行过程分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0:扯淡

对这个openwrt的细节方面了解的还比较欠缺,故从实际中的经常用的功能说起,研究研究,可以了解更多的细节。

在openwrt的页面中已经涉及到下面的内容如:


其中在更新系统时候有进行配置保存及恢复的功能。

1:sysupgrade是的交互式使用命令如下:


经过上面的系统更新之后,会保存上面显示的配置文件中的内容,故更新系统不会影响配置的丢失。

3:脚本分析

脚本有点多,其中分析主要的脚本就可以了,其他的加一些打印信息可以帮助分析执行流程。

[python]  view plain copy
print ?
  1. 上面就是通过openwrt系统提供的sysupgrade命令来对系统进行更新的。  
  2. root@OpenWrt:~# which sysupgrade  
  3. /sbin/sysupgrade  
  4. 看看脚本中的主要内容,  
  5. include /lib/upgrade  
  6.   
  7. do_save_conffiles() {  
  8.     local conf_tar="${1:-$CONF_TAR}"  
  9.   
  10.     [ -z "$(rootfs_type)" ] && {  
  11.         echo "Cannot save config while running from ramdisk."  
  12.         ask_bool 0 "Abort" && exit  
  13.         return 0  
  14.     }  
  15.     run_hooks "$CONFFILES" $sysupgrade_init_conffiles  
  16.     ask_bool 0 "Edit config file list" && vi "$CONFFILES"  
  17.   
  18.     v "Saving config files..."  
  19.     [ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""  
  20.     tar c${TAR_V}zf "$conf_tar" -T "$CONFFILES" 2>/dev/null  
  21. }  
  22. 其中run_hooks函数的定义如下,其主要是执行钩子函数,即,第一个参数为:函数参数,第二个参数之后为:调用函数。  
  23.   
  24. run_hooks() {  
  25.     local arg="$1"; shift  
  26.     for func in "$@"; do  
  27.         eval "$func $arg"  
  28.     done  
  29. }  
  30.     run_hooks "$CONFFILES" $sysupgrade_init_conffiles 的作用就是将需要保存的文件名字保存到"$CONFFILES"文件中,保存那些文件了  
  31.     定义在add_uci_conffiles()和add_overlayfiles()函数中。  
  32. add_uci_conffiles() {  
  33.     local file="$1"  
  34.     ( find $(sed -ne '/^[[:space:]]*$/d; /^#/d; p' \  
  35.         /etc/sysupgrade.conf /lib/upgrade/keep.d/* 2>/dev/null) \  
  36.         -type f 2>/dev/null;  
  37.       opkg list-changed-conffiles ) | sort -u > "$file"  
  38.     return 0  
  39. }  
  40.   
  41. add_overlayfiles() {  
  42.     local file="$1"  
  43.     find /overlay/etc/ -type f | sed \  
  44.         -e 's,^/overlay/,/,' \  
  45.         -e '\,/META_[a-zA-Z0-9]*$,d' \  
  46.         -e '\,/functions.sh$,d' \  
  47.         -e '\,/[^/]*-opkg$,d' \  
  48.     > "$file"  
  49.     return 0  
  50. }  
  51. 默认保存的文件内容如下:如果需要对自定  
  52. etc/wifidog.conf  
  53. etc/sysctl.conf  
  54. etc/squid/squid.conf  
  55. etc/shells  
  56. etc/rc.local  
  57. etc/profile  
  58. etc/passwd  
  59. etc/inittab  
  60. etc/hosts  
  61. etc/group  
  62. etc/dropbear/dropbear_rsa_host_key  
  63. etc/dropbear/dropbear_dss_host_key  
  64. etc/crontabs/root  
  65. etc/config/wifidog  
  66. etc/config/uhttpd  
  67. etc/config/system  
  68. etc/config/redirect  
  69. etc/config/network  
  70. etc/config/ip  
  71. etc/config/firewall  
  72. etc/config/dropbear  
  73. etc/config/dhcp  
  74. 函数ask_bool()实现是否与命令行进行交互式的处理。  
  75.     v "Saving config files..."  
  76.     [ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""  
  77.     tar c${TAR_V}zf "$conf_tar" -T "$CONFFILES" 2>/dev/null  
  78. 实现对上面的数据文件进行压缩处理,其文件名称为:/tmp/sysupgrade.tgz  
  79.   
  80. if [ -n "$CONF_IMAGE" ]; then  
  81.         case "$(get_magic_word $CONF_IMAGE cat)" in  
  82.                 # .gz files  
  83.                 1f8b) ;;  
  84.                 *)  
  85.                         echo "Invalid config file. Please use only .tar.gz files"  
  86.                         exit 1  
  87.                 ;;  
  88.         esac  
  89.         get_image "$CONF_IMAGE" "cat" > "$CONF_TAR"  
  90.         export SAVE_CONFIG=1  
  91. elif ask_bool $SAVE_CONFIG "Keep config files over reflash"; then  
  92.         do_save_conffiles  
  93.         export SAVE_CONFIG=1  
  94. else  
  95.         export SAVE_CONFIG=0  
  96. fi  
  97. 上面的条件判断执行的是elif,即默认是保存更改过的配置文件。 export SAVE_CONFIG=1  
  98.   
  99. 其中语句  
  100. kill_remaining TERM  
  101. sleep 3  
  102. kill_remaining KILL  
  103. 实现对进程的term和kill操作  
  104. kill_remaining() { # [ <signal> ]  
  105.     local sig="${1:-TERM}"  
  106.     echo -n "Sending $sig to remaining processes ... "  
  107.   
  108.     local stat  
  109.     for stat in /proc/[0-9]*/stat; do  
  110.         [ -f "$stat" ] || continue  
  111.   
  112.         local pid name state ppid rest  
  113.         read pid name state ppid rest < $stat  
  114.         name="${name#(}"; name="${name%)}"  
  115.   
  116.         local cmdline  
  117.         read cmdline < /proc/$pid/cmdline  
  118.   
  119.         # Skip kernel threads   
  120.         [ -n "$cmdline" ] || continue  
  121.   
  122.         case "$name" in  
  123.             # Skip essential services  
  124.             *ash*|*init*|*watchdog*|*ssh*|*dropbear*|*telnet*|*login*|*hostapd*|*wpa_supplicant*) : ;;  
  125.   
  126.             # Killable process  
  127.             *)  
  128.                 if [ $pid -ne 
    ] && [ $ppid -ne
     ]; then  
  129.                     echo -n "$name "  
  130.                     kill -$sig $pid 2>/dev/null  
  131.                 fi  
  132.             ;;  
  133.         esac  
  134.     done  
  135.     echo ""  
  136. }  
  137.   
  138. 在升级操作之前有一个run_ramfs(),将一个最小能运行的系统mount到内存中去。为后的操作提供运行环境。  
  139. run_ramfs() { # <command> [...]  
  140.     install_bin /bin/busybox /bin/ash /bin/sh /bin/mount /bin/umount        \  
  141.         /sbin/pivot_root /usr/bin/wget /sbin/reboot /bin/sync /bin/dd   \  
  142.         /bin/grep /bin/cp /bin/mv /bin/tar /usr/bin/md5sum "/usr/bin/[" \  
  143.         /bin/vi /bin/ls /bin/cat /usr/bin/awk /usr/bin/hexdump          \  
  144.         /bin/sleep /bin/zcat /usr/bin/bzcat /usr/bin/printf /usr/bin/wc  
  145.   
  146.     install_bin /sbin/mtd  
  147.     for file in $RAMFS_COPY_BIN; do  
  148.         install_bin $file  
  149.     done  
  150.     install_file /etc/resolv.conf /lib/functions.sh /lib/functions.sh /lib/upgrade/*.sh $RAMFS_COPY_DATA  
  151.   
  152.     pivot $RAM_ROOT /mnt || {  
  153.         echo "Failed to switch over to ramfs. Please reboot."  
  154.         exit 1  
  155.     }  
  156.   
  157.     mount -o remount,ro /mnt  
  158.     umount -l /mnt  
  159.   
  160.     grep /overlay /proc/mounts > /dev/null && {  
  161.         mount -o remount,ro /overlay  
  162.         umount -l /overlay  
  163.     }  
  164.   
  165.     # spawn a new shell from ramdisk to reduce the probability of cache issues  
  166.     exec /bin/busybox ash -c "$*"  
  167. }  
  168. 在整整操作之前先看看 mtd,sysupgrade 更新过程实际使用的就是mtd命令  
  169. root@OpenWrt:/overlay/etc#mtd   
  170. Usage: mtd [<options> ...] <command> [<arguments> ...] <device>[:<device>...]  
  171.   
  172. The device is in the format of mtdX (eg: mtd4) or its label.  
  173. mtd recognizes these commands:  
  174.         unlock                  unlock the device  
  175.         refresh                 refresh mtd partition  
  176.         erase                   erase all data on device  
  177.         write <imagefile>|-     write <imagefile> (use - for stdin) to device  
  178.         jffs2write <file>       append <file> to the jffs2 partition on the device  
  179. Following options are available:  
  180.         -q                      quiet mode (once: no [w] on writing,  
  181.                                            twice: no status messages)  
  182.         -n                      write without first erasing the blocks  
  183.         -r                      reboot after successful command  
  184.         -f                      force write without trx checks  
  185.         -e <device>             erase <device> before executing the command  
  186.         -d <name>               directory for jffs2write, defaults to "tmp"  
  187.         -j <name>               integrate <file> into jffs2 data when writing an image  
  188.         -p                      write beginning at partition offset  
  189.   
  190. Example: To write linux.trx to mtd4 labeled as linux and reboot afterwards  
  191.          mtd -r write linux.trx linux  



[ruby]  view plain copy
print ?
  1. do_upgrade() {  
  2.     v "Performing system upgrade..."  
  3.     if type 'platform_do_upgrade' >/dev/null 2>/dev/null; then  
  4.         platform_do_upgrade "$ARGV"  
  5.     else  
  6.         default_do_upgrade "$ARGV"  
  7.     fi  
  8.     [ "$SAVE_CONFIG" -eq 1 -a -n "$USE_REFRESH" ] && {  
  9.         v "Refreshing partitions"  
  10.         if type 'platform_refresh_partitions' >/dev/null 2>/dev/null; then  
  11.             platform_refresh_partitions  
  12.         else  
  13.             refresh_mtd_partitions  
  14.         fi  
  15.         if type 'platform_copy_config' >/dev/null 2>/dev/null; then  
  16.             platform_copy_config  
  17.         else  
  18.             jffs2_copy_config  
  19.         fi  
  20.     }  
  21.     v "Upgrade completed"  
  22.     [ -n "$DELAY" ] && sleep "$DELAY"  
  23.     ask_bool 1 "Reboot" && {  
  24.         v "Rebooting system..."  
  25.         reboot -f  
  26.         sleep 5  
  27.         echo b 2>/dev/null >/proc/sysrq-trigger  
  28.     }  
  29. }  
  30.   
  31. default_do_upgrade() {  
  32.     sync  
  33.     if [ "$SAVE_CONFIG" -eq 1 -a -z "$USE_REFRESH" ]; then  
  34.         get_image "$1" | mtd -j "$CONF_TAR" write - "${PART_NAME:-image}"  
  35.     else  
  36.         get_image "$1" | mtd write - "${PART_NAME:-image}"  
  37.     fi  
  38. }  
  39.   
  40. platform_do_upgrade() {  
  41.     local rootfs="$(x86_get_rootfs)"  
  42.     local rootfsdev="${rootfs##*:}"  
  43.   
  44.     sync  
  45.     [ -b ${rootfsdev%[0-9]} ] && get_image "$@" | dd of=${rootfsdev%[0-9]} bs=4096 conv=fsync  
  46.     sleep 1  
  47. }  
  48.   
  49.   
  50. x86_get_rootfs() {  
  51.     local rootfsdev  
  52.     local rootfstype  
  53.       
  54.     rootfstype="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "rootfstype") { print $2 }' < /proc/cmdline)"  
  55.     case "$rootfstype" in  
  56.         squashfs|jffs2)  
  57.             rootfsdev="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "block2mtd.block2mtd") { print substr($2,1,index($2, ",")-1) }' < /proc/cmdline)";;  
  58.         ext4)  
  59.             rootfsdev="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "root") { print $2 }' < /proc/cmdline)";;  
  60.     esac  
  61.           
  62.     echo "$rootfstype:$rootfsdev"  
  63. }  
  64.   
  65. jffs2_copy_config() {  
  66.     if grep rootfs_data /proc/mtd >/dev/null; then  
  67.         # squashfs+jffs2  
  68.         mtd -e rootfs_data jffs2write "$CONF_TAR" rootfs_data  
  69.     else  
  70.         # jffs2  
  71.         mtd jffs2write "$CONF_TAR" rootfs  
  72.     fi  
  73. }  
  74. refresh_mtd_partitions() {  
  75.     mtd refresh rootfs  
  76. }  

其中需要注意的是不同的平台如,Atheros和x86的各个平台的执行过程有所不同,最终一点是需要将$CONF_TAR保存到系统的 rootfs_data或者 rootfs_data分区数据中去。

这篇关于openwrt系统 sysupgrade 命令执行过程分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/339954

相关文章

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

2.1/5.1和7.1声道系统有什么区别? 音频声道的专业知识科普

《2.1/5.1和7.1声道系统有什么区别?音频声道的专业知识科普》当设置环绕声系统时,会遇到2.1、5.1、7.1、7.1.2、9.1等数字,当一遍又一遍地看到它们时,可能想知道它们是什... 想要把智能电视自带的音响升级成专业级的家庭影院系统吗?那么你将面临一个重要的选择——使用 2.1、5.1 还是

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

关于Maven生命周期相关命令演示

《关于Maven生命周期相关命令演示》Maven的生命周期分为Clean、Default和Site三个主要阶段,每个阶段包含多个关键步骤,如清理、编译、测试、打包等,通过执行相应的Maven命令,可以... 目录1. Maven 生命周期概述1.1 Clean Lifecycle1.2 Default Li

SpringBoot 整合 Grizzly的过程

《SpringBoot整合Grizzly的过程》Grizzly是一个高性能的、异步的、非阻塞的HTTP服务器框架,它可以与SpringBoot一起提供比传统的Tomcat或Jet... 目录为什么选择 Grizzly?Spring Boot + Grizzly 整合的优势添加依赖自定义 Grizzly 作为

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Ubuntu系统怎么安装Warp? 新一代AI 终端神器安装使用方法

《Ubuntu系统怎么安装Warp?新一代AI终端神器安装使用方法》Warp是一款使用Rust开发的现代化AI终端工具,该怎么再Ubuntu系统中安装使用呢?下面我们就来看看详细教程... Warp Terminal 是一款使用 Rust 开发的现代化「AI 终端」工具。最初它只支持 MACOS,但在 20

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用