osnosn

  博客园 :: 首页 :: 博问 :: 闪存 :: :: 联系 :: 订阅 订阅 :: 管理 ::

Debian11_手工制作deb安装包_过程和例子_dpkg-gencontrol

转载注明来源: 本文链接 来自osnosn的博客,写于 2023-08-10.

参考

需求

  • 想给 armbian 系统更换/升级内核。
    内核包括 image,kmod 和 headers,文件很多,需要放置在不同的系统目录中。
  • 但网上找到别人编译好的内核,是 tar.gz 的压缩包。
    安装过程麻烦。解压后,要copy到指定位置。时间久了,就忘了copy到哪里了。
    不方便安装,不方便卸载。
  • 想把这些文件,打包成一个 deb 安装包。 用 "dpkg -i" 安装,用 "dpkg -r" 卸载。就方便多了。

制作 deb 包

  • 按照参考中的帖子,制作 deb 包,似乎是不难。
    无非就是两步。
    • 准备 deb 包内的文件目录。
    • 创建"控制文件",即 "DEBIAN/" 目录。

碰到的问题

  • "控制文件",最重要的就是 "control" 文件。
    网上的教程都是让你手工自己创建,手工自己填内容。
  • 但是,里头有个 "Installed-Size:" 就不知道怎么填了。网上的各种教程都回避了这个问题。
  • 搜到一个帖子,【如何正确设置deb包的安装大小?】提到,如果设置不正确,安装时会报错。
    尝试用 "du -s" 命令计算目录的大小,又不正确。
    里头有个回复,说,应该用 dpkg-gencontrol 命令生成,它会自动计算 Installed-Size 。
    这个帖子也提到【How to properly set installed-size for deb package】。
  • 邮件列表中,2011年有提出【dpkg-gencontrol should use du --apparent-size】,
    测试du --apparent-size -ks deb目录,结果也不对,不过很接近了。
    查看 【dpkg-gencontrol 的 perl 源码】,发现是用 perl循环自己加出来的结果。
    所以,还是老老实实用 dpkg-gencontrol 生成 "Installed-Size:" 吧。
  • 几经折腾,终于搞明白。
    dpkg-gencontrol 需要两个关键的配置文件,"debian/changelog" 和 "debian/control" 。
  • 而这两个配置文件,格式还挺复杂。
    changelog 第一行的名称,要和 control 第一行的 "Source:" 匹配。
  • 参考官方文档,【本贴的前面】。在当前目录上,建立了这两个文件。
    这时候,执行 dpkg-gencontrol 命令,就不报错了,能给deb目录生成控制文件了。
  • 跨架构: 如果你在 amd64 架构的 debian下,用 dpkg-gencontrol 生成 arm64 架构的 control文件。还是会报错。
    解决办法是,在命令前,用一个环境变量指定cpu架构。
    DEB_HOST_ARCH=arm64 dpkg-gencontrol -P...
  • 至此,制作 deb 就没什么障碍了。
  • 至于,想在 control 结果文件中,填写什么项目。
    可以找一个现成的 deb 包,用 dpkg -e xxxx.deb 把它的控制文件解出来。
    照着别人的内容,慢慢调整自己的输出。
  • "控制文件" 调整满意后。
    dpkg-deb -b ... 打包自己的 deb 即可。
    如果是非 root 身份打包,按需加上 --root-owner-group 参数 (如果希望所有文件/目录的 owner 是 root)。
  • 备注:
    dpkg-deb 命令,在 apt install dpkg 中。
    dpkg-gencontrol 命令,在 apt install dpkg-dev 中。

最终写了个脚本

