Install Debian (jessie) chroot on Android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/system/bin/sh | |
# ####################################### | |
# Adapted from DebKit | |
# https://github.com/cybertim/DebKit/blob/db894dea44705c4a67e0bb8faa67fc3010755483/src/main/res/raw/debkit | |
# ####################################### | |
set -e | |
# directory for setting up debkit | |
ROOT=$(pwd) | |
[ "$ROOT" == "/" ] && { echo "Nope."; exit 1; } | |
# Debian suite | |
DST=jessie | |
DEBIAN_MIRROR=${DEBIAN_MIRROR:-http://ftp.us.debian.org/debian} # Find a mirror: http://httpredir.debian.org/demo.html | |
DEBOOSTRAP_SRC="$DEBIAN_MIRROR/pool/main/d/debootstrap/debootstrap_1.0.84_all.deb" | |
TOOLS_SRC=https://raw.githubusercontent.com/shirish87/DebKit/661fa00137c23099b8592c4d4158b0d2b5980131/src/main/res/raw | |
TOOLS="busybox busybox2 pkgdetails" | |
# packages preinstalled in the disk image | |
INCLUDE_PACKAGES="--include=locales,sudo,man-db,perl,psmisc,ca-certificates,vim,screen,python-pip,openssh-server,telnet" | |
# space separated list of services to manage with 'start-services' and 'stop-services' | |
CHROOT_SERVICES="ssh" | |
# ####################################### | |
# folder to store setup files | |
BIN=$ROOT/setup | |
# mounting path | |
MNT=$ROOT/mnt | |
# busybox path | |
BB=$BIN/bin | |
# debootstrap extract path | |
BS=$BIN/bootstrap | |
# tmp path | |
TMP=$ROOT/tmp | |
# applets such as busybox wget, tar, xzcat, zcat fail on certain devices (exit code 1 is printed) | |
# incase of failure, install busybox for your device and set | |
# BBOX=<path-to-busybox> | |
BBOX="$BIN/busybox" | |
# ####################################### | |
# Disabled by default, this section sets up the Debian rootfs in a file container. | |
# To enable, point env DEBKIT_DISK_PATH to a directory on your sdcard: | |
# export DEBKIT_DISK_PATH=/sdcard/debkit | |
DISKIMG_ENABLED=0 | |
BBOX2="$BIN/busybox2" # contains mkfs.ext2 applet | |
# path to folder on sdcard for storing disk image | |
DISKIMG_PATH="" | |
[ ! -z "$DEBKIT_DISK_PATH" ] && { DISKIMG_PATH="$DEBKIT_DISK_PATH"; DISKIMG_ENABLED=1; } | |
# disk image | |
DISKIMG="$DISKIMG_PATH/disk.img" | |
# size of the disk image. installed packages take up ~280MB of space | |
DISKIMG_SIZE=500 | |
# block device | |
BLK_DEVICE=/dev/block/loop99 | |
# mount check file | |
MNT_CHECK=$MNT/.mount_check | |
create_disk() | |
{ | |
[ -z "$DISKIMG_PATH" ] && { echo "Invalid disk path."; return 1; } | |
[ -f "$DISKIMG" ] && { echo "Disk exists. Delete file $DISKIMG to recreate."; return 0; } | |
echo "Creating empty ext2 diskimage..." | |
$BBOX2 mkdir -p $DISKIMG_PATH | |
$BBOX2 dd if=/dev/zero of=$DISKIMG bs=1M count=0 seek=$DISKIMG_SIZE | |
$BBOX2 mkfs.ext2 -F $DISKIMG | |
echo "Done." | |
} | |
mount_disk() | |
{ | |
(mount_exists "$MNT") && { echo "Disk already mounted: $MNT"; return 0; }; | |
[ ! -f "$DISKIMG" ] && { echo "Invalid disk: $DISKIMG"; return 1; } | |
remove_block_dev > /dev/null | |
echo "Creating block device $BLK_DEVICE" | |
$BBOX2 mknod $BLK_DEVICE b 7 ${BLK_DEVICE##*loop} | |
$BBOX2 losetup $BLK_DEVICE $DISKIMG | |
echo "Mounting $MNT..." | |
$BBOX2 mkdir -p $MNT | |
$BBOX2 mount -o exec,dev,suid,relatime $BLK_DEVICE $MNT | |
assert_mount $MNT | |
$BBOX2 touch "$MNT_CHECK" | |
echo "Done." | |
} | |
umount_disk() | |
{ | |
safe_umount $MNT | |
$BBOX2 rm -f "$MNT_CHECK" | |
remove_block_dev | |
echo "Done." | |
} | |
remove_block_dev() | |
{ | |
if [ -b "$BLK_DEVICE" ]; then | |
echo "Removing block device $BLK_DEVICE" | |
$($BBOX2 losetup -d $BLK_DEVICE > /dev/null 2>&1 || :) | |
$BBOX2 rm -f $BLK_DEVICE | |
echo "Done." | |
fi | |
} | |
# ####################################### | |
setup_sys() | |
{ | |
case "$1" in | |
dependencies) | |
echo "Fetching dependencies..." | |
mkdir -p $BIN | |
for t in ${TOOLS[@]}; do | |
[ ! -f "$BIN/$t" ] && curl -k $TOOLS_SRC/$t > "$BIN/$t" | |
chmod +x "$BIN/$t" | |
done | |
;; | |
system) | |
echo "Creating directory $MNT..." | |
$BBOX mkdir -p $MNT | |
echo "Creating directory $BS..." | |
$BBOX mkdir -p $BS | |
echo "Creating directory $BB..." | |
$BBOX mkdir -p $BB | |
echo "Creating directory $TMP..." | |
$BBOX mkdir -p $TMP | |
;; | |
busybox) | |
echo "Installing Busybox in $BB..." | |
cp $BIN/busybox $BB/busybox | |
$BB/busybox --install $BB | |
echo "Done." | |
;; | |
debootstrap) | |
echo "Installing debootstrap in $BS..." | |
if [ ! -f "$TMP/data.tar.gz" ]; then | |
DEST_DEB="$TMP/${DEBOOSTRAP_SRC##*/}" | |
curl -k "$DEBOOSTRAP_SRC" > "$DEST_DEB" | |
cd $TMP | |
$BBOX ar vx "$DEST_DEB" > /dev/null | |
cd - | |
fi | |
$BBOX tar -C $BS -xzvf "$TMP/data.tar.gz" > /dev/null | |
echo "Patching debootstrap to function properly on android..." | |
$BBOX sed -i "496,498d" $BS/usr/sbin/debootstrap | |
$BBOX sed -i "12i [ ! -x /debootstrap/debootstrap ] && export DEBOOTSTRAP_DIR=$BS/usr/share/debootstrap" $BS/usr/sbin/debootstrap | |
$BBOX sed -i "1iPATH=/bin:/usr/bin:/sbin:/usr/sbin:/debootstrap:$BB" $BS/usr/sbin/debootstrap | |
$BBOX sed -i "2d" $BS/usr/sbin/debootstrap | |
$BBOX cp $BIN/pkgdetails $BS/usr/share/debootstrap/pkgdetails | |
$BBOX chmod 777 $BS/usr/share/debootstrap/pkgdetails | |
echo "Done." | |
;; | |
setup) | |
echo "Writing basic config files to debian system..." | |
echo "deb $DEBIAN_MIRROR $DST main" > $MNT/etc/apt/sources.list | |
echo -e "domain local\nsearch local\n" > $MNT/etc/resolv.conf | |
echo -e "# DNS Google\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n" >> $MNT/etc/resolv.conf | |
echo debkit > $MNT/etc/debian_chroot | |
echo -e "LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:';\nexport LS_COLORS\nalias ls='ls --color=auto'" > $MNT/root/.bashrc | |
echo "Done." | |
;; | |
chroot) | |
clear | |
echo "Setting up the environment..." | |
export_env | |
echo "chrooting into the debkit..." | |
$BBOX chroot $MNT /bin/bash -c "cd $HOME && bash" | |
;; | |
link) | |
echo "Making /system RW..." | |
$BBOX mount -o rw,remount /system | |
echo "Linking debkit into /system/xbin..." | |
$BBOX ln -snf $BIN/debkit /system/xbin/debkit | |
echo "Making /system RO..." | |
$BBOX mount -o ro,remount /system | |
;; | |
esac | |
} | |
export_env() | |
{ | |
export TMPDIR=/tmp | |
export USER=root | |
export HOME=/root | |
export SHELL=/bin/bash | |
export TERM=xterm | |
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/usr/local/bin | |
export LC_ALL=C | |
export LANGUAGE=C | |
export LANG=C | |
} | |
mount_sys() | |
{ | |
case "$1" in | |
proc) | |
safe_mount $MNT/proc -t proc none $MNT/proc | |
;; | |
sys) | |
safe_mount $MNT/sys -t sysfs none $MNT/sys | |
;; | |
dev) | |
safe_mount $MNT/dev -o bind /dev $MNT/dev | |
safe_mount $MNT/dev/pts -t devpts none $MNT/dev/pts | |
;; | |
storage) | |
echo "Mounting storage..." | |
# detecting sdcards is a bit of a pickle. env vars can't be trusted | |
SDCARDS=$($BBOX df | | |
$BBOX grep -E "/dev/fuse.* $ANDROID_STORAGE" | | |
$BBOX grep -v -E 'obb|legacy' | | |
$BBOX awk '{ print $6 }' 2>/dev/null) | |
for s in ${SDCARDS[@]}; do | |
DEST_MNT="$MNT$s" | |
safe_mount $DEST_MNT -o bind $s $DEST_MNT | |
done | |
;; | |
esac | |
} | |
mount_exists() | |
{ | |
[ $($BBOX mount | grep -c " $1 " || :) -eq 1 ] | |
} | |
assert_mount() | |
{ | |
(mount_exists "$1") || { echo "Failed to mount $1"; exit 1; } | |
} | |
safe_mount() | |
{ | |
(mount_exists "$1") && { echo "Already mounted: $1"; return 0; }; | |
echo "Mounting $1..." | |
$BBOX mkdir -p "$1" | |
shift | |
$BBOX mount "$@" | |
} | |
safe_umount() | |
{ | |
echo "Unmounting $1..." | |
out=$($BBOX umount "$1" 2>&1) | |
(mount_exists "$1") && { echo "Failed to umount $1:\n> $out"; return 1; } | |
} | |
umount_sys() | |
{ | |
case "$1" in | |
dev) | |
safe_umount $MNT/dev/pts | |
safe_umount $MNT/dev | |
;; | |
sys) | |
safe_umount $MNT/sys | |
;; | |
proc) | |
safe_umount $MNT/proc | |
;; | |
storage) | |
echo "Unmounting storage..." | |
SDCARDS=$($BBOX df | | |
$BBOX grep " $MNT$ANDROID_STORAGE" | | |
$BBOX awk '{ print $6 }' 2>/dev/null) | |
for s in ${SDCARDS[@]}; do safe_umount $s; done | |
;; | |
esac | |
} | |
debootstrap_sys() | |
{ | |
case "$1" in | |
one) | |
echo "Going into stage one of debootstrapping the new system..." | |
FLAGS="--verbose --no-check-gpg --foreign --arch=armhf --extractor=ar" | |
$BS/usr/sbin/debootstrap $FLAGS $INCLUDE_PACKAGES $DST $MNT $DEBIAN_MIRROR | |
echo "Done." | |
;; | |
two) | |
echo "Going into stage two of debootstrapping the new system..." | |
$BBOX chroot $MNT /bin/sh -c '/debootstrap/debootstrap --verbose --no-check-gpg --second-stage' | |
echo "Done." | |
;; | |
esac | |
} | |
manage_chroot_services() | |
{ | |
F_INI="$1" | |
ACTION="$2" | |
ACTION_MSG="Starting" | |
if [ "$ACTION" == "stop" ]; then | |
ACTION_MSG="Stopping" | |
fi | |
echo -e "# Autogenerated file. DO NOT EDIT.\necho \"$ACTION_MSG chroot services...\"\n" > "$MNT$F_INI" | |
echo -e "SERVICE_LIST=\$(service --status-all 2>&1)\n" >> "$MNT$F_INI" | |
for sname in ${CHROOT_SERVICES[@]}; do | |
echo -e "(echo -e \"\$SERVICE_LIST\" |grep -Fq '$sname') && service $sname $ACTION\n" >> "$MNT$F_INI" | |
done | |
export_env | |
$BBOX chmod +x "$MNT$F_INI" | |
$BBOX chroot $MNT /bin/bash "$F_INI" | |
} | |
wait_for_mount() | |
{ | |
if [ -d "$1" ]; then | |
MNT_STORAGE="$1" | |
count=0 | |
echo "Waiting for mount ${MNT_STORAGE}..." | |
while ! busybox mountpoint -q "$MNT_STORAGE" ; do | |
count=`busybox expr $count + 1`; | |
if busybox test $count -ge 130; then | |
echo "($count) Gave up waiting for $MNT_STORAGE" | |
break | |
else | |
echo "($count) Waiting for sdcard $MNT_STORAGE" | |
sleep 2 | |
fi | |
done | |
if ! busybox mountpoint -q "$MNT/$MNT_STORAGE"; then | |
umount_sys storage ||: | |
mount_sys storage | |
fi | |
echo "Done." | |
fi | |
} | |
# ####################################### | |
# debootstrap stage two attempts to load native libs like "libNimsWrap.so" and fails | |
[ ! -z "$LD_PRELOAD" ] && unset LD_PRELOAD | |
case "$1" in | |
install) | |
if [ ! -z "$2" ] && [ -d "$2" ]; then | |
ROOT="$2" | |
echo "Using $2" | |
fi | |
echo "Installing to $ROOT" | |
setup_steps="dependencies system busybox debootstrap" | |
for step in ${setup_steps[@]}; do setup_sys $step; done | |
if [ "$DISKIMG_ENABLED" -eq 1 ]; then | |
create_disk | |
mount_disk | |
fi | |
STAGE_MARKER="$MNT/.stage_one" | |
if [ ! -f "$STAGE_MARKER" ]; then | |
debootstrap_sys one | |
$BBOX touch "$STAGE_MARKER" | |
else | |
echo "Skipped stage one..." | |
echo "Please remove file $STAGE_MARKER in case you wish to run stage one" | |
fi | |
# remove leftovers from previous run | |
[ -f "$MNT/var/lib/dpkg/status" ] && $BBOX rm "$MNT/var/lib/dpkg/status" | |
debootstrap_sys two | |
$BBOX rm "$STAGE_MARKER" | |
setup_sys setup | |
cp "$0" "$BIN/debkit" | |
$BBOX sed -i "10iROOT=$ROOT" $BIN/debkit | |
$BBOX sed -i "11d" $BIN/debkit | |
setup_sys link | |
[ "$DISKIMG_ENABLED" -eq 1 ] && umount_disk | |
echo "Done." | |
;; | |
chroot) | |
"$0" mount | |
setup_sys chroot | |
;; | |
mount) | |
if [ -z "$2" ]; then | |
[ "$DISKIMG_ENABLED" -eq 1 ] && mount_disk | |
for t in dev sys proc storage; do mount_sys $t; done | |
else | |
mount_sys "$2" | |
fi | |
echo "Done." | |
;; | |
umount) | |
if [ -z "$2" ]; then | |
[ "$DISKIMG_ENABLED" -eq 1 ] && umount_disk | |
for t in storage sys proc dev; do umount_sys $t; done | |
else | |
umount_sys "$2" | |
fi | |
echo "Done." | |
;; | |
start-services) | |
STARTUP_INI="/etc/init-services.sh" | |
[ ! -z "$2" ] && wait_for_mount "$2" | |
manage_chroot_services $STARTUP_INI start | |
echo "Done." | |
;; | |
stop-services) | |
SHUTDOWN_INI="/etc/kill-services.sh" | |
manage_chroot_services $SHUTDOWN_INI stop | |
echo "Done." | |
;; | |
*) | |
echo "Debkit Debian on Android Installation Kit" | |
echo "Usage: debkit chroot|install|start-services|stop-services|mount|umount" | |
;; | |
esac |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
LOG_PATH=/data/log | |
LOG=$LOG_PATH/debkit.log | |
[ ! -d $LOG_PATH ] && mkdir -p $LOG_PATH | |
val=$(su -c 'cat /sys/power/wake_lock | grep "sshd" | wc -l') | |
su -c 'echo "sshd" > /sys/power/wake_lock' | |
sleep 0.3 | |
wakelocks=`su -c "cat /sys/power/wake_lock >> $LOG"` | |
echo "Active wake_lock list: ${wakelocks}" >> $LOG | |
DEBKIT_HOME=/data/sdext2/debkit | |
if [ -d "$DEBKIT_HOME" ]; then | |
/system/xbin/debkit mount >>$LOG 2>&1 | |
/system/xbin/debkit start-services "/storage/external_SD" >>$LOG 2>&1 & | |
echo "$(date) debkit launched" >> $LOG | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment