在鸿蒙 PC 上使用 apt 安装 Debian 软件包(非虚拟机、非容器)
1 前言
在上一篇文章《把 glibc 移植到鸿蒙 PC 上:它能用来做什么》中,我展示了将 glibc 移植到鸿蒙 PC 上的可行性,这让一批依赖 glibc 的 Linux 程序能直接在鸿蒙 PC 上跑起来。
移植完之后,我想做个更激进的验证:既然 glibc 程序能跑,那发行版的包管理器呢?能不能不止跑单个程序,而是直接 apt install Debian 官方仓库里的软件包?
基于这个目标,我做出了 PreLinux 这个开源项目。它能把一整个发行版装进你指定的前缀目录,用发行版自己的包管理器安装软件,不需要 root,不需要虚拟机,也不需要容器。
项目地址:https://github.com/hqzing/prelinux
2 先看效果
在 HiShell 中操作,几步就能完成安装:
# 下载安装脚本
curl -fsSLO https://github.com/hqzing/prelinux/releases/latest/download/install.sh
# 执行安装脚本
# 默认安装 debian:12 到 ~/prelinux,脚本从 GitHub 下载文件,注意网络连通性
sh install.sh
# 进入实例
source ~/prelinux/debian12/env.sh
# 用 apt 装软件
apt update
apt install -y tree
tree -L 1 /
tree -L 1 / 输出的就是实例自己的根目录:
/
|-- bin -> usr/bin
|-- boot
|-- dev
|-- etc
...
`-- var
19 directories, 0 files
这个 / 不是宿主机的根目录,而是 ~/prelinux/debian12。apt、dpkg 的数据库,/etc/apt、/var/lib/dpkg、/usr 全部在这个目录里面,所以 apt 能像在真机上一样工作。仓库的 GPG 校验、依赖解析、维护脚本都没有关掉。
source 只影响当前这个 shell。想回到宿主的普通环境,可以开一个新终端。
所有内容都在 ~/prelinux 下,卸载时删掉这个目录即可。
如果需要指定前缀,可通过 PRELINUX_HOME 变量进行配置:
PRELINUX_HOME=/opt/prelinux sh install.sh
在实例内换源,操作与普通的 Linux 环境无异:
sed -i 's|http://deb.debian.org/debian|http://mirrors.aliyun.com/debian|;
s|http://deb.debian.org/debian-security|http://mirrors.aliyun.com/debian-security|' \
/etc/apt/sources.list.d/debian.sources
apt update
apt 在使用过程中会打印一条
Setting TIOCSCTTY ... failed,这是鸿蒙内核拒绝了那个 ioctl,apt 会继续执行,忽略即可。
3 它不是虚拟机,也不是容器
把它和几种常见方案放在一起比较,差别主要在这几个地方:要不要自带内核、要不要 root、和宿主系统是什么关系。
| 方案 | 需要一个内核 | 需要 root | 和宿主的关系 |
|---|---|---|---|
| 虚拟机 | 是 | 否 | 完全隔离 |
| 容器 | 复用宿主内核 | 通常需要 | 靠 namespace 隔离 |
| proot | 复用宿主内核 | 否 | 靠 ptrace 拦截系统调用 |
| PreLinux | 复用宿主内核 | 否 | 靠改过的 glibc 改写路径 |
原理上就一句话:实例里的程序跑在一份改过的 glibc 上,这份 glibc 把 FHS 路径重定向进实例目录。
/bin、/lib、/usr、/etc、/var指向~/prelinux/<发行版>里的对应目录;/proc、/sys、/dev直通给宿主;- 非 FHS 路径(比如鸿蒙的
/storage、/system)原样直通。
包管理器把实例目录当成自己的 /,所以 apt 这类普通 Linux 程序不需要任何改造就能工作。
还有一个绕不过去的环节是签名。鸿蒙 PC 强制校验可执行文件和 .so 的代码签名,未签名的二进制无法运行,而软件包里的二进制原本都是给发行版用的,既没有签名,解释器路径也不指向实例。PreLinux 的做法是让包管理器在解包时自动处理:dpkg 的落盘路径上挂了钩子,每装完一个可执行文件就改写解释器路径并立即签名。所以 apt install 装完的软件可以直接运行,用户不需要再手动签一次。
4 装几个常用的软件
PreLinux 不只能跑 tree 这种小工具,下面这几个稍微复杂一点的软件也能正常工作:
apt update
apt install -y curl python3
# git 会推荐 openssh-client,它要创建系统用户,实例里这一步会失败,因此跳过它
apt install -y --no-install-recommends git
# 装完直接运行
curl -sI https://www.baidu.com | head -3
python3 -c "import sys; print(sys.version)"
git clone --depth 1 https://github.com/git/git
curl 能正常发起 HTTPS 请求,说明 OpenSSL、CA 证书、DNS 解析这条链在实例里都是通的;python3 能启动,说明解释器和它的整套共享库也正常;git 能从 GitHub 克隆一个开源仓库,说明它依赖的 libcurl、perl 以及证书链也都完整可用。


5 目前的限制
这套方案的边界由它的实现方式决定,以下是一些主要的限制:
- 静态链接的程序不走映射。Go 程序、部分 musl 静态工具直接访问宿主真实路径,看到的是宿主的文件系统。
- 实例内不能编译。任何语言都不行:动态 ELF 要 relocate 才能在本实例运行,静态 ELF 又不过映射。软件来源是发行版预编译包,pip 只能装带 wheel 的包。
- 不能升级 glibc。实例里的 glibc 是改过的,升级会破坏路径映射,所以 apt 会跳过
libc6。 - 实例不能移动或改名。实例根写死进了 glibc 和每个可执行文件的解释器路径,需要另一个位置就重新导入一个实例。
- 需要特权的操作不可用。mount、namespace、cgroup、setuid、加载内核模块都不行,没有图形界面。
- 要创建系统用户或组的软件包可能装不上。内核拒绝 audit netlink 连接,
groupadd、useradd会失败并让 postinst 返回错误,可以加--no-install-recommends跳过这类推荐依赖。 - 权限和属主信息不可信。hmdfs 忽略 chmod 也没有扩展属性,
ls -l显示的模式和实际行为不一致;文件内容、大小、时间戳是正常的。
6 结语
PreLinux 和 Harmonybrew 解决的不是同一个问题。
Harmonybrew 把软件包原生适配到鸿蒙(musl 工具链、原生构建),面向日常使用。PreLinux 则是一次边界测试,探索鸿蒙对 Linux 二进制生态的兼容能做到多深。
就如上文所说,它存在诸多限制,并不适合日常开发。第 5 节那些限制里,随便一条都会在长期使用中变成麻烦:不能编译、不能升级 glibc、实例不能移动、权限元数据不可信。
如果你是急需使用发行版仓库中的某个软件,可以把它当作一个临时的、可用的手段。如果你想要一套稳定的开发环境,Harmonybrew 才是当前最佳的选择。
更多推荐




所有评论(0)