以下是完整的例子

  • 此例子是为了【Armbian_N1_笔记--试试别人的内核】帖子而做的。
  • 去 【ophub/kernel_dev】下载 "5.15.125.tar.gz",约 89MB。
  • 脚本没有获取命令行参数。内核版本号,写在脚本的第二行,需要的时候,手工修改一下 "version=" 即可。
    脚本执行后,会在当前目录创建几个目录,
    "debian/", "img_root/", "head_root/", "5.15.125/"(解压 tar.gz 创建的目录)。
    最后生成两个 deb 文件。脚本执行结束后,上述的 4 个目录就没用了,可以删除。
  • 这个脚本,创建"文件目录"部分,参考了 ophub 内核升级脚本 【armbian-update】 "update_kernel()" 函数的安装步骤。
    #!/bin/bash
    
    version=5.15.125
    # export DEB_HOST_ARCH=arm64  #如果机器的cpu架构,不是arm64,则取消这行的注释
    
    #为了给N1更换kernel,但ophub的kernel是以tar.gz发布,需要打包为 deb文件,方便安装。
    
    #=== 解压tar.gz压缩包 ===
    tar zxf "${version}.tar.gz" -C ./
    kernel_boot="$(basename $(ls ${version}/boot-${inputs_kernel}*.tar.gz 2>/dev/null | head -n 1))"
    kernel_name="${kernel_boot:5:-7}"
    
    #=== 创建 源码包控制文件,Source package control files ===
    mkdir -p debian
    cat <<EOF  > debian/changelog
    linux-image-and-headers-amlogic-s905d-osn (0.1) focal; urgency=low
    
      * Custom built Linux kernel.
    
     -- System Administrator <root@localhost.localdomain>  Fri, 15 Aug 2023 10:20:30 -0000
    EOF
    cat <<EOF  > debian/control
    Source: linux-image-and-headers-amlogic-s905d-osn
    Maintainer: System Administrator osn <root@localhost.localdomain>
    
    Package: linux-image-${kernel_name}-amlogic-s905d-osn
    Architecture: arm64
    Section: kernel
    Priority: optional
    Homepage: https://www.kernel.org/
    Description: Linux kernel, version ${kernel_name}-amlogic-s905d-osn
     This package contains the Linux kernel, modules and corresponding other files.
    
    Package: linux-headers-${kernel_name}-amlogic-s905d-osn
    Architecture: arm64
    Section: kernel
    Priority: optional
    Homepage: https://www.kernel.org/
    Description: Linux kernel headers for ${kernel_name}-amlogic-s905d-osn on arm64
     This package provides kernel header files for ${kernel_name}-amlogic-s905d-osn on arm64.
     This is useful for people who need to build external modules
    EOF
    #==============image.deb=========
    IMAGE_ROOT=img_root
    mkdir -p "${IMAGE_ROOT}"
    # --- boot ---
    boot_dir=${IMAGE_ROOT}/boot
    mkdir -p "${boot_dir}"
    tar zxf "${version}/boot-${kernel_name}.tar.gz" -C ${boot_dir}
    #mv ${boot_dir}/uInitrd-${kernel_name}  ${boot_dir}/bak.uInitrd-${kernel_name} #备份原来的uInitrd
    #cp ${boot_dir}/vmlinuz-${kernel_name}  ${boot_dir}/zImage
    rm -f ${boot_dir}/{uInitrd*,initrd.img*}  #去掉没用的文件
    # --- dtb ---
    dtb_dir=${boot_dir}/dtb-${kernel_name}/
    mkdir -p "${dtb_dir}"
    tar zxf "${version}/dtb-amlogic-${kernel_name}.tar.gz" -C ${dtb_dir}
    ls ${dtb_dir}/* | grep -v s905d |xargs rm --   #去掉非s905d的dtb文件
    
    # --- kmod ---
    kmod_dir=${IMAGE_ROOT}/usr/lib/modules
    mkdir -p "${kmod_dir}"
    tar zxf "${version}/modules-${kernel_name}.tar.gz" -C ${kmod_dir}
    rm -f ${kmod_dir}/${kernel_name}/{build,source}  #去掉两个链接,放到headers中去
    
    # --- DEBIAN 控制文件和脚本 ---
    mkdir -p "${IMAGE_ROOT}/DEBIAN"
    touch ${IMAGE_ROOT}/DEBIAN/md5sums
    cat <<EOF  > ${IMAGE_ROOT}/DEBIAN/postinst
    #!/bin/sh
    set -e
    # Pass maintainer script parameters to hook scripts
    export DEB_MAINT_PARAMS="\$*"
    # Tell initramfs builder whether it's wanted
    export INITRD=Yes
    test -d /etc/kernel/postinst.d && run-parts --arg="${kernel_name}" --arg="/boot/vmlinuz-${kernel_name}" /etc/kernel/postinst.d
    exit 0
    EOF
    cat <<EOF  > ${IMAGE_ROOT}/DEBIAN/postrm
    #!/bin/sh
    set -e
    # Pass maintainer script parameters to hook scripts
    export DEB_MAINT_PARAMS="\$*"
    # Tell initramfs builder whether it's wanted
    export INITRD=Yes
    test -d /etc/kernel/postrm.d && run-parts --arg="${kernel_name}" --arg="/boot/vmlinuz-${kernel_name}" /etc/kernel/postrm.d
    exit 0
    EOF
    cat <<EOF  > ${IMAGE_ROOT}/DEBIAN/preinst
    #!/bin/sh
    set -e
    # Pass maintainer script parameters to hook scripts
    export DEB_MAINT_PARAMS="\$*"
    # Tell initramfs builder whether it's wanted
    export INITRD=Yes
    test -d /etc/kernel/preinst.d && run-parts --arg="${kernel_name}" --arg="/boot/vmlinuz-${kernel_name}" /etc/kernel/preinst.d
    exit 0
    EOF
    cat <<EOF  > ${IMAGE_ROOT}/DEBIAN/prerm
    #!/bin/sh
    set -e
    # Pass maintainer script parameters to hook scripts
    export DEB_MAINT_PARAMS="\$*"
    # Tell initramfs builder whether it's wanted
    export INITRD=Yes
    test -d /etc/kernel/prerm.d && run-parts --arg="${kernel_name}" --arg="/boot/vmlinuz-${kernel_name}" /etc/kernel/prerm.d
    exit 0
    EOF
    chmod +x ${IMAGE_ROOT}/DEBIAN/{postinst,postrm,preinst,prerm}  #给4个脚本执行权限
    dpkg-gencontrol  -P${IMAGE_ROOT} -plinux-image-${kernel_name}-amlogic-s905d-osn -v${kernel_name}-amlogic-s905d-osn-1 -DSource=linux-upstream
    # --- 打包 deb ---
    dpkg-deb --root-owner-group -b ${IMAGE_ROOT} linux-image-${kernel_name}-amlogic-s905d-osn_arm64.deb
    #==============image.deb, finished=========
    
    # exit  #不制作headers.deb, 就退出了
    
    #==============headers.deb=========
    HEADER_ROOT=head_root
    mkdir -p "${HEADER_ROOT}"
    header_dir=${HEADER_ROOT}/usr/src/linux-headers-${kernel_name}
    mkdir -p "${header_dir}"
    tar zxf "${version}/header-${kernel_name}.tar.gz" -C ${header_dir}
    
    kmod_dir=${HEADER_ROOT}/usr/lib/modules
    mkdir -p "${kmod_dir}/${kernel_name}"
    ln -sf /usr/src/linux-headers-${kernel_name} ${kmod_dir}/${kernel_name}/build
    
    # --- DEBIAN 控制文件 ---
    mkdir -p "${HEADER_ROOT}/DEBIAN"
    touch ${HEADER_ROOT}/DEBIAN/md5sums
    dpkg-gencontrol  -P${HEADER_ROOT} -plinux-headers-${kernel_name}-amlogic-s905d-osn -v${kernel_name}-amlogic-s905d-osn-1 -DSource=linux-upstream
    # --- 打包 deb ---
    dpkg-deb --root-owner-group -b ${HEADER_ROOT} linux-headers-${kernel_name}-amlogic-s905d-osn_arm64.deb
    #==============headers.deb, finished=========
    
  • 在准备deb的文件中,如果有 "链接文件",要用 ln -sf /usr/src/... 链接文件
    要按照 安装完deb后的情况,设置 "链接文件"。ln -sf 前面的参数路径,可以不存在。
  • 在 N1 上执行这个脚本。耗时 2m55s ~ 3m08s 生成两个 deb 文件。文件还挺大的。
    7.2M  linux-headers-5.15.125-ophub-amlogic-s905d-osn_arm64.deb
     64M  linux-image-5.15.125-ophub-amlogic-s905d-osn_arm64.deb
    
    修改了一下脚本,删除 initrd,uInitrd 之后,image.deb体积小了好多。
     26M  linux-image-5.15.125-ophub-amlogic-s905d-osn_arm64.deb
    
  • 拿去armbian中,安装顺利。卸载也顺利。
  • 这个脚本的逻辑,对于制作 linux-image.deb 还有改进空间。
    • 在 preinst 中,先备份 /boot/ 中的 zImage, uInitrd, uEnv.ini。
    • 直接把 vmlinuz-xxx 拷贝为 zImage,就不用手工去做了。
    • 在 dtb-5.15.125-ophub/ 中去掉不相干的 dtb文件,只留下 s905d 的 dtb文件。
    • 解压到 boot/ 目录的 uInitrd-xxx, initrd.img-xxx 是没用的,可以删除。
      因为安装完成后,会被重新生成。
    • 在 postinst 中,直接修改 uEnv.ini 文件。
      用 sed 把所有的 "dtb_name=" 的行,注释掉,然后再添加一行正确路径的 "dtb_name="。

----end----


转载注明来源: 本文链接 https://www.cnblogs.com/osnosn/p/17622874.html
来自 osnosn的博客 https://www.cnblogs.com/osnosn/ .


posted on 2023-08-11 14:37  osnosn  阅读(655)  评论(0编辑  收藏  举报