手机服务器-小米6折腾记录
termux工具安装
Genymobile/scrcpy:可以直接通过ADB,在PC上直接操作手机。
termux/termux-app:termux核心应用
termux/termux-boot:(可选)支持执行自启动脚本
chroot方式安装发行版本
这种方式安装Linux发行版本系统,需要root权限,但整体性能更好。
安装常用工具
打开termux,执行1
2
3
4
5
6
7
8
9
10
11
12pkg update -y
pkg upgrade -y
pkg install -y \
root-repo \
tsu \
wget \
curl \
proot \
tar \
xz-utils \
vim \
nano
debootstrap构建rootfs
在PC上发行版本都带有debootstrap工具,没有就安装此工具即可。与一般的rootfs-base相比,在线构建的版本带有更多的调试工具,遇到问题更容易解决。1
2
3
4
5debootstrap --arch=arm64 bookworm debian-rootfs https://mirrors.aliyun.com/debian/
# 打包文件系统
tar czpf debian-rootfs.tar.gz debian-rootfs
# 上传到手机,解压到特定目录
tar xpf debian-rootfs.tar.gz -C /data/local/
手机解压rootfs需要root权限,最后可以得到跟文件系统路径:/data/local/debian-rootfs,后面chroot需要切换到此路径。1
2
3root@localhost:~# ls /data/local/debian-rootfs
bin data etc lib mnt proc run sdcard sys usr
boot dev home media opt root sbin srv tmp var
配置启动脚本
最后通过统一的脚本switch_rootfs配置容器系统和进入容器1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49#!/system/bin/sh
set -e
ROOTFS=$1
USER_SH=${2:-"/bin/bash"}
USER_HOST_NAME=${3:-"termux-001"}
if [ -z "$ROOTFS" ]; then
echo "empty rootfs"; exit -1
fi
if [ ! -e "$ROOTFS" ]; then
echo "not exist rootfs: '$ROOTFS'"; exit -1
fi
# mount
mkdir -p $ROOTFS/dev
mkdir -p $ROOTFS/proc
mkdir -p $ROOTFS/sys
mkdir -p $ROOTFS/dev/pts
mkdir -p $ROOTFS/sdcard
mkdir -p $ROOTFS/data
mountpoint -q $ROOTFS/dev || mount --bind /dev $ROOTFS/dev
mountpoint -q $ROOTFS/proc || mount --bind /proc $ROOTFS/proc
mountpoint -q $ROOTFS/sys || mount --bind /sys $ROOTFS/sys
mountpoint -q $ROOTFS/dev/pts || mount -t devpts -o gid=5,mode=620 devpts $ROOTFS/dev/pts
mountpoint -q $ROOTFS/sdcard || mount --bind /sdcard $ROOTFS/sdcard
mountpoint -q $ROOTFS/data || mount --bind /data $ROOTFS/data
# tmp
mkdir -p $ROOTFS/tmp
chmod 1777 $ROOTFS/tmp
# DNS
cat > $ROOTFS/etc/resolv.conf <<EOF
nameserver 223.5.5.5
nameserver 114.114.114.114
EOF
# hostname
echo $USER_HOST_NAME > $ROOTFS/etc/hostname
# start
export TTY=$(tty)
exec /data/data/com.termux/files/usr/bin/chroot \
--userspec=root:root --groups=3003,3004,1003,1004 \
$ROOTFS /usr/bin/env -i \
HOME=/root \
TERM="$TERM" \
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
LANG=C.UTF-8 \
$USER_SH --login -c "cd ~; exec $USER_SH" <$TTY >$TTY 2>$TTY
需要su切换为root才能chroot进入容器1
2
3
4~ $ mv ~/switch_rootfs $PREFIX/bin/
~ $ su
:/data/data/com.termux/files/home # $PREFIX/bin/switch_rootfs /data/local//data/local/debian-rootfs
root@localhost:~#
配置别名简化流程1
2
3
4
5
6
7
8~ $ cat ~/.bashrc
start-linux() {
local cmd="$PREFIX/bin/switch_rootfs $@"
su -c "$PREFIX/bin/script -q -c '$cmd' /dev/null"
}
alias debian='start-linux /data/local/debian-rootfs'
~ $ debian
root@localhost:/#
proot-dist方式安装发行版本
这种方式安装Linux发行版本系统,不需要root权限,虽然整体性能稍差,但无需额外繁杂的配置步骤。
容器配置
替换源
1 | # debian (bookworm) |
常用工具安装
1 | apt-get install -y vim procps ca-certificates bash-completion zsh |
自启动配置
termux脚本1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20$ cat > ~/.termux/boot/start-services <<'EOF'
#!/data/data/com.termux/files/usr/bin/sh
termux-wake-lock
if [ ! -d "$PREFIX/var/run/service" ]; then
sh $PREFIX/etc/profile.d/start-services.sh
fi
EOF
$ cat > ~/.termux/boot/start-debian <<'EOF'
#!/data/data/com.termux/files/usr/bin/sh
termux-wake-lock
BOOT_LOG="$HOME/boot.log"
ROOTFS="/data/local/debian-rootfs"
echo "--- Start Auto Boot: $(date) ---" >> $BOOT_LOG
su -c "$PREFIX/bin/script -q -c '$PREFIX/bin/switch_rootfs /data/local/debian-rootfs /bin/bash /bin/startup_container' /dev/null" >> $BOOT_LOG 2>&1
echo "--- Boot Script End ---" >> $BOOT_LOG
EOF
容器脚本1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61$ cat > /etc/init.d/frpc <<'EOF'
#!/bin/sh
### BEGIN INIT INFO
# Provides: frpc
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start frpc at boot time
### END INIT INFO
DAEMON=/usr/local/frp_0.68.1_linux_arm64/frpc
NAME=frpc
DESC="frp client"
# 配置文件路径
CONF=/usr/local/frp_0.68.1_linux_arm64/frpc.yaml
# PID文件位置
PIDFILE=/var/run/$NAME.pid
test -x $DAEMON || exit 0
case "$1" in
start)
echo -n "Starting $DESC: "
# 使用 start-stop-daemon 后台运行
start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE --exec $DAEMON -- -c $CONF
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile $PIDFILE
rm -f $PIDFILE
echo "$NAME."
;;
restart)
$0 stop
sleep 1
$0 start
;;
status)
if [ -f $PIDFILE ]; then
echo "$NAME is running (pid $(cat $PIDFILE))"
else
echo "$NAME is not running"
fi
;;
*)
echo "Usage: service frpc {start|stop|restart|status}" >&2
exit 1
;;
esac
exit 0
EOF
cat > /bin/startup_container <<'EOF'
#!/bin/bash
service ssh start
service frpc start
EOF
附录
预构建的base rootfs
与使用debootstrap在线构建相比,预构建的rootfs基本为最小文件系统,缺少必要的网络调试工具。
常见问题
Ctrl+C没有和系统绑定,造成终端异常
问题现象:在容器中执行ping命令,Ctrl+C任然会继续打印;容器中直接执行Ctrl+C,退出容器并且termux也不能正常执行命令。
根因是tty没有正确重定向到容器标准输入输出中,修改启动命令1
2
3
4
5
6
7
8
9
10
11...
# 需要卸载$ROOTFS/dev/pts
mountpoint -q $ROOTFS/dev/pts || mount -t devpts -o gid=5,mode=620 devpts $ROOTFS/dev/pts
...
export TTY=$(tty)
exec /data/data/com.termux/files/usr/bin/chroot --userspec=root:root --groups=3003,3004,1003,1004 $ROOTFS /usr/bin/env -i \
HOME=/root \
TERM="$TERM" \
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
LANG=C.UTF-8 \
/bin/bash --login <$TTY >$TTY 2>$TTY
进入系统后ping 223.5.5.5返回socket权限异常
问题现象1
2root@localhost:/# ping 223.5.5.5
ping: socket: Permission denied
问题根因
没有将debian系统的root加入inet组,修改启动脚本1
2
3
4
5
6exec /data/data/com.termux/files/usr/bin/chroot --userspec=root:root --groups=3003,3004,1003,1004 $ROOTFS /usr/bin/env -i \
HOME=/root \
TERM="$TERM" \
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
LANG=C.UTF-8 \
/bin/bash --login
debian系统中执行命令1
2
3
4root@localhost:/# groupadd -g 3003 inet
root@localhost:/# usermod -aG inet root
root@localhost:/# id
uid=0(root) gid=0(root) groups=0(root),1003,1004,3003(inet),3004
ping域名没有问题后,apt update报错
问题现象1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16root@localhost:/etc/apt# ping mirrors.tuna.tsinghua.edu.cn -c 1
PING bfdmirrors.s.tuna.tsinghua.edu.cn (101.6.15.130) 56(84) bytes of data.
64 bytes from 101.6.15.130 (101.6.15.130): icmp_seq=1 ttl=37 time=129 ms
--- bfdmirrors.s.tuna.tsinghua.edu.cn ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 129.118/129.118/129.118/0.000 ms
root@localhost:/etc/apt# apt update
...
W: Failed to fetch http://mirrors.tuna.tsinghua.edu.cn/debian/dists/bookworm/InRelease Temporary failure resolving 'mirrors.tuna.tsinghua.edu.cn'
W: Failed to fetch http://mirrors.tuna.tsinghua.edu.cn/debian/dists/bookworm-updates/InRelease Temporary failure resolving 'mirrors.tuna.tsinghua.edu.cn'
W: Failed to fetch http://mirrors.tuna.tsinghua.edu.cn/debian/dists/bookworm-backports/InRelease Temporary failure resolving 'mirrors.tuna.tsinghua.edu.cn'
W: Failed to fetch http://mirrors.tuna.tsinghua.edu.cn/debian-security/dists/bookworm-security/InRelease Temporary failure resolving 'mirrors.tuna.tsinghua.edu.cn'
W: Some index files failed to download. They have been ignored, or old ones used instead.
定位流程1
2
3
4# 确保权限正确
chmod 644 /etc/resolv.conf
# 尝试清理 apt 的缓存
rm -rf /var/lib/apt/lists/*
(非此原因)域名被解析为ipv61
2root@localhost:/etc/apt# getent hosts mirrors.tuna.tsinghua.edu.cn
2402:f000:1:400::2 bfdmirrors.s.tuna.tsinghua.edu.cn mirrors.tuna.tsinghua.edu.cn
(没有效果)强制改为ipv41
2
3
4
5
6
7
8
9
10
11deb http://mirrors4.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware
deb http://mirrors4.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware
deb http://mirrors4.tuna.tsinghua.edu.cn/debian/ bookworm-backports main contrib non-free non-free-firmware
deb https://security.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware
root@localhost:/etc/apt# getent hosts mirrors4.tuna.tsinghua.edu.cn
101.6.15.130 bfdmirrors4.a.s.tuna.tsinghua.edu.cn mirrors4.tuna.tsinghua.edu.cn
echo "101.6.15.130 mirrors.tuna.tsinghua.edu.cn" >> /etc/hosts
# 彻底修复:修改 Android 内核的 Ping 组范围
su -c "sysctl -w net.ipv4.ping_group_range='0 2147483647'"
以下尝试成功解决问题1
2
3
4
5
6
7# 如果 _apt 用户不存在,先通过一次失败的安装尝试让它产生,或者直接手动添加
# 将 _apt 用户也加入 3003(inet) 组
groupadd -g 3003 inet 2>/dev/null
usermod -aG inet _apt
# 同时给 apt 关闭沙盒模式做测试(临时)
apt update -o Debug::Acquire::http=true -o APT::Sandbox::User=root
apt update -o Debug::Acquire::http=true -o APT::Sandbox::User=root命令执行成功。
问题根因
在较新版本的 Debian 中,apt update 为了安全,默认会降权使用 _apt 用户来执行网络下载任务。强制让沙箱用户使用root即可,否则会被android组拦截。1
2
3
4# apt update -o Debug::Acquire::http=true -o APT::Sandbox::User=root
cat >> /etc/apt/apt.conf.d/99-android-fix <<'EOF'
APT::Sandbox::User "root";
EOF