jetson nano 系统镜像制作_参考备份Jetson Nano系统(该程序不完备,制作的image不可用,仅供)...

参考备份Jetson Nano系统(该程序不完备,制作的image不可用,仅供)

#!/usr/bin/python3

# -*- coding: utf-8 -*-

"""

Description:Ubuntu 19.04 Python 3.7.3

FileName: back_jetson.py

cmd:

sudo umount /dev/mapper/loop0p

sudo kpartx -dv /dev/loop0

sudo losetup -d /dev/loop0

sudo dump -0uaf - /media/fzyzm/S_TOOLS/BaiduNetdiskDownload|sudo restore -rf -

dump -0 -f /media/fzyzm/S_LINUX_OTHER/my_temp/bd.dump /home/fzyzm/下载/aarch64/EFI/BOOT/

sudo restore -rf /media/fzyzm/S_LINUX_OTHER/my_temp/bd.dump -D /media/fzyzm/S_LINUX_OTHER/my_temp/temp2/

run:

sudo python3 /home/fzyzm/PycharmProjects/my_tools/back_sys_image/back_jetson.py

"""

import os

import sys

import time

import subprocess

import chardet

from collections import OrderedDict

def get_coding(org_bytes):

encoding = chardet.detect(org_bytes)

if not encoding:

return "utf-8"

if not encoding['encoding']:

return "utf-8"

return encoding['encoding']

def exec_shell_cmd(cmd_list):

"""

执行shell命令

:param cmd_list:

:return:

"""

if not isinstance(cmd_list, (str, tuple, list)):

return ""

if isinstance(cmd_list, str):

cmd_list = cmd_list.split()

print("")

cmd_prompt = "exec cmd:" + " ".join(cmd_list)

print(cmd_prompt)

print("=" * len(cmd_prompt))

# 必须加上close_fds=True,否则子进程会一直存在 , shell=True会造成parted一直执行超时,

