记录一次失败了的在 Manjaro 系统安装 deb 包的过程

发布于 2022/8/18, 编辑于 2022/11/5

deb 包是由软件 apt 包管理系统管理的的包, 常用于 Debian 系统的软件安装, pacman 系的系统无法直接安装 deb 包软件. 一般而言, 可以借助 debtap 这类工具来二次打包为 tar.zst 包, 再由 pacman 进行安装. 但是这种二次打包的方式并不为人所推荐, 即使是 debtap 的作者也不推荐利用这种方式来转包. 本文记录了笔者的一次转包过程 ( 结果是失败了 ), 探讨了这种转包方式的: 原理 / 可能遇到的问题 / 兼容性的处理

关于

转包 aTrust.deb 的可行性分析

aTrust 是深信服的一款产品, 主要用于在电脑中建立公司的工作环境网络, 类似 openvpn, Linux 版本只提供了 deb 包

我的需求是在我的工作环境 Manjaro 系统中装上该软件

aTrust.deb 官方兼容性

compatibility

上图 ( 来源 ) 可见, 官方支持的 Linux 系统只有 UOS 和 麒麟, 而 UOS 来自于 deepin 魔改, 可见 deepin 也支持

deb 包和 tar.zst 包

// sudo dpkg --install foo.deb
// foo.deb 解包后:
deb
├── DEBIAN
│   ├── control
│   ├── postinst
│   ├── postrm
│   ├── preinst
│   └── prerm
└── (others)
  • deb: 该包中的
    • DEBIAN 文件夹就是存放安装信息和安装脚本的地方
      • control 记录了包信息
      • postinst / postrm 等顾名思义是 hook, 里面是具体的脚本代码
      • 另外 DEBIAN 文件夹里可以放置自定义 sh 脚本文件, 供给 hook 调用
    • (others) 指待安装到系统的文件如 /opt/Something / /usr/bin/MyApp
// sudo pacman -U foo.tar.zst
// foo.tar.zst 解包后:
tar.zst
├── .INSTALL
├── .MTREE
├── .PKGINFO
└── (others)
  • tar.zst: 该包

    • .PKGINFO 是存放安装信息
    • .MTREE 我也不太理解, 请看这里
    • .INSTALL 同样是脚本, 里面的代码结构描述了和上面 deb 包的 hook 脚本一样的钩子

      post_install() {
        echo "do something" # 此处的代码理论上与 deb 中的 postinst 一致
      }
      
      pre_remove() {
        echo "do something" # 此处的代码理论上与 deb 中的 postrm 一致
      }
    • (others) 指待安装到系统的文件如 /opt/Something / /usr/bin/MyApp

由上文可得知, 虽然两种打包系统的安装包文件结构不同, 但是总体的安装包的设计思路还是十分类似的:

  • 安装信息 ( 包名 / 依赖等 )
  • 安装的生命周期

debtap 可以帮我们直接把 deb 包转成一个模板化的 tar.zst 包, 即:

  1. 按照转换规则进行转化 ( 例如把 postins 脚本的代码注入进 .INSTALLpost_install 函数中 )
  2. 以及帮我们解决依赖问题 ( 本文不提 )

这种方法的坑点如下:

  1. 不会打包 DEBIAN 中的内置脚本. 例如有一种情况: DEBIAN 中写有自定义脚本 helpers.sh, 钩子脚本 post_install 会调用这个 helpers.sh 来帮忙安装. 那么 debtap 在转的时候会无视这些自定义脚本, 统统不会打包进 tar.zst
  2. debian 和 arch 系统结构的差别可能会导致文件复制的时候找不到路径

因此只要先用 debtap 把 deb 包初步转成 tar.zst 包, 再根据需求修改里面的 .INSTALL 代码, 理论上可以实现本次需求

转包过程

准备

  • aTrust.deb
  • debtap
  • dpkg

解包 deb

