在 Android 上 chroot 一个 ArchLinux

AndroidLinux

翻知乎看到初春静流的 这条回答 ,刚好手边有闲置的 Android 机,不妨来试试 chroot 。

创建 root 目录

首先手机必须破解了 root 权限,然后到 /data 下面建一个用作 rootfs 的目录,比如我用的是 /data/local/archlinux

获取合适的 ArchLinuxARM 镜像

虽然现在 ArchLinux 只对 x86_64 架构提供支持,但是有 ArchLinuxARM 项目对 arm 平台也提供了完善的支持,去源里找一个支持你手机平台的镜像,比如我用的是 ArchLinuxARM-odroid

把镜像安装到手机

把镜像下载下来,解压到 /data/local/archlinux ,先别急着 chroot ,把必要的目录 rbind 过去

busybox mount --rbind /dev /data/local/archlinux/dev
busybox mount --rbind /sys /data/local/archlinux/sys
busybox mount --rbind /proc /data/local/archlinux/proc
busybox mount -t tmpfs tmpfs /data/local/archlinux/tmp

切换到 chroot 环境

现在就是切换到 chroot 环境的时候了,使用这条命令就好

chroot /data/local/archlinux bash

不出所料的话, bash 会出现在你的眼前。

联网

讲道理网络本来应该是配好的,不过 Android 内核有个蛋疼的网络权限机制,所以还需要做一些魔改

groupadd -g 3001 aid_bt
groupadd -g 3002 aid_bt_net
groupadd -g 3003 aid_inet
groupadd -g 3004 aid_net_raw
groupadd -g 3005 aid_admin

usermod -a -G aid_bt,aid_bt_net,aid_inet,aid_net_raw,aid_admin root

newgrp aid_inet    # 切换到 aid_inet 组,获取联网权限

然后是解析,Arch Linux 的网络和解析默认都是由 systemd 管着的,然而在 chroot 环境下,systemd 不能正常工作,所以手动设置一下吧。

rm /etc/resolv.conf    # 先删掉之前的符号链接
echo 'nameserver ip.of.name.server' > /etc/resolv.conf

pacman

清华和科大都提供了 ArchLinuxARM 的开源镜像,把这两行放到 /etc/pacman.d/mirrorlist 顶上

Server = http://mirrors.ustc.edu.cn/archlinuxarm/$arch/$repo
Server = http://mirrors.tuna.tsinghua.edu.cn/archlinuxarm/$arch/$repo

然后配置 pacman 使用 curl 进行下载,在 /etc/pacman.conf 中取消注释下面一行

XferCommand = /usr/bin/curl -C - -f %u > %o

完成之后 pacman 应该就能正常工作了。

服务

由于 systemd 在 chroot 环境下不能工作,所以需要使用 nohup 启动服务。

例如启动 sshd 服务使用

nohup /bin/sshd -D > sshd.log &

要提示没有 host key 就 gen 一个

ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa

用户与权限

大部分手机在挂载 /data 时使用了 nosuid ,比如我这部手机的

/dev/block/mmcblk0p21 /data ext4 rw,seclabel,nosuid,nodev,noatime,journal_checksum,journal_async_commit,noauto_da_alloc,data=ordered 0 0

这使得需要 suid 的东西都无法工作,比如 sudo ,要解决这个问题,有三种方案:

  • 直接使用 root 用户,有需要时使用 sudo 降低权限(可能不安全)
  • 把整个 rootfs 放到一个 img 文件里,然后挂载
  • 在手机上使用 suid 选项重新挂载 /data

     busybox mount -o remount,suid /data