child = subprocess.Popen(cmd_list, close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

stdoutdata, stderrdata = child.communicate()

if child.returncode != 0:

stderrdata = stderrdata.decode(get_coding(stderrdata))

print("error info", child.returncode, stderrdata)

return ""

stdoutdata = stdoutdata.decode(get_coding(stdoutdata))

print(stdoutdata)

return stdoutdata

def exec_pip_cmd(*args, **kwargs):

"""

执行管道式命令

:param args:

:param kwargs:

:return:

"""

if not args:

return ""

for cmd_list in args:

if not isinstance(cmd_list, (str, tuple, list)):

return ""

cwd = None

if kwargs and "cwd" in kwargs:

cwd = kwargs["cwd"]

child_list = []

for cmd_list in args:

if isinstance(cmd_list, str):

cmd_list = cmd_list.split()

print("")

cmd_prompt = "exec cmd:" + " ".join(cmd_list)

print(cmd_prompt)

print("=" * len(cmd_prompt))

if child_list:

child = subprocess.Popen(cmd_list, close_fds=True, stdin=child_list[-1].stdout,

stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)

else:

child = subprocess.Popen(cmd_list, close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)

child_list.append(child)

if not child_list:

return ""

stdoutdata, stderrdata = child_list[-1].communicate()

if child_list[-1].returncode != 0:

stderrdata = stderrdata.decode(get_coding(stderrdata))

print("error info", child_list[-1].returncode, stderrdata)

return stderrdata

stdoutdata = stdoutdata.decode(get_coding(stdoutdata))

print(stdoutdata)

return stdoutdata

def get_part_used(first_part_dev_name):

"""

得到分区的已经使用量

:param first_part_dev_name:

:return:

"""

# 挂载分区

data = exec_shell_cmd(f"df -k")

src_mount_path_name = None

for line in data.split("\n"):

line = line.strip()

if not line:

continue

line = line.split()

if not line:

continue

if line[0] == first_part_dev_name:

src_mount_path_name = line[-1].strip()

break

if not src_mount_path_name:

src_mount_path_name = "/mnt/mysrc_" + first_part_dev_name.replace("/", "_")

exec_shell_cmd(f"mkdir -p {src_mount_path_name}")

exec_shell_cmd(f"mount -t ext4 {first_part_dev_name} {src_mount_path_name}")

data = exec_shell_cmd(["df", "-k"])

if data is None:

return 0

line = ""

for line in data.split("\n"):

line = line.strip()

if line.find(first_part_dev_name) > -1:

break

if len(line) < len(first_part_dev_name):

return 0

line = line.split()

if len(line) < 4:

return 0

used_bytes = int(line[2])*1024

used_bytes = int(used_bytes * 1.2 + 32 * 1024 * 1024)

return used_bytes

def copy_sys_32m(dev_name, bak_part_image_name):

"""

拷贝磁盘的前32M

:param dev_name:

:param bak_part_image_name:

:return:

"""

return ["dd", f"if=/dev/{dev_name}", f"of={bak_part_image_name}", "bs=1M", "count=32"]

def get_src_part_info(disk_dev_name, disk_used_size):

"""

获得分区信息

:param disk_dev_name:

:param disk_used_size:

:return:

"""

# 分区

src_part_info = OrderedDict()

data = exec_shell_cmd(f"fdisk -l {disk_dev_name}")

first_part = True

for line in data.split("\n"):

line = line.strip()

if line.find(disk_dev_name) != 0:

continue

line = line.split()

if len(line) < 3:

continue

if first_part:

line[2] = (disk_used_size - 32 * 1024 * 1024) // 512

first_part = False

src_part_info[line[0]] = line[:3]

# 分区name

data = exec_shell_cmd(f"parted --script {disk_dev_name} print ")

need_process = False

for line in data.split("\n"):

line = line.strip()

if not need_process and line.find("End") > 0 and line.find("Name") > 0:

need_process = True

continue

if not need_process:

continue

line = line.split()

if len(line) < 5:

continue

part_info = src_part_info[disk_dev_name + line[0]]

part_info.append(line[0])

part_info.append(line[-1])

for info_id in range(1, len(part_info) - 1):

if isinstance(part_info[info_id], str):

part_info[info_id] = int(part_info[info_id])

return src_part_info

def create_new_image(out_img_name, disk_used_size, disk_part_info):

"""

创建一个新的镜像

:param out_img_name:

:param disk_used_size:

:param disk_part_info:

:return:

"""

new_disk_used_size = (int(disk_used_size) // 1024 + 1) // 1024 + 1

exec_shell_cmd(f"dd if=/dev/zero of={out_img_name} bs=1M count={new_disk_used_size}")

exec_shell_cmd(f"parted {out_img_name} --script -- mklabel GPT")

for _, part_info in disk_part_info.items():

if part_info[3] == "1":

cmd_str = f"parted --script {out_img_name} mkpart {part_info[4]} ext4 {part_info[1]}s {part_info[2]}s"

else:

cmd_str = f"parted --script {out_img_name} mkpart {part_info[4]} {part_info[1]}s {part_info[2]}s"

# print(cmd_str)

exec_shell_cmd(cmd_str)

return True

def copy_1m_32m(bak_part_image_name, new_image_name, disk_part_info):

"""

拷贝一个文件的1M到31M数据

:param bak_part_image_name:

:param new_image_name:

:param disk_part_info:

:return:

"""

min_part_start = min([part_info[1] for _, part_info in disk_part_info.items()]) * 512

# 将前几个分区的数据拷贝到新的镜像文件

space_24m = 24 * 1048576

print(f"copy {bak_part_image_name}/{min_part_start}:{space_24m} {new_image_name}/{min_part_start}:{space_24m}")

with open(bak_part_image_name, "rb") as src_image:

src_image.seek(min_part_start)

data = src_image.read(space_24m - min_part_start)

if not data:

return False

with open(new_image_name, "rb+") as dest_image:

dest_image.seek(min_part_start)

dest_image.write(data)

return True

def mount_data_part(src_part_dev_name, new_image_name):

"""

挂载img的APP分区

:param src_part_dev_name:

:param new_image_name:

:return:

"""

img_dev_name = exec_shell_cmd(f"losetup --show -f {new_image_name}").strip()

data = exec_shell_cmd(f"kpartx -av {img_dev_name}")

mapper_part_name = "/dev/mapper/" + data.split("\n")[0].strip().split()[2].strip() # /dev/mapper/loop2p1

exec_shell_cmd(f"mkfs.ext4 {mapper_part_name}")

dest_mount_path_name = "/mnt/mydest_" + mapper_part_name.replace("/", "_")

exec_shell_cmd(f"mkdir -p {dest_mount_path_name}")

exec_shell_cmd(f"mount -t ext4 {mapper_part_name} {dest_mount_path_name}")

data = exec_shell_cmd(f"df -k")

src_mount_path_name = None

for line in data.split("\n"):

line = line.strip()

if not line:

continue

line = line.split()

if not line:

continue

if line[0] == src_part_dev_name:

src_mount_path_name = line[-1].strip()

break

if not src_mount_path_name:

src_mount_path_name = "/mnt/mysrc_" + src_part_dev_name.replace("/", "_")

exec_shell_cmd(f"mkdir -p {src_mount_path_name}")

exec_shell_cmd(f"mount -t ext4 {src_part_dev_name} {src_mount_path_name}")

return img_dev_name, src_mount_path_name, dest_mount_path_name

def umount_data_part(img_dev_name, src_mount_path_name, dest_mount_path_name):

"""

卸载img的APP分区

:param img_dev_name:

:param src_mount_path_name:

:param dest_mount_path_name:

:return:

"""

exec_shell_cmd(f"umount {src_mount_path_name}")

exec_shell_cmd(f"umount {dest_mount_path_name}")

exec_shell_cmd(f"kpartx -dv {img_dev_name}")

exec_shell_cmd(f"losetup -d {img_dev_name}")

return True

def copy_app_part(src_part_dev_name="/dev/sdc1", new_image_name="/media/fzyzm/Y_LINUX_BAK/jetson_20190630_154532.img"):

"""

备份APP分区

:param src_part_dev_name:

:param new_image_name:

:return:

"""

img_dev_name, src_mount_path_name, dest_mount_path_name = mount_data_part(src_part_dev_name, new_image_name)

exec_pip_cmd(f"dump -0uaf - {src_mount_path_name}", f"restore -rf -", cwd=dest_mount_path_name)

# rm

exec_shell_cmd(f"rm -fr {dest_mount_path_name}/proc/*")

exec_shell_cmd(f"rm -fr {dest_mount_path_name}/tmp/*")

exec_shell_cmd(f"rm -fr {dest_mount_path_name}/lost+found/*")

exec_shell_cmd(f"rm -fr {dest_mount_path_name}/media/*")

exec_shell_cmd(f"rm -fr {dest_mount_path_name}/mnt/*")

exec_shell_cmd(f"rm -fr {dest_mount_path_name}/run/*")

exec_shell_cmd(f"rm -fr {dest_mount_path_name}/dev/*")

exec_shell_cmd(f"rm -fr {dest_mount_path_name}/sys/*")

exec_shell_cmd(f"rm -fr {dest_mount_path_name}/var/*")

umount_data_part(img_dev_name, src_mount_path_name, dest_mount_path_name)

return True

def main():

# 设置变量初始值

disk_name = "sdc"

out_path = "/media/fzyzm/S_LINUX_OTHER/my_temp/"

now_time_str = time.strftime("%Y%m%d_%H%M%S", time.localtime())

# 从命令行获取参数

if len(sys.argv) >= 2:

disk_name = sys.argv[1]

if len(sys.argv) >= 3:

out_path = sys.argv[2]

# 备份磁盘的前32M

bak_part_image_name = os.path.join(out_path, f"{disk_name}_{now_time_str}.img")

exec_shell_cmd(copy_sys_32m(disk_name, bak_part_image_name))

# 磁盘设备序号处理

disk_dev_name = f"/dev/{disk_name}"

first_part_dev_name = f"{disk_dev_name}1"

# 新镜像名称处理

new_image_name = os.path.join(out_path, f"jetson_{now_time_str}.img")

# 获取磁盘已使用空间

disk_used_size = get_part_used(first_part_dev_name)

print("use disk space:", disk_used_size)

# 创建新分区

disk_part_info = get_src_part_info(disk_dev_name, disk_used_size)

create_new_image(new_image_name, disk_used_size, disk_part_info)

copy_1m_32m(bak_part_image_name, new_image_name, disk_part_info)

copy_app_part(first_part_dev_name, new_image_name)

return

if __name__ == "__main__":

if len(sys.argv) == 1:

print("usage: back_jetson.py disk_device_name backup_dest_path_name")

print("example: back_jetson.py sdc /media/fzyzm/S_LINUX_OTHER/my_temp/")

main()


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部