这一步主要是查看源 deb 的打包脚本和取得 debtap 不会帮忙打包的冗余文件

mkdir -p extract/DEBIAN && dpkg -X aTrust.deb ./extract && dpkg -e aTrust.deb ./extract/DEBIAN

然后获得文件夹 extract, 里面就是源 deb 包的安装文件和脚本

debtap 转包

利用 debtap 初步转包

sudo debtap -u # 更新库
debtap aTrust.deb

过程中要求输入包名

debtap 会帮你分析出哪个依赖包你当前的系统不满足, 然后要求你编辑依赖信息, 你可以根据自己的需求进行删除

例如 aTrust 要求一个 deepin 的环境监测包 deepin-elf-verify, 根据博文 deepin-elf-verify 究竟是何物? 可知 deepin-elf-verify 为空包, 于是直接从依赖中删掉

最终得到 tar.zst 包 aTrust.pkg.tar.zst

然后解开他: mkdir pkg && cp aTrust.tar.zst ./pkg && cd ./pkg && tar -I zstd -xvf aTrust.pkg.tar.zst

得到 tar.zst 的所有文件和脚本

对比脚本

分别对比 deb 包里和 tar.zst 包里的钩子脚本

参数

首先发现 deb 的脚本中大量存在参数的获取, 例如脚本路径

SCRIPT_PATH=$(dirname "$0")

但是 pacman 的安装是没有参数传递的, 因此需要改造, 这里我直接写死了路径:

SCRIPT_PATH=/home/MyPath

同理, 所有的需要参数的地方都被我写死为具体的值

未被打包的文件

同时也发现了 deb 包中有几个 sh 脚本未被 debtap 打包进 tar.zst 中, 于是观察这些脚本被调用的方式, 发现是钩子直接调用了同级目录的脚本: sh -c ./xxx.sh, 于是我把这些类似的调用都改成了 sh -c ~/Desktop/aTrust/sh/xxx.sh 这样的形式, 也就是固定他的调用路径, 然后把这些脚本放到桌面中: ~/Desktop/aTrust/sh/, 然后给执行权限: chmod +x ~/Desktop/aTrust/sh/

重新打包

重新打包 deb 包得到 atrust2.deb

dpkg -b ./extract aTrust2.deb

再次转包

debtap aTrust2.deb

然后同样和上面一样也是删掉依赖: deepin-elf-verify, 然后得到 aTrust2.pkg.tar.zst, 安装:

sudo pacman -U aTrust2.pkg.tar.zst

结果

结果和一开始相比果然有了变化:

  1. 安装 log 显示能进行最后一步的安装了, 一开始因为脚本缺失的原因没有走到最后一步
  2. 能启动 aTrust 的 GUI 界面, 一开始点击启动没有任何变化

但是从本质上来说, 和一开始比也没有不同: 同样无法启动代理. 这一点我看 aTrust 的日志以后, 发现直接原因是有一个 (登录) 服务没法启动, 这点与我在 Ubuntu22 上的实验结果完全一样 (Ubuntu22 上也没成功, 但 Ubuntu20 成功了)

最后推测原因可能有两个:

  1. 依赖 deepin-elf-verify 被删除了, Ubuntu22 也是装不上这个包, 原因是 openssl 的版本问题
  2. openssl 的缘故, 我 manjaro 系统的 Ubuntu22 的 openssl 版本都是较新的, 考虑到这种代理软件多半需要调用 ssl 的库, 那么很可能就是这个原因

不过这些都是主观猜测, 没有任何证据

最终解决办法

最后起了一个 Ubuntu20 的虚拟机, 在虚拟机上启动 aTrust 后, 利用 tinyproxy + microsocks 给 host 机输出一个代理端口

点击这里前往 Github 查看原文,交流意见~

文档信息

版权声明:自由转载 - 非商用 - 非衍生 - 保持署名(创意共享3.0许可证