那这次再说吧……
再一次提醒没有耐心和同理心的家伙们去用其它即用的工具像是 TermuxArch 和 Linux Deploy ……
所以这回咱们要干什么?
由于咱不可能把所有发行版都装一次,也不可能在各种手机上都测试一遍,于是咱只能拿 咱手边的家伙举个例子,例如咱手上的小米平板4 ……
- 一部 aarch64 / arm64 设备
现在的手机 CPU 基本上都是 64 位了吧,不知道的话搜索一下手上 CPU 的型号应该就能看个大概。
- 比较新的 Android 系统,最好有 root 权限和完整 busybox 支持。
如果汝已经动手给手机安装了第三方 ROM,那应该不是什么难事。
某蓝绿海厂等受害者可以尝试 UserLAnd……
- 一些剩余存储空间
(这不是废话么) - 安装好终端模拟器和合适的键盘。
或者 Termux 也可以,在里面装上 tsu 以后可以让 Termux 里的 Bash 以 root 用户运行。
作为好几年的 Arch Linux 受害 爱好者,咱当然就装一个 ArchLinux ARM 试试看啦
(虽然这不是官方分支,以及不是有 TermuxArch 了么……)
那么我们的目标是,没有蛀牙 ……
- 能够在 chroot 下基本正常工作
例如正常的使用包管理器、安装软件以及用它们等等。
- 能够访问网络和内存设备 (踩坑警告)
- 能够通过外部访问 (ssh 或者 vnc 啥的)
如有任何不适还请装作没事
天降大坑 nosuid ……(?)
某些手机上的 /data 挂载的时候加上了 nosuid 选项,于是 sudo 就炸了……
sudo: effective uid is not 0, is /sbin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
这种情况可以考虑创建一个磁盘映像把容器放进去(大概吧……)
# 找个地方创建一个映像文件
dd if=/dev/zero of=/path/to/root.img bs=1048576 count=4096
# 给映像创建文件系统和挂载
mke2fs -t ext4 -F /path/to/root.img
mkdir -p /data/linux/arch
mount -t ext4 -o loop /path/to/root.img /data/linux/arch
如果肯定不用 sudo 的话能不能当做没事……
要有空间,于是……
丢了个 tarball 下来让汝自己 bootstrap 去(啥?)
安装 GNU/Linux 发行版的过程,其实就是在解决一个先有鸡还是先有蛋的问题,这个过程就是 bootstrap。 大概就是……
- 从别的什么可以启动的地方把要安装的 GNU/Linux 发行版的最小的部份下载回来,安装上。
- 通过一些方法进入这个最小的部份中(例如 chroot ),为目标设备特化配置。
只不过大部分发行版的安装过程中被自动化了(Arch / Gentoo 等用户表示情绪稳定。)。 在 Android 上安装,同样要经过这个过程。
于是,首先咱们要下载 Arch Linux ARM 的 tarball ,可以在电脑上下载下来发送到手机上,也可以用手机 的浏览器直接下载,也可以用 curl 或者 wget:
wget http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz
如果直接从官方仓库下载不够快的话,可以通过镜像网站下载,例如:
https://mirrors.tuna.tsinghua.edu.cn/archlinuxarm/os/ArchLinuxARM-aarch64-latest.tar.gz
然后创建一个目录存放解压出来的基本系统,再解压出来刚下载的 tarball:
# 因为 SD 卡可能放不下权限等神奇的原因,就放在内存设备上好了……
# mkdir -p /data/linux/arch
# 以及 Arch Linux ARM 官方是建议用 bsdtar 的,要是汝的手机上凑巧有(不管是
# 系统里的还是 Termux 的),就用上吧……
# bsdtar -xpf /path/to/ArchLinuxARM-aarch64-latest.tar.gz -C /path/to/mountpoint
# 不然 tar 也是可以的。
# tar -xzvf /path/to/ArchLinuxARM-aarch64-latest.tar.gz -C /path/to/mountpoint
Chroot on Android
在普通的 GNU/Linux 发行版上 chroot 时,咱们大抵会这么做:
# 切换到 chroot 的目标目录并挂载上 /dev /sys 这样的伪文件系统
# cd /location/of/new/root
# mount -t proc proc proc/
# mount --rbind /sys sys/
# mount --rbind /dev dev/
# 通过给定的 shell 进入 chroot
# chroot /location/of/new/root /bin/bash
在 Android 上其实也差不多:
# mount -o bind /dev /data/linux/arch
# mount -o bind /sys /data/linux/arch/sys
# mount -o bind /proc /data/linux/arch/proc
# mount -t tmpfs tmpfs /data/linux/arch/tmp
以及记得修改一下 chroot 里面的 /etc/resolv.conf , Arch 这个默认是到
/run/systemd/resolve/resolv.conf 的软链接。 反正里面也没有 systemd 用 ,于是
删掉重建好了……
# /data/linux/arch/etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
如果有必要的话,可以同时修改里面的镜像仓库地址。
# /data/linux/arch/etc/pacman.d/mirrorlist
Server = https://mirrors.ustc.edu.cn/archlinuxarm/$arch/$repo
然后就和平常一样 chroot 进去咯~
clover:/data/linux # chroot /data/linux/arch /bin/bash
[root@localhost /]#
起始配置
The bootstrap environment is really barebones (no nano or lvm2). Therefore, we need to set up pacman in order to download other necessary packages.
这下知道为啥要在外面改 /etc/resolv.conf 了吧(当然汝要是独辟蹊径的话那当咱没说……)
正如 官方说明提示的一样 ,初始化 pacman 密钥环和获得密钥:
[root@localhost /]# pacman-key --init
gpg: /etc/pacman.d/gnupg/trustdb.gpg: trustdb created
gpg: no ultimately trusted keys found
gpg: starting migration from earlier GnuPG versions
gpg: porting secret keys from '/etc/pacman.d/gnupg/secring.gpg' to gpg-agent
gpg: migration succeeded
gpg: Generating pacman keyring master key...
gpg: key 56753AA14274D5A7 marked as ultimately trusted
gpg: directory '/etc/pacman.d/gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/etc/pacman.d/gnupg/openpgp-revocs.d/46C9147EE071F7E5D16A085856753AA14274D5A7.rev'
gpg: Done
==> Updating trust database...
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
[root@localhost /]# pacman-key --populate archlinuxarm
==> Appending keys from archlinuxarm.gpg...
==> Locally signing trusted keys in keyring...
-> Locally signing key 69DD6C8FD314223E14362848BF7EEF7A9C6B5765...
-> Locally signing key 02922214DE8981D14DC2ACABBC704E86B823CD25...
-> Locally signing key 9D22B7BB678DC056B1F7723CB55C5315DCD9EE1A...
==> Importing owner trust values...
gpg: setting ownertrust to 4
gpg: inserting ownertrust of 4
gpg: setting ownertrust to 4
==> Updating trust database...
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 3 trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: depth: 1 valid: 3 signed: 1 trust: 0-, 0q, 0n, 3m, 0f, 0u
gpg: depth: 2 valid: 1 signed: 0 trust: 1-, 0q, 0n, 0m, 0f, 0u
[root@localhost /]#
接下来安装(和更新)基本系统,如果有别的需要的话也可以装别的。
[root@localhost /]# pacman -Syu base base-devel nano --needed
如果不幸遇到了像是 error: could not determine cachedir mount point /var/cache/pacman/pkg 这样的错误, 那在 /etc/pacman.conf 里把 Misc options 下面的 CheckSpace 注释掉应该能绕过 (于是有别的方法嘛)
基于正经的 GNU/Linux 用户不会日用 root 账户这一指导原则(啥?),咱们也要新建一个用户:
[root@localhost /]# useradd -m -s /bin/bash horo
[root@localhost /]# passwd horo
有必要的话也可以修改 sudoers 文件(记得用 visudo),把汝刚刚创建的用户添加到 sudoers 中。
以及介于 Android 的魔改属性,只有特定的组可以进行像是访问网络或者访问 SD 卡等操作,于是 还要在 chroot 里新建相应的组,并把新建的用户加到这些组去:
# groupadd 可以用 -g 参数制定新增组的 id ,至于这些组分别是啥
# 看后面的组名应该就知道了吧……
groupadd -g 3001 android_bt
groupadd -g 3002 android_bt-net
groupadd -g 3003 android_inet
groupadd -g 3004 android_net-raw
groupadd -g 1015 sdcard-rw
groupadd -g 1028 sdcard-r
# 然后把新建的用户添加到合适的组中
gpasswd -a horo android_bt
gpasswd -a horo android_bt-net
gpasswd -a horo android_inet
gpasswd -a horo android_net-raw
gpasswd -a horo sdcard-rw
gpasswd -a horo sdcard-r
最后(?),因为没有 systemd,所以请像新装 Arch Linux 的时候一样手动设置一下 locales:
- /etc/locale.gen 是一个仅包含注释文档的文本文件。指定您需要的本地化类型,去掉对应行前面的注释符号(#)就可以啦,还是用 nano 打开,建议选择帶UTF-8的項:
# nano /etc/locale.gen
en_US.UTF-8 UTF-8
- 执行 locale-gen 以生成 locale 讯息:
# locale-gen
- 创建 locale.conf 并提交本地化选项:
# echo 用来输出某些文字,后面的大于号表示把输出保存到某个文件里啦~
# 或者可以用文字编辑器新建这个文件加上这一行。
# echo LANG=en_US.UTF-8 > /etc/locale.conf
设置用户级别的 locale
用 su 切换到刚建立的用户,然后编辑 ~/.bashrc 修改自己的 Locale ,例如:
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
(为啥不是 ~/.config/locale.conf 了啊…… 其实咱也不知道…… )
于是现在大概就有了这个样子:
(这个在终端里显示发行版等信息的软件是 screenfetch 啦,也有人喜欢另一个 小修改版 neofetch )
设置 SSH 和 SD 卡访问
SSH 的话,生成好主机密钥然后再启动 sshd 就可以:
## 在有 systemd 这样的 init 系统的发行版上启动 sshd 时会帮汝运行这一步,
## 不过这里就只有自己代劳啦……
# ssh-keygen -A
## 这里一定要是绝对路径,不然就会出 "sshd re-exec requires execution with an absolute path" 错误。
# /usr/bin/sshd
然后就可以用一个新的终端模拟器窗口通过 ssh 连接进来啦……
clover:/ $ ssh horo@127.0.0.1
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256: .
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
horo@127.0.0.1's password:
[horo@localhost ~]$
要是汝在登录时遇到了 PTY allocation failed on channel 0 这样的错误,在 chroot 里(重新) 挂载一下 /dev/pts 试试?
# umount /dev/pts
# mount -t devpts devpts /dev/pts
以及可以的话记得修改 /etc/sshd_config 把 sshd 限定到只允许本地连接?
要把 SD 卡挂载到哪里的话,在 chroot 的外面运行:
## 当然汝的 /sdcard 可能是汝的内存设备什么的,别忘了自己调整路径……
# mkdir /data/linux/arch/mnt/sdcard
# mount -o bind /sdcard /data/linux/arch/mnt/sdcard
设置 VNC 访问
首先安装桌面和 VNC Server ,考虑到两大桌面的资源需求和或多或少有点依赖 GNOME,比较合适的是 xfce:
## 当然汝可以看需要装些别的,像是中文字体什么的。
# pacman -S xorg xfce4 xfce4-goodies tigervnc
接下来启动 vncserver,设置一个密码:
[horo@localhost ~]$ vncserver
You will require a password to access your desktops.
Password:
Verify:
# 要创建一个只读桌面用的密码嘛?
Would you like to enter a view-only password (y/n)?
xauth: file /home/horo/.Xauthority does not exist
# 桌面的位置
New 'localhost:1 (horo)' desktop is localhost:1
Creating default startup script /home/horo/.vnc/xstartup
Creating default config /home/horo/.vnc/config
Starting applications specified in /home/horo/.vnc/xstartup
Log file is /home/horo/.vnc/localhost:1.log
然后先用 vncserver -kill :1 中止掉现有的 VNC Server 进程,修改一下新生成的配置文件。
# /home/horo/.vnc/xstartup
#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
exec xfce4-session
# /home/horo/.vnc/config
## Supported server options to pass to vncserver upon invocation can be listed
## in this file. See the following manpages for more: vncserver(1) Xvnc(1).
## Several common ones are shown below. Uncomment and modify to your liking.
##
# securitytypes=vncauth,tlsvnc
# desktop=sandbox
# 可以在这里修改分辨率和限定本地连接,具体的参数可以查阅相应的手册页来了解。 (vncserver(1) Xvnc(1))
geometry=1920x1080
# localhost
# alwaysshared
如果一切正常的话应该会连上去之后有 xfce 的界面的,但是咱这回就只有 Unable to contact settings server 这个错误,以后再说吧(跑)
不过隔壁 Linux Deploy 出的 Debian 是好的……
总结?
所以有 Linux Deploy 那样好用(?)的工具了为啥不直接拿来用呢(划掉)
以及纯粹是闲的,找一台正经的电脑装正经的 GNU/Linux 不好么 (x)