【笔记】openwrt - 备份、还原、定期备份

root@OpenWrt_D2550:/usr/lib/lua/luci# cat /etc/banner
     _________
    /        /\      _    ___ ___  ___
   /  LE    /  \    | |  | __|   \| __|
  /    DE  /    \   | |__| _|| |) | _|
 /________/  LE  \  |____|___|___/|___|
 \        \   DE /
  \    LE  \    /  -------------------------------------------
   \  DE    \  /    OpenWrt SNAPSHOT, r4415-8f2b0b86b
    \________\/    -------------------------------------------

(下图)openwrt luci 界面的备份是通过 lua 调用 sysupgrade 实现的。

sysupgrade help

root@OpenWrt_D2550:/usr/lib/lua/luci# sysupgrade --help
Usage: /sbin/sysupgrade [<upgrade-option>...] <image file or URL>
       /sbin/sysupgrade [-q] [-i] [-c] [-u] [-o] [-k] <backup-command> <file>

upgrade-option:
        -f <config>  restore configuration from .tar.gz (file or url)
        -i           interactive mode
        -c           attempt to preserve all changed files in /etc/
        -o           attempt to preserve all changed files in /, except those
                     from packages but including changed confs.
        -u           skip from backup files that are equal to those in /rom
        -n           do not save configuration over reflash
        -p           do not attempt to restore the partition table after flash.
        -k           include in backup a list of current installed packages at
                     /etc/backup/installed_packages.txt
        -T | --test
                     Verify image and config .tar.gz but do not actually flash.
        -F | --force
                     Flash image even if image checks fail, this is dangerous!
        -q           less verbose
        -v           more verbose
        -h | --help  display this help

backup-command:
        -b | --create-backup <file>
                     create .tar.gz of files specified in sysupgrade.conf
                     then exit. Does not flash an image. If file is '-',
                     i.e. stdout, verbosity is set to 0 (i.e. quiet).
        -r | --restore-backup <file>
                     restore a .tar.gz created with sysupgrade -b
                     then exit. Does not flash an image. If file is '-',
                     the archive is read from stdin.
        -l | --list-backup
                     list the files that would be backed up when calling
                     sysupgrade -b. Does not create a backup file.

至于 sysupgrade 是一个 shell 脚本(位置在 /sbin/sysupgrade)(300行代码)

引用了

. /lib/functions.sh
. /lib/functions/system.sh
. /usr/share/libubox/jshn.sh

# 备份的 luci 界面


在这里插入图片描述

源码在 /usr/lib/lua/luci/controller/admin/system.lua

看懂源码只需要明白openwrt的mvc架构
参考:【笔记】openwrt - luci开发(资料整理)
https://lawsssscat.blog.csdn.net/article/details/103609225

其中,每个按钮的 action 如下:

# 首页
entry({"admin", "system", "flashops"}, call("action_flashops"), _("Backup / Flash Firmware"), 70)
# 执行重置
entry({"admin", "system", "flashops", "reset"}, post("action_reset"))
# 生成备份
entry({"admin", "system", "flashops", "backup"}, post("action_backup"))

entry({"admin", "system", "flashops", "backupmtdblock"}, post("action_backupmtdblock"))

entry({"admin", "system", "flashops", "backupfiles"}, form("admin_system/backupfiles"))

# 上传备份(同时执行配置还原)
-- call() instead of post() due to upload handling!
entry({"admin", "system", "flashops", "restore"}, call("action_restore"))

entry({"admin", "system", "flashops", "sysupgrade"}, call("action_sysupgrade"))

entry({"admin", "system", "reboot"}, template("admin_system/reboot"), _("Reboot"), 90)

entry({"admin", "system", "reboot", "call"}, post("action_reboot"))

下面对每个 action 的操作流程进行分析

# 生成备份


在这里插入图片描述
源码

entry({"admin", "system", "flashops", "backup"}, post("action_backup"))

function action_backup()
        local reader = ltn12_popen("sysupgrade --create-backup - 2>/dev/null")

        luci.http.header(
                'Content-Disposition', 'attachment; filename="backup-%s-%s.tar.gz"' %{
                        luci.sys.hostname(),
                        os.date("%Y-%m-%d")
                })

        luci.http.prepare_content("application/x-targz")
        luci.ltn12.pump.all(reader, luci.http.write)
end

-- nixio api
-- https://github.com/openwrt/luci/blob/master/libs/luci-lib-nixio/docsrc/nixio.lua
function ltn12_popen(command)

        local fdi, fdo = nixio.pipe()
        local pid = nixio.fork()

        if pid > 0 then
                fdo:close()
                local close
                return function()
                        local buffer = fdi:read(2048)
                        local wpid, stat = nixio.waitpid(pid, "nohang")
                        if not close and wpid and stat == "exited" then
                                close = true
                        end

                        if buffer and #buffer > 0 then
                                return buffer
                        elseif close then
                                fdi:close()
                                return nil
                        end
                end
        elseif pid == 0 then
                nixio.dup(fdo, nixio.stdout)
                fdi:close()
                fdo:close()
                nixio.exec("/bin/sh", "-c", command)
        end
end

主要的命令就是

sysupgrade --create-backup - 2>/dev/null

把备份的配置传到(-)管道(pipe)中,然后通过http传到前端

这里,需要注意的是 sysupgrade 备份的内容。它会读文件 /etc/sysupgrade.conf/lib/upgrade/keep.d/* 对里面声明的内容进行备份,因此,我们可以把自定义的备份内容写到前者 sysupgrade.conf 中

下面是源码

# /sbin/sysupgrade 中的方法

list_static_conffiles() {
        local filter=$1

        find $(sed -ne '/^[[:space:]]*$/d; /^#/d; p' \
                /etc/sysupgrade.conf /lib/upgrade/keep.d/* 2>/dev/null) \
                \( -type f -o -type l \) $filter 2>/dev/null
}

# 执行重置

源码

entry({"admin", "system", "flashops", "reset"}, post("action_reset"))

function action_reset()
        if supports_reset() then
                luci.template.render("admin_system/applyreboot", {
                        title = luci.i18n.translate("Erasing..."),
                        msg   = luci.i18n.translate("The system is erasing the configuration partition now and will reboot itself when finished."),
                        addr  = "192.168.1.1"
                })

                fork_exec("sleep 1; killall dropbear uhttpd; sleep 1; jffs2reset -y && reboot")
                return
        end

        http.redirect(luci.dispatcher.build_url('admin/system/flashops'))
end

local function supports_reset()
        return (os.execute([[grep -sq "^overlayfs:/overlay / overlay " /proc/mounts]]) == 0)
end

主要的命令是

jffs2reset -y 
root@OpenWrt_D2550:~# jffs2reset
This will erase all settings and remove any installed packages. Are you sure? [N/y]

它是一个二进制文件,作用就是直接把 upper 层删了

关于 upper 层
参考:
【笔记】openwrt 扩容 overlay文件系统
https://lawsssscat.blog.csdn.net/article/details/105237099

另外这里,一般我们重置配置用的 firstboot 其实也是调用的 jffs2reset

root@OpenWrt_D2550:~# cat /sbin/firstboot
#!/bin/sh

/sbin/jffs2reset $@

# 定期备份

前面了解了 luci 的备份命令,就可以写我们自己的定期备份脚本了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骆言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值