From Newsgroup: alt.os.linux
PSA: How to type ADB commands on your phone instead of on your PC.
This tutorial shows desktop folks how to remove the laptop/desktop
(whether macOS, Linux, or Windows) from the adb linux equation.
Note that Termux/Remote-interactive-shell (rish), localadb (ladb)
and ShizuShell are all effectively the same thing, where each
can run the same ADB linux commands locally on Android sans the PC.
I've already written a tutorial for building ladb from source, and
I've written a tutorial for installing ShizuShell instead of Termux.
Therefore, this is a tutorial for installing and using Termux/risha
(remote interactive shell) to run the same adb commands, which youa
normally would run connected to the desktop over Wi-Fi or USB, but,
with this tutorial, you can now omit the desktop & still use adb.
The problem turning Termux into an adb-capable terminal emulator...a
a. Shizuku runs a background service daemon with shell privileges.a
b. But Termux is blocked from running system commands, by default.
c. So this remote interactive shell installation fixes that problem.
If you know *exactly* how to do it, it's probably worth doing
because it allows you to run all your adb commands, without the PC.
However... there is an unholy labyrinth of traps such as copy/paste issues,a permissions issues, buffer limitations, obnoxious Termux side drawers, etc.
An example is Termux has an obnoxious side drawer that attacks you whena
you're just trying to copy, and worse, Termux won't accept a paste froma
scrcpy keyboards unless you know enough to change scrcpy invocation from
aC:\> scrcpy --keyboard=sdk
a a a to
a C:\> scrcpy --legacy-paste
It's an OMfG experience, if you're doing it sans good instructions.
But it's trivial to set up, if you already know how to do it.
Here is a straightforward, mostly sane way to survive the gauntlet.
[Some things are so ungodly crazy that you need a tutorial to do them.]
Bear in mind that Termux is just an unprivileged app sandboxed by Android, where Shizuku opens the backend door via its binder daemon, and rish actsa
as the bridge so that we can pass text commands through it sans a PC. .
Step 1: Export the files from Shizuku
a a a a Instead of manually typing scripts or fighting multi-line pastea
a a a a buffers in Termux, let Shizuku generate the base rish files
a a a a A. Open the Shizuku app on the phone.
a a a a B. Tap "Use Shizuku in terminal apps".
a a a a C. Tap "Export files" and choose an accessible folder on the device.
a a a a a aThis exports two files:
a a a a a aa. A helper script, see below.
a a a a a a a Name: rish
a a a a a a a Size: 882 bytes
a a a a a a a SHA256: 3B01B0CC72CFAD779BFF56EFC29E6AD30AAA9B3969AA349CDF2AA5F876BF2066
a a a a a ab. A Java background handler
a a a a a a a Name: rish_shizuku.dex
a a a a a a a Size: 6828 bytes (6 KiB)
a a a a a a a SHA256: 3AA6AD7B64796C54DAA1FB6D5A046495513466166E87E5739967D5A4C565560E
a a a aI exported to an existing directory:
a a a a a a a /storage/emulated/0/0000/apk/risha
a a a a a a a /storage/emulated/0/0000/apk/rish/rish_shizuku.dex
Step 2: Grant storage access because Termux cannot use shared storage.a
a a a a A. Open Termux on the phone
a a a a B. Run this command and accept the system prompt:
a a a a a a $ termux-setup-storage
a a a a C. Follow prompts
Step 3: Obtain & run the community-created installer.
a a a a A. Run this in Termux while connected to the Internet
a a a a a a $ curl -fsSL tinyurl.com/rish3266 | sh
a a a a B. Follow the prompts inside of Termux
a a a a C. When it asks you to select source, choose "1"a
a a a a a a(Offline / Extract app).a
a a aWhere the "curl" downloads "tinyurl.com/rish3266" hosted by merbah3266
a a aon Github and where fsSL flags tell curl to be quiet, and to follow
a a aweb redirects if the link changes & fail silently if the network errors
a a aand where the pipe to sh feeds it into the shell interpreter so that
a a ait executes immediately, saving us time given Termux copy/paste/typing
a a ais essentially atrocious.
a a aNote the rish remote interactive shell is the official companion toola
a a abuilt by the Shizuku developer team (RikkaApps) specifically designeda
a a ato let terminal apps like Termux tap into Shizuku's ADB/shell bridge.
a a aThe script will automatically pull the assets from your installeda
a a aShizuku app, drop them into Termux's binary folder ($PREFIX/bin)
a a aand configure rish.
a a aHere is what the script is doing step-by-step under the hood:
a a a1. Safety Check:a
a a a a It makes sure we aren't accidentally running it as the systema
a a a a root user (which would break things).
a a a2. Menu Prompt:a
a a a a It asks you how we want to get the Shizuku filesa
a a a a (e.g., pulling them directly from the Shizuku app alreadya
a a a a installed on the phone, or downloading them from GitHub).
a a a3. Dependency Check:a
a a a a It checks if tools like unzip and sed are available, and if not,a
a a a a it automatically downloads a lightweight utility called BusyBoxa
a a a a so it can still do its job.
a a a4. Extraction:a
a a a a It unpacks the Shizuku APK to pull out the two critical filesa
a a a a (rish and rish_shizuku.dex).
a a a5. Installation:a
a a a a It automatically copies those files into Termux's system binarya
a a a a folder ($PREFIX/bin), sets the correct executable permissionsa
a a a a (chmod), and creates handy shortcuts so you we just type
a a a a rish from anywhere.
Step 4: Once the installation finishes, we are ready to test it.
a a a a A. Type the new shortcut command:
a a a a a a$ rish
a a a a B. A popup will ask "Allow Termux to access Shizuku".a
a a a a C. Tap "Allow all the time".
a a a a Note: This error is apparently bogus:
a a a a Request timeout. The connection between the current appa
a a a a and Shizuku app may be blocked...
a a a a This is apparently a false alarm caused by Shizuku's 5-seconda
a a a a handshake timer getting bogged down the first time it wakes up.a
a a a a Simply repeat the typing of "rish" a second time:
Step 5. The prompt will change from "~ $" to something like "a32x:/ $".a
a a a a A. Check elevated status
a a a a a aa32x:/ $ whoamia
a a a a a a a a a We should see "shell"
a a a a B. Read a restricted system property
a a a a a a32x:/ $ getprop ro.serialno
a a a a a a a a aWe should see our phone hardware serial number.
a a a aC. Check system process ownership
a a a a a a32x:/ $ ps -AZ | grep shell
a a a a a a a a aWe should see active system processesa
a a a a a a a a afiltered for the shell context, e.g.,a
a a a a a a a a au:r:shell:s0 shell 28060 1 shizuku_server
Voila!
a a a aThis means Termux & Shizuku are bridged, bypassing Android
a a a asandboxing, without needing a full device root.
The rish bridge is talking to the shizuku_server, running undera
the true shell security context, bypassing the normal app sandbox.
REFERENCE FILES:
a ----- < below is rish > -----
a #!/system/bin/sh
a BASEDIR=$(dirname "$0")
a DEX="$BASEDIR"/rish_shizuku.dex
aa
a if [ ! -f "$DEX" ]; then
a a echo "Cannot find $DEX, please check the tutorial in Shizuku app"
a a exit 1
a fi
aa
a if [ $(getprop ro.build.version.sdk) -ge 34 ]; then
a a if [ -w $DEX ]; then
a a a echo "On Android 14+, app_process cannot load writable dex."
a a a echo "Attempting to remove the write permission..."
a a a chmod 400 $DEX
a a fi
a a if [ -w $DEX ]; then
a a a echo "Cannot remove the write permission of $DEX."
a a a echo "You can copy to file to terminal app's private directory (/data/data/<package>, so that remove write permission is possible"
a a a exit 1
a a fi
a fi
aa
a # Replace "PKG" with the application id of your terminal app
a [ -z "$RISH_APPLICATION_ID" ] && export RISH_APPLICATION_ID="PKG"
a /system/bin/app_process -Djava.class.path="$DEX" /system/bin --nice-name=rish rikka.shizuku.shell.ShizukuShellLoader "$@"
a ----- < above is rish > -----
a ----- < below is the Shizuku rish installer > ------
a exec 2>/dev/null
a BIN="$(dirname "$(command -v bash)")"
a RISH="$BIN/rish"; DEX="$BIN/rish_shizuku.dex"
a ACTION="install"; SILENT_MODE=0; SOURCE_MODE="default"; SOURCE_PATH=""; SOURCE_PROVIDED=0
aa
a if [ "$(id -u)" -eq 0 ]; then
a a a printf "\033[1;31m[x]\033[0m Please do not run this as root!\n" >&2
a a a exit 1
a fi
aa
a while [ $# -gt 0 ]; do
a a case "$1" in
a a a --uninstall) ACTION="uninstall" ;;
a a a --reinstall) ACTION="reinstall" ;;
a a a --silent) SILENT_MODE=1 ;;
a a a --source=*) SOURCE_MODE="${1#*=}"; SOURCE_PROVIDED=1 ;;
a a a --source) shift; SOURCE_MODE="$1"; SOURCE_PROVIDED=1 ;;
a a a --path=*) SOURCE_PATH="${1#*=}" ;;
a a a --path) shift; SOURCE_PATH="$1" ;;
a a esac
a a shift
a done
aa
a if [ -t 1 ]; then
a a C0='\033[0m'
a a CR='\033[1;31m'
a a CG='\033[1;32m'
a a CY='\033[1;33m'
a a CB='\033[1;34m'
a a CC='\033[1;36m'
a else
a a C0=''
a a CR=''
a a CG=''
a a CY=''
a a CB=''
a a CC=''
a fi
aa
a cancel(){ echo -e "${CY}[!]${C0} $1"; exit 0; }
a msg(){ [ "$SILENT_MODE" -eq 0 ] && echo -e "${CB}[i]${C0} $1"; }
a ok(){ [ "$SILENT_MODE" -eq 0 ] && echo -e "${CG}[+]${C0} $1"; }
a warn(){ [ "$SILENT_MODE" -eq 0 ] && echo -e "${CY}[!]${C0} $1"; }
a err(){ echo -e "${CR}[x]${C0} $1"; exit 1; }
a step(){ [ "$SILENT_MODE" -eq 0 ] && echo -e "${CC}==>${C0} $1"; }
aa
a cleanup() {
a a a [ -n "$TMP_SUBDIR" ] && rm -rf "$TMP_SUBDIR"
a }
aa
a on_cancel() {
a a a echo -e "\n${CY}[!]${C0} Operation cancelled by user."
a a a exit 1
a }
aa
a trap on_cancel INT
a trap cleanup EXIT
aa
a if [ "$ACTION" = "uninstall" ]; then
a a rm -f "$RISH" "$DEX" "$HOME/rish" "$HOME/rish_shizuku.dex"
a a find "$HOME" -maxdepth 1 -type l -name "rish*" -delete || true
a a echo -e "${CG}[+]${C0} rish has been removed."
a a exit 0
a fi
aa
a detect_pkg(){
a a p="${PREFIX:-$(pwd)}"
a a case "$p" in
a a a /data/data/*)
a a a a echo "${p#/data/data/}" | cut -d/ -f1
a a a a return
a a a a ;;
a a a /data/user/*)
a a a a echo "$p" | cut -d/ -f5
a a a a return
a a a a ;;
a a esac
aa
a a if [ -n "$HOME" ]; then
a a a case "$HOME" in
a a a a /data/data/*)
a a a a a echo "${HOME#/data/data/}" | cut -d/ -f1
a a a a a return
a a a a a ;;
a a a a /data/user/*)
a a a a a echo "$HOME" | cut -d/ -f5
a a a a a return
a a a a a ;;
a a a esac
a a fi
aa
a a echo "unknown"
a }
aa
a PKG="$(detect_pkg)"
a [ "$PKG" = "unknown" ] && err "Package detect failed"
aa
a if [ -f "$RISH" ] && [ "$ACTION" != "reinstall" ] && [ "$SILENT_MODE" -eq 0 ]; then
a a echo -ne "${CY}[?]${C0} rish installed. Reinstall? [y/N]: "
a a read -r c < /dev/tty
a a case "$c" in
a a a y|Y) ACTION="reinstall" ;;
a a a *) cancel "Cancelled."; exit 0 ;;
a a esac
a fi
aa
a if [ "$SILENT_MODE" -eq 0 ] && [ "$SOURCE_PROVIDED" -eq 0 ]; then
a a echo -e "\n${CB}Select source:${C0}\n 1) Offline (Extract app)\n 2) RikkaApps/Shizuku\n 3) thedjchi/Shizuku\n 4) Custom Repo\n 5) Direct URL\n 6) Local APK"
a a printf "Choice [1-6]: "
a a read src_choice < /dev/tty
aa
a a case "$src_choice" in
a a a 1) SOURCE_MODE="local_app" ;;
a a a 2) SOURCE_MODE="default" ;;
a a a 3) SOURCE_MODE="thedjchi" ;;
a a a 4)
a a a a SOURCE_MODE="custom_repo"
a a a a printf "Repo (user/repo): "
a a a a read SOURCE_PATH < /dev/tty
a a a a ;;
a a a 5)
a a a a SOURCE_MODE="custom_url"
a a a a printf "URL: "
a a a a read SOURCE_PATH < /dev/tty
a a a a ;;
a a a 6)
a a a a SOURCE_MODE="local_file"
a a a a printf "Path: "
a a a a read SOURCE_PATH < /dev/tty
a a a a ;;
a a a *)
a a a a cancel "Invalid choice. Cancelled."
a a a a ;;
a a esac
a fi
aa
a [ "$SILENT_MODE" -eq 1 ] && echo -e "${CG}[+]${C0} Starting silent rish installation..."
aa
a RAND_ID="$RANDOM"
a TMP_SUBDIR="${TMPDIR:-/tmp}/rish.$RAND_ID"
a mkdir -p "$TMP_SUBDIR"
aa
a PLAN_A=1
a for t in unzip sed grep install; do
a a command -v "$t" >/dev/null 2>&1 || PLAN_A=0
a done
aa
a if [ "$PLAN_A" -eq 1 ]; then
a a UNZIP=unzip
a a SED=sed
a a GREP=grep
a a INSTALL=install
a else
a a warn "Using busybox"
aa
a a ARCH="$(uname -m)"
a a case "$ARCH" in
a a a aarch64|arm64|armv8*) ARCH=arm64 ;;
a a a armv*|armhf|arm) ARCH=arm ;;
a a a x86_64|amd64) ARCH=x86_64 ;;
a a a i386|i686|x86) ARCH=x86 ;;
a a a *) err "Unsupported arch" ;;
a a esac
aa
a a BB="$TMP_SUBDIR/busybox"
a a step "Downloading BusyBox..."
aa
a a curl -fsSL "
https://raw.githubusercontent.com/merbah3266/rish_installer/main/busybox/$ARCH/busybox" -o "$BB" || err "BB download failed"
aa
a a chmod +x "$BB"
aa
a a UNZIP="$BB unzip"
a a SED="$BB sed"
a a GREP="$BB grep"
a a INSTALL="$BB install"
aa
a a ok "BusyBox ready."
a fi
aa
a APK_PATH="$TMP_SUBDIR/app.apk"
a OFFLINE_OK=0
aa
a if [ "$SOURCE_MODE" = "local_app" ] || [ "$SOURCE_MODE" = "default" ]; then
a a step "Offline attempt..."
aa
a a EXTRACTED="$(cmd package path moe.shizuku.privileged.api --user 0 2>/dev/null | cut -d: -f2)"
aa
a a if [ -n "$EXTRACTED" ] && cp "$EXTRACTED" "$APK_PATH" 2>/dev/null; then
a a a ok "Local APK extracted"
a a a OFFLINE_OK=1
a a elif [ "$SOURCE_MODE" = "local_app" ]; then
a a a cancel "Shizuku not found locally. Cancelled."
a a else
a a a warn "Offline failed, falling back online..."
a a fi
a fi
aa
a if [ "$OFFLINE_OK" -eq 0 ]; then
a a case "$SOURCE_MODE" in
a a a local_file)
a a a a step "Using local file"
a a a a [ -z "$SOURCE_PATH" ] && cancel "No path provided. Cancelled."
a a a a [ ! -f "$SOURCE_PATH" ] && cancel "File not found. Cancelled."
a a a a cp "$SOURCE_PATH" "$APK_PATH" || cancel "Copy failed. Cancelled."
a a a a ok "Copied"
a a a a ;;
aa
a a a custom_url)
a a a a step "Downloading from URL"
a a a a [ -z "$SOURCE_PATH" ] && cancel "No URL provided. Cancelled."
a a a a curl -fsSL -o "$APK_PATH" "$SOURCE_PATH" || cancel "Download failed. Cancelled."
a a a a ok "Downloaded"
a a a a ;;
aa
a a a default|thedjchi|custom_repo)
a a a a if [ "$SOURCE_MODE" = "default" ]; then
a a a a a REPO="RikkaApps/Shizuku"
a a a a elif [ "$SOURCE_MODE" = "thedjchi" ]; then
a a a a a REPO="thedjchi/Shizuku"
a a a a else
a a a a a REPO="$SOURCE_PATH"
a a a a fi
aa
a a a a [ -z "$REPO" ] && cancel "No repo provided. Cancelled."
aa
a a a a step "Fetching from $REPO..."
aa
a a a a URL="$(curl -fsSL "
https://api.github.com/repos/$REPO/releases/latest" | sed -n 's/.*"browser_download_url":[[:space:]]*"\([^"]*\.apk\)".*/\1/p')"
aa
a a a a [ -z "$URL" ] && cancel "URL fetch failed. Cancelled."
aa
a a a a step "Downloading APK..."
a a a a curl -fsSL -o "$APK_PATH" "$URL" || cancel "Download failed. Cancelled."
a a a a ok "Downloaded"
a a a a ;;
aa
a a a *)
a a a a cancel "Invalid source. Cancelled."
a a a a ;;
a a esac
a fi
aa
a step "Extracting..."
a $UNZIP -qq "$APK_PATH" -d "$TMP_SUBDIR" || err "Unzip failed"
aa
a [ ! -f "$TMP_SUBDIR/assets/rish" ] && err "rish not found"
a [ ! -f "$TMP_SUBDIR/assets/rish_shizuku.dex" ] && err "dex not found"
aa
a SH_PATH="$(command -v sh)"
a [ -z "$SH_PATH" ] && err "sh not found"
aa
a TMP_RISH="$TMP_SUBDIR/rish.$RAND_ID"
aa
a echo "#!$SH_PATH" > "$TMP_RISH"
a $GREP -v '^#' "$TMP_SUBDIR/assets/rish" >> "$TMP_RISH"
a $SED -i "s/PKG/$PKG/g" "$TMP_RISH"
aa
a step "Installing..."
a INSTALL_SUCCESS=0
aa
a if $INSTALL -m755 "$TMP_RISH" "$RISH" 2>/dev/null &&
a a a$INSTALL -m400 "$TMP_SUBDIR/assets/rish_shizuku.dex" "$DEX" 2>/dev/null; then
a a ok "Installed to bin ($BIN)"
a a ln -sf "$RISH" "$HOME/rish" 2>/dev/null
a a ln -sf "$DEX" "$HOME/rish_shizuku.dex" 2>/dev/null
a a INSTALL_SUCCESS=1
a else
a a warn "Bin failed, trying Home..."
aa
a a if $INSTALL -m755 "$TMP_RISH" "$HOME/rish" 2>/dev/null &&
a a a a$INSTALL -m400 "$TMP_SUBDIR/assets/rish_shizuku.dex" "$HOME/rish_shizuku.dex" 2>/dev/null; then
a a a ok "Installed to Home"
a a a INSTALL_SUCCESS=1
a a fi
a fi
aa
a if [ "$INSTALL_SUCCESS" -eq 1 ]; then
a a [ "$SILENT_MODE" -eq 1 ] &&
a a a echo -e "${CG}[+]${C0} Success: rish installed." ||
a a a ok "Setup complete. Run 'rish' or '~/rish'"
a else
a a err "Installation failed"
a fi
a ----- < above is the Shizuku rish installer > ------
SOFTWARE:
*Termux* by Fredrik Fornwall
<
https://packages.termux.dev/>
<
https://github.com/termux/termux-app>
<
https://f-droid.org/en/packages/com.termux/>
<
https://f-droid.org/repo/com.termux_118.apk>
Warning: Google Play versions of Termux are deprecated:
<
https://play.google.com/store/apps/details?id=com.termux>
Rish (remote interactive shell) installer
<
https://github.com/merbah3266/rish_installer>
*Shizuku* by Xingchen & Rikka
<
https://github.com/RikkaApps/Shizuku>
<
https://play.google.com/store/apps/details?id=moe.shizuku.privileged.api>
*ShizuShell* by Nindle Studio
<
https://play.google.com/store/apps/details?id=com.noxinfinity.shell>
Local adb
<
https://github.com/tytydraco/LADB>
<
https://play.google.com/store/apps/details?id=com.draco.ladb>
As always, please correct where I err and add value where I omit.
--a
Some things are so unintuitive that you need a tutorial to do them.
--- Synchronet 3.22a-Linux NewsLink 1.2