termux使用proot构建ubuntu20.04(非proot-distro),并搭建.net10的开发编译环境

具体操作步骤如下:

下载

ubuntu-base-20.04.5-base-arm64.tar

 

地址

https://cdimage.ubuntu.com/ubuntu-base/releases/focal/release/

 

通过WinScp拷贝到android 的termux目录下(/data/data/com.termux/files/home)

 

解压到目标目录

tar --numeric-owner -zxvf ubuntu-base-20.04.5-base-arm64.tar.gz -C ubuntu2004/ubuntu-fs/

 

 

构建proot启动脚本

 #---------------------------------------------------------------------------------------

#!/data/data/com.termux/files/usr/bin/bash

cd $(dirname $0)

 

## 取消可能导致冲突的环境变量

unset LD_PRELOAD

 

command="proot"

command+=" --link2symlink"

command+=" -0"

command+=" -r ubuntu-fs"

 

## 挂载基础系统目录

command+=" -b /dev"

command+=" -b /proc"

command+=" -b /sys"

command+=" -b ubuntu-fs/tmp:/dev/shm"

 

## 挂载手机存储(移除引起路径冲突的全局根目录 / 挂载)

command+=" -b /data/data/com.termux"

command+=" -b /sdcard"

command+=" -b /storage"

 

## 设置运行环境与标准的 Ubuntu 20.04 环境变量

command+=" -w /root"

command+=" /usr/bin/env -i"

command+=" HOME=/root"

command+=" PATH=/usr/local/sbin:/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin:/usr/games:/usr/local/games"

command+=" TERM=$TERM"

command+=" LANG=C.UTF-8"

command+=" /bin/bash --login"

 

# 支持外部命令直接输入执行

com="$@"

if [ -z "$1" ];then

    exec $command

else

    $command -c "$com"

fi

 #---------------------------------------------------------------------------------------------------------------------------

 

给予权限

sudo chmod +x start_chroot.sh

sudo ./start_chroot.sh

 

登录后group id报错信息解决

echo "aid_inet:x:3003:root" >> /etc/group

echo "aid_everybody:x:9997:root" >> /etc/group

echo "aid_u0_a362:x:20362:root" >> /etc/group

echo "aid_u0_a362_cache:x:50362:root" >> /etc/group

 

登录后环境配置

apt update

apt upgrade

apt install busybox

apt install nano

apt install net-tools

apt install iputils-ping

 (dotnet 依赖环境)

apt install -y build-essential

 

apt install -y libicu66

 

apt install wget

 

遇到不能联网,执行下面命令来指定dns

echo "nameserver 223.5.5.5" > /etc/resolv.conf

 

下载SDK

wget https://builds.dotnet.microsoft.com/dotnet/Sdk/10.0.301/dotnet-sdk-10.0.301-linux-arm64.tar.gz

 

mkdir -p $HOME/dotnet && tar zxf dotnet-sdk-10.0.301-linux-arm64.tar.gz -C $HOME/dotnet

 

增加环境变量

export DOTNET_ROOT=$HOME/dotnet

export PATH=$PATH:$HOME/dotnet

# proot下需要额外加入这行,解决GC堆内存限制

export DOTNET_GCHeapHardLimit=1C0000000

#建议proot下加入如下环境,解决该环境下Socket对外联网工作异常的问题(依然需要root)

export DOTNET_SYSTEM_NET_SOCKETS_INLINE_COMPLETIONS=0

 

#建议proot下添加下面的代码,避免后台编译VBCSCompiler进程不能退出的问题

alias exit='pkill -9 -f VBCSCompiler; pkill -9 -P $$; builtin exit'

 

关于网络配置解释(export DOTNET_SYSTEM_NET_SOCKETS_INLINE_COMPLETIONS=0):

在 Linux 系统上,.NET 为了实现极高的并发网络吞吐量,其 System.Net.Sockets 核心库默认开启了 Inline Completions(内联完成) 机制。

  • 开启时(.NET 默认行为): 当 Socket 发生 I/O 事件时,.NET 会通过底层的 epoll 线程池直接在当前 I/O 线程中“就地(Inline)”触发并回调 C# 代码中的 Task 状态机。这减少了线程上下文切换(Thread Context Switch)的开销。
  • PRoot 中为什么会挂: PRoot 依靠 ptrace 来拦截和翻译每一次网络系统调用。当 .NET 的多个高性能 I/O 线程在非常底层的级别同时尝试内联触发事件,并疯狂交织进行 epoll_wait、setsockopt 时,PRoot 的用户态仿真层(模拟内核)无力应对如此高并发且复杂的底层调用同步,导致线程锁死、系统调用被 PRoot 挂起,或者因时序混乱被 Android 内核误判为非法越权。
  • 关闭后(设置=0): .NET 会被迫放弃这个极限网络优化。所有的 Socket 事件完成通知不再“内联”执行,而是乖乖地被扔回 .NET 全局的 ThreadPool(普通线程池) 中,由独立的标准工作线程去排队调度。

 

微软文档:

DOTNET_SYSTEM_NET_SOCKETS_*

This section highlights two System.Net.Sockets environment variables:

  • DOTNET_SYSTEM_NET_SOCKETS_INLINE_COMPLETIONS
  • DOTNET_SYSTEM_NET_SOCKETS_THREAD_COUNT

DOTNET_SYSTEM_NET_SOCKETS_INLINE_COMPLETIONS (default disabled) allows socket continuations to run on the event thread instead of being dispatched to the ThreadPool, potentially enhancing performance but risking IO thread blockage. [1]

DOTNET_SYSTEM_NET_SOCKETS_THREAD_COUNT allows overriding default, high-load optimized thread calculations (30 x64 / 8 Arm64 per engine) for scenarios with extreme request volumes. [1]

  • If INLINE_COMPLETIONS is 1, Environment.ProcessorCount is used.
  • Otherwise, it defaults to 8 for Arm/Arm64, or 30 for others, determined by RuntimeInformation.ProcessArchitecture. [1]

 

另外.net 编译程序能正常联网的前提,需要使用sudo启动脚本,没有管理员权限,在联网或安装时,都可能遇到问题,这也是直接用脚本构建proot的原因。

 

测试

dotnet --version

 

安装SVN

apt install -y subversion

拉取代码,编译测试

 

安装ubuntu24.04时,libicu可以选择libicu74(libicu-dev太大)

 

另外尝试了下,proot-distro也可以加sudo 去启动,解决.net 程序的对外网络连接的问题。

proot-distro的安装后的文件系统路径比较难找,这里附带下:

/data/data/com.termux/files/usr/var/lib/proot-distro/containers/debian

路径比较难找,这也是为嘛要用脚本构建的原因,编译后程序直接rootfs中找。

 

posted @ 2026-07-24 10:47  猿妙不可言  阅读(1)  评论(0)    收藏  举报