From Newsgroup: comp.sys.mac.system
PSA: How to type ADB commands on our phones instead of on our PCs.
This tutorial shows desktop folks how to remove the laptop/desktop
(whether macOS, Linux, or Windows) from the Android adb 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 commands locally on Android without 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/rish
(remote interactive shell) to run the same adb commands, which we
normally would run connected to the desktop over Wi-Fi or USB, but,
with this tutorial, we can now omit the desktop & still use adb.
The problem turning Termux into an adb-capable terminal emulator...
a. Shizuku runs a background service daemon with shell privileges.
b. But Termux is blocked from running system commands, by default.
c. So this remote interactive shell installation fixes that problem.
If we know *exactly* how to do it, it's probably worth doing
because it allows us to run all our adb commands, without the PC.
However there is an unholy labyrinth of traps such as copy/paste issues, permissions issues, buffer limitations, obnoxious Termux side drawers, etc.
An example is Termux has an obnoxious side drawer that attacks us when
we're just trying to copy. Worse, Termux won't accept a long paste from
scrcpy keyboards unless we know enough to change scrcpy invocation from
scrcpy --keyboard=sdk
to
C:\> scrcpy --legacy-paste
It's an OMG experience if we're doing it sans good instructions.
But it's trivial to set up, if we already know how to do it.
Here is a straightforward, mostly sane way to survive the gauntlet.
[Some things are so ungodly crazy that we 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 acts
as the bridge so that we can pass text commands through it sans a PC.
Note: We can choose either a manual Shizuku export from the phone,
or we can choose an automated installer script off the Internet
to install the necessary files inside of the Termux private storage.
Option 1: The Manual Export Method (using Shizuku's built-in export)
Instead of letting an automated script pull the files, we can
manually have Shizuku generate and export the base rish files.
A. Open the Shizuku app on the phone.
B. Tap "Use Shizuku in terminal apps".
C. Tap "Export files" & choose an accessible folder on the device.
This exports two files:
a. A helper script, see below.
Name: rish
Size: 882 bytes
SHA256: 3B01B0CC72CFAD779BFF56EFC29E6AD30AAA9B3969AA349CDF2AA5F876BF2066
b. A Java background handler
Name: rish_shizuku.dex
Size: 6828 bytes (6 KiB)
SHA256: 3AA6AD7B64796C54DAA1FB6D5A046495513466166E87E5739967D5A4C565560E
I had exported to an existing directory on my internal storage named...
/storage/emulated/0/0000/apk/rish
/storage/emulated/0/0000/apk/rish/rish_shizuku.dex
Step 2: Grant storage access (because Termux cannot use shared storage).
A. Open Termux on the phone
B. Run this command and accept the system prompt:
$ termux-setup-storage
C. Follow prompts
Option 2: The Automated Installer Script Method (using curl)
We can let a community-written tested script fetch and configure
everything automatically using the methodology below.
A. Run this in Termux while connected to the Internet:
$ curl -fsSL tinyurl.com/rish3266 | sh
B. Follow the prompts inside of Termux
C. When it asks to select source, choose "1"
(Offline / Extract app) if we want it to pull directly from
our installed Shizuku app package automatically.
That "curl" downloads "tinyurl.com/rish3266" hosted by merbah3266
on GitHub and those fsSL flags tell curl to be quiet and to follow
web redirects if the link changes & to fail silently if the network
errors. The pipe to sh feeds it into the shell interpreter so that
it executes immediately, saving us time and effort (especially
given Termux copy/paste/typing is essentially atrocious).
Note the rish remote interactive shell is the official companion tool
built by the Shizuku developer team (RikkaApps) specifically designed
to let terminal apps like Termux tap into Shizuku's ADB/shell bridge.
That script will automatically pull the assets, drop them into
Termux's binary folder ($PREFIX/bin) and it will configure rish.
Here is what the script is doing step-by-step under the hood:
1. Safety Check:
It makes sure we aren't accidentally running it as the system
root user (which would break things).
2. Menu Prompt:
It asks us how we want to get the Shizuku files
(e.g., pulling them directly from the Shizuku app already
installed on the phone, or downloading them from GitHub).
3. Dependency Check:
It checks if tools like unzip and sed are available, and if not,
it automatically downloads a lightweight utility called BusyBox
so it can still do its job.
4. Extraction:
It unpacks the Shizuku APK to pull out the two necessary files
(rish and rish_shizuku.dex).
5. Installation:
It automatically copies those files into Termux's system binary
folder ($PREFIX/bin), sets the correct executable permissions
(chmod), and creates handy shortcuts so we can just type
rish from anywhere.
Step 4: Once the installation finishes, we are ready to test it.
A. Type the new shortcut command:
$ rish
B. A popup will ask "Allow Termux to access Shizuku".
C. Tap "Allow all the time".
Note: This error is apparently bogus:
Request timeout. The connection between the current app
and Shizuku app may be blocked...
That is apparently a false alarm caused by Shizuku's 5-second
handshake timer getting bogged down the first time it wakes up.
Just repeat the typing of "rish" a second time if that happens.
Step 5. The prompt will change from "~ $" to something like "a32x:/ $".
A. Check elevated status
a32x:/ $ whoami
We should see "shell"
B. Read a restricted system property
a32x:/ $ getprop ro.serialno
We should see our phone hardware serial number.
C. Check system process ownership
a32x:/ $ ps -AZ | grep shell
We should see active system processes
filtered for the shell context, e.g.,
u:r:shell:s0 shell 28060 1 shizuku_server
Voila!
This means Termux & Shizuku are now bridged which means we
bypassed Android sandboxing, without needing a full device
root on my Android 13, non-rooted Samsung Galaxy A32-5G.
The rish bridge is talking to the shizuku_server, running under
the true shell security context, bypassing the normal app sandbox.
REFERENCE FILES:
----- < below is rish > -----
#!/system/bin/sh
BASEDIR=$(dirname "$0")
DEX="$BASEDIR"/rish_shizuku.dex
if [ ! -f "$DEX" ]; then
echo "Cannot find $DEX, please check the tutorial in Shizuku app"
exit 1
fi
if [ $(getprop ro.build.version.sdk) -ge 34 ]; then
if [ -w $DEX ]; then
echo "On Android 14+, app_process cannot load writable dex."
echo "Attempting to remove the write permission..."
chmod 400 $DEX
fi
if [ -w $DEX ]; then
echo "Cannot remove the write permission of $DEX."
echo "You can copy to file to terminal app's private directory (/data/data/<package>, so that remove write permission is possible"
exit 1
fi
fi
# Replace "PKG" with the application id of your terminal app
[ -z "$RISH_APPLICATION_ID" ] && export RISH_APPLICATION_ID="PKG"
/system/bin/app_process -Djava.class.path="$DEX" /system/bin --nice-name=rish rikka.shizuku.shell.ShizukuShellLoader "$@"
----- < above is rish > -----
----- < below is the Shizuku rish installer > ------
exec 2>/dev/null
BIN="$(dirname "$(command -v bash)")"
RISH="$BIN/rish"; DEX="$BIN/rish_shizuku.dex"
ACTION="install"; SILENT_MODE=0; SOURCE_MODE="default"; SOURCE_PATH=""; SOURCE_PROVIDED=0
if [ "$(id -u)" -eq 0 ]; then
printf "\033[1;31m[x]\033[0m Please do not run this as root!\n" >&2
exit 1
fi
while [ $# -gt 0 ]; do
case "$1" in
--uninstall) ACTION="uninstall" ;;
--reinstall) ACTION="reinstall" ;;
--silent) SILENT_MODE=1 ;;
--source=*) SOURCE_MODE="${1#*=}"; SOURCE_PROVIDED=1 ;;
--source) shift; SOURCE_MODE="$1"; SOURCE_PROVIDED=1 ;;
--path=*) SOURCE_PATH="${1#*=}" ;;
--path) shift; SOURCE_PATH="$1" ;;
esac
shift
done
if [ -t 1 ]; then
C0='\033[0m'
CR='\033[1;31m'
CG='\033[1;32m'
CY='\033[1;33m'
CB='\033[1;34m'
CC='\033[1;36m'
else
C0=''
CR=''
CG=''
CY=''
CB=''
CC=''
fi
cancel(){ echo -e "${CY}[!]${C0} $1"; exit 0; }
msg(){ [ "$SILENT_MODE" -eq 0 ] && echo -e "${CB}[i]${C0} $1"; }
ok(){ [ "$SILENT_MODE" -eq 0 ] && echo -e "${CG}[+]${C0} $1"; }
warn(){ [ "$SILENT_MODE" -eq 0 ] && echo -e "${CY}[!]${C0} $1"; }
err(){ echo -e "${CR}[x]${C0} $1"; exit 1; }
step(){ [ "$SILENT_MODE" -eq 0 ] && echo -e "${CC}==>${C0} $1"; }
cleanup() {
[ -n "$TMP_SUBDIR" ] && rm -rf "$TMP_SUBDIR"
}
on_cancel() {
echo -e "\n${CY}[!]${C0} Operation cancelled by user."
exit 1
}
trap on_cancel INT
trap cleanup EXIT
if [ "$ACTION" = "uninstall" ]; then
rm -f "$RISH" "$DEX" "$HOME/rish" "$HOME/rish_shizuku.dex"
find "$HOME" -maxdepth 1 -type l -name "rish*" -delete || true
echo -e "${CG}[+]${C0} rish has been removed."
exit 0
fi
detect_pkg(){
p="${PREFIX:-$(pwd)}"
case "$p" in
/data/data/*)
echo "${p#/data/data/}" | cut -d/ -f1
return
;;
/data/user/*)
echo "$p" | cut -d/ -f5
return
;;
esac
if [ -n "$HOME" ]; then
case "$HOME" in
/data/data/*)
echo "${HOME#/data/data/}" | cut -d/ -f1
return
;;
/data/user/*)
echo "$HOME" | cut -d/ -f5
return
;;
esac
fi
echo "unknown"
}
PKG="$(detect_pkg)"
[ "$PKG" = "unknown" ] && err "Package detect failed"
if [ -f "$RISH" ] && [ "$ACTION" != "reinstall" ] && [ "$SILENT_MODE" -eq 0 ]; then
echo -ne "${CY}[?]${C0} rish installed. Reinstall? [y/N]: "
read -r c < /dev/tty
case "$c" in
y|Y) ACTION="reinstall" ;;
*) cancel "Cancelled."; exit 0 ;;
esac
fi
if [ "$SILENT_MODE" -eq 0 ] && [ "$SOURCE_PROVIDED" -eq 0 ]; then
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"
printf "Choice [1-6]: "
read src_choice < /dev/tty
case "$src_choice" in
1) SOURCE_MODE="local_app" ;;
2) SOURCE_MODE="default" ;;
3) SOURCE_MODE="thedjchi" ;;
4)
SOURCE_MODE="custom_repo"
printf "Repo (user/repo): "
read SOURCE_PATH < /dev/tty
;;
5)
SOURCE_MODE="custom_url"
printf "URL: "
read SOURCE_PATH < /dev/tty
;;
6)
SOURCE_MODE="local_file"
printf "Path: "
read SOURCE_PATH < /dev/tty
;;
*)
cancel "Invalid choice. Cancelled."
;;
esac
fi
[ "$SILENT_MODE" -eq 1 ] && echo -e "${CG}[+]${C0} Starting silent rish installation..."
RAND_ID="$RANDOM"
TMP_SUBDIR="${TMPDIR:-/tmp}/rish.$RAND_ID"
mkdir -p "$TMP_SUBDIR"
PLAN_A=1
for t in unzip sed grep install; do
command -v "$t" >/dev/null 2>&1 || PLAN_A=0
done
if [ "$PLAN_A" -eq 1 ]; then
UNZIP=unzip
SED=sed
GREP=grep
INSTALL=install
else
warn "Using busybox"
ARCH="$(uname -m)"
case "$ARCH" in
aarch64|arm64|armv8*) ARCH=arm64 ;;
armv*|armhf|arm) ARCH=arm ;;
x86_64|amd64) ARCH=x86_64 ;;
i386|i686|x86) ARCH=x86 ;;
*) err "Unsupported arch" ;;
esac
BB="$TMP_SUBDIR/busybox"
step "Downloading BusyBox..."
curl -fsSL "
https://raw.githubusercontent.com/merbah3266/rish_installer/main/busybox/$ARCH/busybox" -o "$BB" || err "BB download failed"
chmod +x "$BB"
UNZIP="$BB unzip"
SED="$BB sed"
GREP="$BB grep"
INSTALL="$BB install"
ok "BusyBox ready."
fi
APK_PATH="$TMP_SUBDIR/app.apk"
OFFLINE_OK=0
if [ "$SOURCE_MODE" = "local_app" ] || [ "$SOURCE_MODE" = "default" ]; then
step "Offline attempt..."
EXTRACTED="$(cmd package path moe.shizuku.privileged.api --user 0 2>/dev/null | cut -d: -f2)"
if [ -n "$EXTRACTED" ] && cp "$EXTRACTED" "$APK_PATH" 2>/dev/null; then
ok "Local APK extracted"
OFFLINE_OK=1
elif [ "$SOURCE_MODE" = "local_app" ]; then
cancel "Shizuku not found locally. Cancelled."
else
warn "Offline failed, falling back online..."
fi
fi
if [ "$OFFLINE_OK" -eq 0 ]; then
case "$SOURCE_MODE" in
local_file)
step "Using local file"
[ -z "$SOURCE_PATH" ] && cancel "No path provided. Cancelled."
[ ! -f "$SOURCE_PATH" ] && cancel "File not found. Cancelled."
cp "$SOURCE_PATH" "$APK_PATH" || cancel "Copy failed. Cancelled."
ok "Copied"
;;
custom_url)
step "Downloading from URL"
[ -z "$SOURCE_PATH" ] && cancel "No URL provided. Cancelled."
curl -fsSL -o "$APK_PATH" "$SOURCE_PATH" || cancel "Download failed. Cancelled."
ok "Downloaded"
;;
default|thedjchi|custom_repo)
if [ "$SOURCE_MODE" = "default" ]; then
REPO="RikkaApps/Shizuku"
elif [ "$SOURCE_MODE" = "thedjchi" ]; then
REPO="thedjchi/Shizuku"
else
REPO="$SOURCE_PATH"
fi
[ -z "$REPO" ] && cancel "No repo provided. Cancelled."
step "Fetching from $REPO..."
URL="$(curl -fsSL "
https://api.github.com/repos/$REPO/releases/latest" | sed -n 's/.*"browser_download_url":[[:space:]]*"\([^"]*\.apk\)".*/\1/p')"
[ -z "$URL" ] && cancel "URL fetch failed. Cancelled."
step "Downloading APK..."
curl -fsSL -o "$APK_PATH" "$URL" || cancel "Download failed. Cancelled."
ok "Downloaded"
;;
*)
cancel "Invalid source. Cancelled."
;;
esac
fi
step "Extracting..."
$UNZIP -qq "$APK_PATH" -d "$TMP_SUBDIR" || err "Unzip failed"
[ ! -f "$TMP_SUBDIR/assets/rish" ] && err "rish not found"
[ ! -f "$TMP_SUBDIR/assets/rish_shizuku.dex" ] && err "dex not found"
SH_PATH="$(command -v sh)"
[ -z "$SH_PATH" ] && err "sh not found"
TMP_RISH="$TMP_SUBDIR/rish.$RAND_ID"
echo "#!$SH_PATH" > "$TMP_RISH"
$GREP -v '^#' "$TMP_SUBDIR/assets/rish" >> "$TMP_RISH"
$SED -i "s/PKG/$PKG/g" "$TMP_RISH"
step "Installing..."
INSTALL_SUCCESS=0
if $INSTALL -m755 "$TMP_RISH" "$RISH" 2>/dev/null &&
$INSTALL -m400 "$TMP_SUBDIR/assets/rish_shizuku.dex" "$DEX" 2>/dev/null; then
ok "Installed to bin ($BIN)"
ln -sf "$RISH" "$HOME/rish" 2>/dev/null
ln -sf "$DEX" "$HOME/rish_shizuku.dex" 2>/dev/null
INSTALL_SUCCESS=1
else
warn "Bin failed, trying Home..."
if $INSTALL -m755 "$TMP_RISH" "$HOME/rish" 2>/dev/null &&
$INSTALL -m400 "$TMP_SUBDIR/assets/rish_shizuku.dex" "$HOME/rish_shizuku.dex" 2>/dev/null; then
ok "Installed to Home"
INSTALL_SUCCESS=1
fi
fi
if [ "$INSTALL_SUCCESS" -eq 1 ]; then
[ "$SILENT_MODE" -eq 1 ] &&
echo -e "${CG}[+]${C0} Success: rish installed." ||
ok "Setup complete. Run 'rish' or '~/rish'"
else
err "Installation failed"
fi
----- < 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>
*Android Debug Bridge* (adb)
Windows:
<
https://dl.google.com/android/repository/platform-tools-latest-windows.zip>
macOS:
<
https://dl.google.com/android/repository/platform-tools-latest-darwin.zip>
Linux:
<
https://dl.google.com/android/repository/platform-tools-latest-linux.zip>
--
Some things are so unintuitive that we need a tutorial to do them.
--- Synchronet 3.22a-Linux NewsLink 1.2