本文记录使用命令 OHOS_ARCH=aarch64 OHOS_ABI=arm64-v8a sh ./create-hnp.sh 构建 Proot 的完整过程,包括环境、构建链路、关键日志、常见问题与解决方案、产物验证与重建方法,便于复现与运维。

📖 Proot 简介

Proot(PRoot)是一个用户空间实现 chroot、mount --bind 和 binfmt_misc 的工具,允许用户在没有 root 权限的情况下运行需要 root 权限的程序。它通过 ptrace 系统调用拦截和重定向系统调用,实现文件系统隔离和权限模拟。

🎯 Proot 的作用与重要性

Proot 是现代容器化和沙箱环境的核心工具,提供了:

  • 无 root 权限的 chroot:在用户空间实现 chroot 功能,无需 root 权限
  • 文件系统隔离:创建独立的文件系统视图,隔离应用环境
  • 路径重定向:重定向文件系统路径,实现虚拟根文件系统
  • 权限模拟:模拟 root 用户权限,运行需要特权的程序
  • 容器化支持:为容器和沙箱环境提供基础支持
  • 跨平台兼容:支持多种架构和操作系统

🔧 Proot 核心特性

1. 用户空间实现
  • ptrace 拦截:通过 ptrace 系统调用拦截和修改系统调用
  • 无 root 权限:完全在用户空间运行,不需要 root 权限
  • 透明重定向:对应用程序透明,无需修改应用程序代码
2. 文件系统功能
  • chroot 模拟:模拟 chroot 功能,创建虚拟根目录
  • bind mount:模拟 mount --bind,绑定挂载目录
  • 路径转换:自动转换文件系统路径
  • 符号链接处理:正确处理符号链接和硬链接
3. 权限管理
  • 用户 ID 模拟:模拟 root 用户(UID 0)
  • 组 ID 模拟:模拟 root 组(GID 0)
  • 权限检查绕过:绕过需要 root 权限的检查
4. 容器化支持
  • 环境隔离:创建独立的运行环境
  • 资源限制:支持资源限制和配额
  • 网络隔离:可选的网络隔离功能
5. 应用场景
  • 容器运行时:作为轻量级容器运行时
  • 沙箱环境:创建安全的沙箱环境
  • 开发环境:隔离开发环境,避免污染系统
  • 软件包管理:支持软件包安装和依赖管理
  • 跨平台开发:在不同平台间移植应用

