Skip to content

Instantly share code, notes, and snippets.

@shirish87
Last active Oct 19, 2016
Embed
What would you like to do?
Install Debian (jessie) chroot on Android
#!/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
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