Я испробовал множество средств для установки Linux на свое Android устройство, но все они или не работали вовсе, или были слишком глючные. К счастью я использую на ПК ArchLinux и узнав о проекте ArchLinux ARM решил попробовать его в деле. И не просто установить в chroot, а заставить его работать и без него.
Нам потребуется
- Прямые руки
- Android устройство
- Root доступ
- Busybox
- Эмулятор терминала
- Свободное место
- ADB(для удобства)
Все действия Вы выполняете на свой страх и риск.
Я использовал
- Устройство Android 4.2 с 512Мб ОЗУ, ядро Linux 3.4.5 armv7l
- Эмулятор терминала ConnectBot
- Управление суперпольпользователем SuperSU
- BusyBox v1.20.0
Часть 1: Подготовка
1. Скачаем архив с ArchLinux ARM с зеркала:
wget http://mirror.yandex.ru/archlinux-arm/os/ArchLinuxARM-armv7-latest.tar.gz
mv ArchLinuxARM-armv7-latest.tar.gz ArchLinuxARM.tar.gz
adb push ArchLinuxARM.tar.gz /sdcard/
Дальнейшие действия необходимо проделывать на Android устройстве
2. Создаем файл для будущего образа с помощью make_ext4fs.
Если у вас есть отдельный раздел на карте памяти — желательно использовать его. В моем случае 16Гб SD карта была забита важными данными и возможности сдвинуть главный FAT раздел не было.
В зависимости от настроек /sdcard может быть как внешней, так и внутренней картой памяти.
cd sdcard
make_ext4fs -l 3221225472 arch.img
3221225472 это 1024*1024*1024*3, следовательно будет создан образ в 3Гб. Размер образа определите для себя по вкусу. Помните что на FAT32 нельзя создать файл больше 4Гб
3. Примонтируем образ и распакуем файлы ArchLinux ARM
mount -o rw,remount /
mkdir /arch
busybox mount /sdcard/arch.img /arch
tar -xvf ArchLinuxARM.tar.gz -C /arch/
4. Несмотря на то, что наша цель — обойтись без chroot, для базовой настройки и проверки работоспособности chroot все же нужно сделать. В противном случае обновлять, доставлять пакеты Вам придется уже на боевой системе.
busybox mount -t proc none /arch/proc
busybox mount -o rbind /dev /arch/dev
busybox mount -t tmpfs none /arch/tmp
busybox mount -o size=10%,mode=0755 -t tmpfs none /arch/run
chroot /arch /bin/bash
Часть 2: Поиск и решение проблем
Проблема 1: ping не работает
Попробуем ping
ping 8.8.8.8
socket: Permission denied
Вспоминаем, что у Android серьезная система разграничения прав. И в нем существует пермишен на «Полный доступ к сети». Без этого пермишшена пользователи не могут получить полный доступ к сокетам. То что надо.
Вернемся к Android консоли и пропишем комманду id:
uid=2000(shell) gid=2000(shell) groups=1003(graphics),1004(input),1007(log),1009(mount),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats)
У вас вывод может быть другой
groupadd -g 3003 inet
usermod -a -G inet root
Но вот незадача, chroot не обновляет group. Поможет вот такой «хак»:
su root
Пробуем еще раз:
ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=59 time=89.6 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=59 time=88.6 ms
Проблема 2: Не работает DNS
Удаляем симлинк на systemd и запишем нормальные DNS:
rm /etc/resolv.conf
echo "nameserver 8.8.8.8" > /etc/resolv.conf
Если Вы запороли PATH
Если произошло такое, что простые комманды вида ls,cat,su не работают(не видятся) системой, Вы можете попробывать вызвать их напрямую: /system/bin/ls, /system/bin/cat, /system/xbin/su.
Или перезагрузить устройство.
Ставим необходимые пакеты
pacman -S gcc htop iotop sudo openssh
Проверяем gcc
cd /root
nano main.cpp
#include <iostream>
int main() {
std::cout << "Hello World!n";
return 0;
}
g++ main.cpp
./a.out
Часть 3: Подготовка к работе без chroot
Самое главное, что позволяет ArchLinux работать без chroot рядом с андроидом — тот факт, что папки и файлы ArchLinux и андроид различны и не мешают друг другу.
Если Вы не уверены в том, что файлы не пересекутся, выполните эти команды из Android консоли:
ls /etc/ > /sdcard/ls.txt
ls /arch/etc/ > /sdcard/ls2.txt
busybox grep -F -f /sdcard/ls.txt /sdcard/ls2.txt
Покажет пересечение файлов. У меня это выглядит так:
dhcpcd.conf
hosts
security
Выполним копирование файлов из /etc/ в /arch/etc/ из Android:
cp -Ra /etc/* /arch/etc/
cp -a /sbin/adbd /arch/usr/bin/
Ключ -a обязателен, так как при использовании обычного -R права скопированы не будут.
Нужно заранее позаботится о Root.
Android приложения требуют, что бы комманда su сразу же давала доступ к суперпользователю и не запрашивала пароль.
passwd
mv /usr/bin/su /usr/bin/su.r
Часть 4: Поехали!
Создадим нужные каталоги и воспользуемся mount --bind что бы виртуально заменить директорию, не изменяя ее на диске.
mkdir /lib
mkdir /bin
mkdir /xbin
mkdir /opt
mkdir /usr
mkdir /home
mkdir /run
mkdir /srv
mkdir /tmp
mkdir /var
busybox mount --bind /arch/etc /etc
busybox mount --bind /arch/opt /opt
busybox mount --bind /arch/home /home
busybox mount -o size=10%,mode=0755 -t tmpfs none /run
busybox mount --bind /arch/srv /srv
busybox mount -t tmpfs none /tmp
busybox mount --bind /arch/sbin /sbin
busybox mount --bind /arch/usr/ /usr
busybox mount --bind /arch/var/ /var
busybox mount --bind /arch/lib/ /lib
busybox mount --bind /arch/usr/bin/ /bin
/bin/bash
Если что-то сделано неправильно, Вы можете перезагрузить устройство и попробовать снова. Порядок монтирования важен. При ошибке с монтированием стандартные команды могут взятся из ArchLinux до того, как все каталоги будут смонтированы.
Что дальше
В итоге мы имеем практически полноценный ArchLinux за исключением systemd с свежими версиями пакетов.
Можно установить http, php, mysql. При правильной настройке на уменьшение потребления памяти даже на моем смартфоне с ОЗУ 512Мб они работали корректно.
Можно установить иксовые библиотеки и с помощью X сервера для Android пользоваться ПО для линукса. xterm заработал корректно.
Можно собирать любые программы (и, о нет, ядра) для Linux без ПК.
Можно установить Java для ARM и использовать Java приложения.
Послесловие
Большой проблемой остается systemd и его привязка к PID 1. Для того, что бы сохранить PID 1 нужно влезть в init андроида и прописать exec после инициализации устройств. Это можно сделать заменив init андроида shell скриптом, но тогда остается вопрос что делать с оригинальным init андроида. Так как место на загрузочном диске ограничено несколькими мегабайтами, нужно будет использовать switch_root в заранее созданный образ. Мне пока не удалось завести systemd таким способом.
Мне 16, и это моя первая публикация. Конструктивная критика приветствуется.
Автор: Gravit