🚀 构建入口与环境

  • 📝 执行命令OHOS_ARCH=aarch64 OHOS_ABI=arm64-v8a sh ./create-hnp.sh
  • 🔧 入口脚本create-hnp.sh
    • 检查必需的环境变量 OHOS_ARCHOHOS_ABI
    • 导出 LC_CTYPETOOL_HOMEOHOS_SDK_HOME
    • 执行 make -C build-hnp
  • 📦 顶层构建build-hnp/Makefile
    • PKGS 变量定义需要构建的包列表(包含 proot
    • 通过 check-pkgs 机制自动检测 PKGS 变化并触发重新构建
    • 自动合并 external-hnp 目录下的外部 HNP 包
    • base.hnp 依赖所有包的 .stamp 和外部 HNP 包
    • 总目标 all: copy,打包 base.hnp 并拷贝到 entry/hnp/$(OHOS_ABI)

⚙️ Proot 包的构建配置

  • 📁 包目录build-hnp/proot/Makefile
    • 继承通用规则:include ../utils/Makefrag
    • 源码来源:GitHub 仓库 https://github.com/termux/proot.git
    • 版本:60485d2646c1e09105099772da4a20deda8d020d(特定提交)
  • 🔨 构建流程
    1. 下载源码:从 GitHub 克隆 proot 仓库(递归克隆子模块)
    2. 应用补丁:应用 ohos.patch 适配 OpenHarmony 平台
    3. 复制 queue.h:复制 queue.hsysroot/include(OpenHarmony 缺少 sys/queue.h)
    4. 构建 loader:先构建 loader(加载器)
    5. 构建 proot:构建主程序 proot
    6. 安装:复制二进制到 sysroot/bin
  • ⚙️ 关键配置参数
    • CC="$(CC)" - 使用交叉编译器
    • CFLAGS - 包含 sysroot、优化选项、安全选项(-D_FORTIFY_SOURCE=2
    • CPPFLAGS="-D__OHOS__" - 定义 OpenHarmony 平台宏
    • LDFLAGS - 链接器标志,包含 sysroot 和库路径
    • OBJCOPYREADELF - 使用交叉工具链的工具
    • PKG_CONFIG_PATH - 指向 sysroot 的 pkg-config 目录
  • 🔧 依赖
    • talloc:内存分配库(已在 PKGS 中)
    • queue.h:BSD 队列宏定义(已复制到 sysroot/include)

📋 关键日志与过程节点

  • 📥 下载与准备
    • 从 GitHub 克隆 proot 仓库(递归克隆子模块)
    • 检出特定提交:60485d2646c1e09105099772da4a20deda8d020d
    • 应用 ohos.patch 适配 OpenHarmony 平台
    • 复制 queue.hsysroot/include
  • 🔨 构建 loader
    • 进入 temp/proot/build 目录
    • 设置交叉编译环境变量
    • 执行 make -C ../src loader
    • 生成 loader 二进制文件
  • 🔨 构建 proot
    • 设置交叉编译环境变量(包含 -D__OHOS__
    • 执行 make -C ../src proot
    • 编译过程中出现一些警告(宏重定义、未使用变量),但不影响构建
    • 生成 proot 二进制文件
  • 📦 安装与打包
    • 复制 proot 二进制到 build/bin/
    • 复制到 sysroot/bin/
    • 完成 base.hnp 重打包,拷贝产物到 entry/hnp/arm64-v8a/
    • Proot 工具已成功打包到 base.hnp

✅ 产物验证

📦 检查打包文件

ls build-hnp/base.hnp  # 应存在
ls entry/hnp/arm64-v8a/*.hnp  # 应包含 base.hnp 与 base-public.hnp

🔍 检查二进制文件

# 检查 proot 二进制
ls -lh build-hnp/sysroot/bin/proot
file build-hnp/sysroot/bin/proot

# 检查 queue.h 头文件
ls -lh build-hnp/sysroot/include/queue.h

image-20251124094816177

✅ 构建验证结果

  • ✅ Proot 二进制已成功安装:
    • proot (995K) - 主程序二进制
  • ✅ 文件类型:ELF 64-bit LSB pie executable, ARM aarch64
  • ✅ 动态链接:interpreter /lib/ld-musl-aarch64.so.1
  • ✅ 包含调试信息:with debug_info, not stripped
  • ✅ queue.h 头文件已安装:sysroot/include/queue.h
  • ✅ 已打包到 base.hnp 中(1,018,328 字节)

💻 终端中执行的示例命令

image-20251124095123159

🔧 Proot 基本使用

1. 创建虚拟根文件系统
# 创建虚拟根目录
mkdir -p ~/proot-root

# 使用 proot 进入虚拟根目录
proot -r ~/proot-root /bin/sh

# 指定根目录并运行命令
proot -r ~/proot-root -w / /bin/ls -la

# 绑定挂载目录
proot -r ~/proot-root -b /data:/data /bin/sh
2. 模拟 root 用户
# 模拟 root 用户运行命令
proot -0 /bin/sh

# 模拟 root 用户并指定根目录
proot -0 -r ~/proot-root /bin/sh

# 模拟 root 用户并绑定目录
proot -0 -r ~/proot-root -b /data:/data /bin/sh
3. 路径绑定和重定向
# 绑定多个目录
proot -r ~/proot-root \
  -b /data:/data \
  -b /sdcard:/sdcard \
  /bin/sh

# 绑定文件
proot -r ~/proot-root \
  -b /etc/passwd:/etc/passwd \
  -b /etc/group:/etc/group \
  /bin/sh

# 绑定并设置工作目录
proot -r ~/proot-root \
  -w /home/user \
  -b /data:/data \
  /bin/sh
4. 环境变量设置
# 设置环境变量
proot -r ~/proot-root \
  -e HOME=/root \
  -e PATH=/usr/bin:/bin \
  /bin/sh

# 传递所有环境变量
proot -r ~/proot-root \
  -e "HOME=/root" \
  -e "SHELL=/bin/bash" \
  /bin/sh
5. 运行应用程序
# 运行 shell
proot -r ~/proot-root /bin/bash

# 运行特定命令
proot -r ~/proot-root /usr/bin/python3 --version

# 运行脚本
proot -r ~/proot-root /bin/sh script.sh

# 运行并传递参数
proot -r ~/proot-root /usr/bin/gcc -o test test.c

🔧 Proot 高级用法

6. 容器化应用
# 创建完整的容器环境
proot -r ~/proot-root \
  -0 \
  -w / \
  -b /data:/data \
  -b /sdcard:/sdcard \
  /bin/sh

# 运行容器化应用
proot -r ~/proot-root \
  -0 \
  /usr/bin/myapp

# 隔离网络(如果支持)
proot -r ~/proot-root \
  --networking=false \
  /bin/sh
7. 软件包管理
# 在虚拟环境中安装软件包
proot -r ~/proot-root \
  -0 \
  /usr/bin/apt-get install package-name

# 运行包管理器
proot -r ~/proot-root \
  -0 \
  /usr/bin/yum install package-name

# 更新软件包
proot -r ~/proot-root \
  -0 \
  /usr/bin/apt-get update
8. 开发环境隔离
# 创建开发环境
proot -r ~/dev-root \
  -0 \
  -w /workspace \
  -b ~/projects:/workspace/projects \
  /bin/bash

# 编译项目
proot -r ~/dev-root \
  -0 \
  -w /workspace/projects/myproject \
  /usr/bin/make

# 运行测试
proot -r ~/dev-root \
  -0 \
  -w /workspace/projects/myproject \
  /usr/bin/make test
9. 文件系统操作
# 创建目录结构
proot -r ~/proot-root \
  -0 \
  /bin/mkdir -p /usr/local/bin

# 复制文件
proot -r ~/proot-root \
  -0 \
  /bin/cp /source/file /dest/file

# 设置权限
proot -r ~/proot-root \
  -0 \
  /bin/chmod +x /usr/local/bin/script

# 创建符号链接
proot -r ~/proot-root \
  -0 \
  /bin/ln -s /usr/bin/python3 /usr/local/bin/python
10. 实际应用示例
# 运行 Python 环境
proot -r ~/python-root \
  -0 \
  -w / \
  -b /data:/data \
  /usr/bin/python3

# 运行 Node.js 应用
proot -r ~/node-root \
  -0 \
  -w /app \
  -b ~/projects:/app \
  /usr/bin/node app.js

# 运行编译工具链
proot -r ~/build-root \
  -0 \
  -w /workspace \
  -b ~/source:/workspace/source \
  /usr/bin/gcc -o output input.c

# 运行数据库服务
proot -r ~/db-root \
  -0 \
  -w /var/lib/db \
  -b /data/db:/var/lib/db \
  /usr/bin/mysqld

# 运行 Web 服务器
proot -r ~/web-root \
  -0 \
  -w /var/www \
  -b ~/html:/var/www/html \
  /usr/bin/nginx

# 创建完整的 Linux 环境
proot -r ~/linux-root \
  -0 \
  -w / \
  -b /data:/data \
  -b /sdcard:/sdcard \
  -e "HOME=/root" \
  -e "PATH=/usr/bin:/bin:/usr/sbin:/sbin" \
  /bin/bash

🧪 功能验证脚本

#!/bin/bash
# Proot 工具验证脚本

PROOT_BIN="build-hnp/sysroot/bin"
PROOT_INCLUDE="build-hnp/sysroot/include"

echo "=== Proot 工具验证 ==="

# 检查 proot 二进制
if [ -f "$PROOT_BIN/proot" ]; then
    echo "✓ proot: 存在"
    file "$PROOT_BIN/proot"
    echo "文件大小: $(ls -lh "$PROOT_BIN/proot" | awk '{print $5}')"
    echo "架构信息: $(file "$PROOT_BIN/proot" | grep -o "ARM aarch64")"
else
    echo "✗ proot: 缺失"
fi

# 检查 queue.h 头文件
echo ""
echo "=== 头文件验证 ==="
if [ -f "$PROOT_INCLUDE/queue.h" ]; then
    echo "✓ queue.h: 存在"
    echo "文件大小: $(ls -lh "$PROOT_INCLUDE/queue.h" | awk '{print $5}')"
    echo "前几行:"
    head -5 "$PROOT_INCLUDE/queue.h"
else
    echo "✗ queue.h: 缺失"
fi

# 检查依赖
echo ""
echo "=== 依赖验证 ==="
if [ -f "build-hnp/sysroot/lib/libtalloc.so" ]; then
    echo "✓ talloc: 已安装"
else
    echo "✗ talloc: 未安装(proot 需要 talloc)"
fi

🐛 常见问题与处理

❌ 问题 1:sys/queue.h 缺失

  • 🔍 症状:编译错误 sys/queue.h: No such file or directory
  • 🔎 原因:OpenHarmony 系统头文件中缺少 BSD 风格的 sys/queue.h
  • ✅ 解决方法
    • build-hnp/proot/Makefile 中复制 queue.hsysroot/include
    • 在源码中使用条件编译:#ifdef __OHOS__ 时包含 queue.h,否则包含 <sys/queue.h>
    • 位置:build-hnp/proot/Makefile:6build-hnp/proot/ohos.patch

❌ 问题 2:ptrace(TRACEME) 失败

  • 🔍 症状:运行时错误 ptrace(TRACEME): Operation not permitted
  • 🔎 原因:OpenHarmony 平台对 ptrace 有特殊限制
  • ✅ 解决方法
    • ohos.patch 中禁用 ptrace(TRACEME) 的错误检查
    • 添加条件编译:#ifndef __OHOS__ 时检查 ptrace 返回值
    • 位置:build-hnp/proot/ohos.patchsrc/tracee/event.c

❌ 问题 3:access(X_OK) 检查失败

  • 🔍 症状:无法执行文件,access: Permission denied
  • 🔎 原因:OpenHarmony 平台对文件执行权限检查有特殊处理
  • ✅ 解决方法
    • ohos.patch 中禁用 access(host_path, X_OK) 检查
    • 添加条件编译:#ifndef __OHOS__ 时检查执行权限
    • 位置:build-hnp/proot/ohos.patchsrc/execve/enter.csrc/path/path.c

❌ 问题 4:MSG_COPY 宏未定义

  • 🔍 症状:编译错误 MSG_COPY undeclared
  • 🔎 原因:OpenHarmony 系统头文件中可能未定义 MSG_COPY
  • ✅ 解决方法
    • ohos.patch 中添加条件编译检查 MSG_COPY 是否存在
    • 如果未定义,则使用默认值 false
    • 位置:build-hnp/proot/ohos.patchsrc/extension/sysvipc/sysvipc_msg.c

❌ 问题 5:READELF 工具未指定

  • 🔍 症状:构建 loader 时使用系统 readelf 而非交叉工具链的 readelf
  • 🔎 原因:Makefile 中未显式指定 READELF 变量
  • ✅ 解决方法
    • ohos.patch 中添加 READELF 变量定义
    • 在构建时显式传递 READELF=$(READELF)
    • 位置:build-hnp/proot/ohos.patchsrc/GNUmakefile)、build-hnp/proot/Makefile:17,27

❌ 问题 6:宏重定义警告

  • 🔍 症状:编译时出现大量警告 'LIST_INIT' macro redefined
  • 🔎 原因queue.h 中的宏与系统头文件中的宏冲突
  • ✅ 解决方法
    • 这些警告不影响构建,可以忽略
    • 如果需要消除警告,可以在 queue.h 中添加保护宏检查
    • 位置:构建日志中的警告信息

❌ 问题 7:talloc 依赖缺失

  • 🔍 症状:链接错误 undefined reference to 'talloc_*'
  • 🔎 原因:proot 依赖 talloc 库,但未正确链接
  • ✅ 解决方法
    • 确保 tallocPKGS 中,并在 proot 之前构建
    • 设置 PKG_CONFIG_PATH 指向 sysroot/lib/pkgconfig
    • 位置:build-hnp/Makefile:PKGSbuild-hnp/proot/Makefile:12,21,28

❌ 问题 8:getcwd 在 Android/OHOS 上的行为差异

  • 🔍 症状:临时目录处理失败
  • 🔎 原因:OpenHarmony 平台的 getcwd 行为与标准 Linux 不同
  • ✅ 解决方法
    • ohos.patch 中将 OpenHarmony 与 Android 同等处理
    • 使用 malloc(PATH_MAX)getcwd(cwd, PATH_MAX) 替代标准方式
    • 位置:build-hnp/proot/ohos.patchsrc/path/temp.c

🔄 重建与扩展

  • 🔧 重建单包

    make -C build-hnp rebuild-proot  # 触发子包重新编译并刷新 .stamp
    
  • 🧹 清理

    make -C build-hnp clean  # 清理 sysroot、所有 .stamp 和 PKGS_MARKER
    
  • 📦 扩展:Proot 是容器化和沙箱环境的基础工具

  • 🔄 自动重建机制

    • 修改 PKGS 后,check-pkgs 会自动检测变化并触发重新构建
    • 新增外部 HNP 包到 external-hnp 目录后,会自动合并到 base.hnp

💡 实践建议

  • 🔧 依赖管理:确保 talloc 已正确构建和安装
  • 🚀 补丁维护ohos.patch 需要根据 OpenHarmony 平台特性持续更新
  • 📦 功能测试:在目标平台上测试 proot 的各项功能
  • 🔗 容器化应用:Proot 可用于创建轻量级容器环境
  • 🌐 权限管理:注意 OpenHarmony 平台对 ptrace 和文件权限的特殊限制

📝 结论与建议

  • ✅ 本次已在 aarch64 环境下完成 Proot 的交叉编译与打包,proot 工具已安装到 sysroot 并纳入 HNP 包。
  • 💡 为保证构建稳定
    • 使用 ohos.patch 适配 OpenHarmony 平台特性
    • 确保 talloc 依赖已正确构建
    • 正确处理 queue.h 头文件缺失问题
    • 注意 OpenHarmony 平台对 ptrace 和文件权限的特殊限制
    • 利用 check-pkgs 机制自动检测包列表变化,无需手动清理
    • Proot 为容器化和沙箱环境提供了强大的基础支持
    • 常见陷阱包括平台特性差异(ptrace、文件权限、系统调用)与头文件缺失;当前已通过补丁和条件编译修复

📚 以上为 Proot 构建的深度解读与实践记录。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