#!/usr/bin/env bash
# ==========================
# Termux Sandbox Script
# ==========================
# This script creates a localized, Termux-like sandbox using proot, designed to
# provide an isolated, ephemeral Termux environment within the ~/sandbox-termux
# directory. It mimics a clean Termux installation and is ideal for testing.
#
# Features:
# - Start, reset, and destroy the sandbox.
# - Bind /sdcard for minimal external storage access (optional).
# - Pre-install default Termux packages to mimic a clean Termux environment.
# - Sets up all necessary Termux-specific environment variables.
#
# Dependencies: proot
#
# Usage:
# ./sandbox-termux.sh [options]
# Options:
# start Start the sandbox and drop into a shell
# destroy Destroy the sandbox environment
# reset Reset the sandbox, re-initializing both usr and home
# -s, --sdcard Bind /sdcard for external storage access (optional)
# -h, --help Show this help message and exit
# ==========================
# Global variables
# ==========================
SANDBOX_DIR="$HOME/sandbox-termux"
SANDBOX_HOME="${SANDBOX_DIR}/home"
BIND_SDCARD=false
TERMUX_USR="/data/data/com.termux/files/usr" # Shared root directory
# ==========================
# Functions
# ==========================
# Show usage information
function print_usage() {
cat <<EOF
Usage: $(basename "$0") [start|destroy|reset] [options]
Options:
start Start the Termux sandbox and drop into a shell
destroy Destroy the sandbox environment
reset Reset the sandbox (delete and recreate both usr and home)
-s, --sdcard Bind /sdcard to access external storage within the sandbox
-h, --help Show this help message and exit
Examples:
./sandbox-termux.sh start -s
./sandbox-termux.sh destroy
./sandbox-termux.sh reset
EOF
}
# Initialize the standard shell configuration files
function initialize_shell_config() {
# Ensure .bashrc, .profile, and .bash_logout exist
cat > "${SANDBOX_HOME}/.bashrc" << 'EOF'
# .bashrc for Termux sandbox
export PATH="$PREFIX/bin:$PATH"
export LD_LIBRARY_PATH="$PREFIX/lib"
export TERM=xterm-256color
alias ls='ls --color=auto'
alias ll='ls -la'
EOF
cat > "${SANDBOX_HOME}/.profile" << 'EOF'
# .profile for Termux sandbox
if [ -n "$BASH" ]; then
# Source .bashrc if present
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
export HOME="$HOME"
export PREFIX="$HOME/../usr"
export PATH="$PREFIX/bin:$PATH"
export TMPDIR="$PREFIX/tmp"
EOF
cat > "${SANDBOX_HOME}/.bash_logout" << 'EOF'
# .bash_logout for Termux sandbox
# Clean up temporary files on logout
EOF
# Ensure tmp directory exists inside the sandbox (in this case, shared with host Termux)
mkdir -p "${TERMUX_USR}/tmp"
}
# Create the initial sandbox directory structure
function initialize_sandbox() {
echo "Initializing sandbox directory structure..."
# Create sandbox home directory
mkdir -p "${SANDBOX_HOME}"
# Initialize the standard shell configuration files
initialize_shell_config
echo "Sandbox initialization complete."
}
# Start the sandbox environment
function start_sandbox() {
if [[ ! -d "${SANDBOX_HOME}" ]]; then
echo "Sandbox home directory not found. Initializing sandbox..."
initialize_sandbox
fi
# Prepare proot command with appropriate bindings
PROOT_CMD="proot --link2symlink -r ${TERMUX_USR} -b ${SANDBOX_HOME}:/data/data/com.termux/files/home -b /dev/ -b /proc/ -b /sys/"
# Bind external storage (/sdcard) if requested
if [[ "${BIND_SDCARD}" == true ]]; then
PROOT_CMD="${PROOT_CMD} -b /sdcard"
echo "Binding /sdcard to sandbox environment."
fi
echo "Starting Termux sandbox..."
${PROOT_CMD} /usr/bin/env -i HOME="/data/data/com.termux/files/home" TERM="$TERM" \
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin \
PREFIX="${TERMUX_USR}" \
LD_LIBRARY_PATH="${TERMUX_USR}/lib" \
TMPDIR="${TERMUX_USR}/tmp" \
/bin/bash --login
}
# Destroy the sandbox environment
function destroy_sandbox() {
if [[ -d "${SANDBOX_DIR}" ]]; then
echo "Destroying Termux sandbox..."
rm -rf "${SANDBOX_DIR}"
echo "Sandbox destroyed."
else
echo "No sandbox directory found. Nothing to destroy."
fi
}
# Reset the sandbox environment by destroying and recreating it
function reset_sandbox() {
echo "Resetting Termux sandbox..."
destroy_sandbox
start_sandbox
}
# ==========================
# Argument Parsing
# ==========================
# Parse command line options and arguments
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
start|destroy|reset)
ACTION="$1"
shift
;;
-s|--sdcard)
BIND_SDCARD=true
shift
;;
-h|--help)
print_usage
exit 0
;;
*)
echo "Unknown option: $1"
print_usage
exit 1
;;
esac
done
# ==========================
# Main Logic
# ==========================
if [[ -z "${ACTION}" ]]; then
echo "Error: No action specified."
print_usage
exit 1
fi
case "${ACTION}" in
start)
start_sandbox
;;
destroy)
destroy_sandbox
;;
reset)
reset_sandbox
;;
*)
echo "Error: Invalid action '${ACTION}'."
print_usage
exit 1
;;
esac
This is my fifth script iteraton. I am not yet a proficient shell scripter, but I am aspiring to be a better scripter and become adept, and wish to contribute to the Termux community in future. I am still learning how Termux works. This project is to help make a testing environment for my own scripts, modules and packages, as well as an environment for testing post-patching compilation and builds of third-party projects for possible inclusion in the Termux repository. This sandbox script is endeavouring to be an addition and companion to Android Studio, which I am running in a proot chroot alias of Debian GNU/Linux.