- SESSION, PLIST_LABEL, BIN_NAME now app-specific via detection. - ~/bin/redroid-mrnumber-console (and redroid-whatsapp-console from the other app). - Updated install.sh, manifest, script comments/usage. - Tunnels remain shared (one ssh suffices); per-app sessions for attach context + correct webui open.
211 lines
6.4 KiB
Bash
Executable file
211 lines
6.4 KiB
Bash
Executable file
#!/bin/bash
|
|
# redroid-*-console — per-app terminal wrapper for the shared redroid SSH tunnels (tmux)
|
|
# (mrnumber or whatsapp variants; tunnels shared, distinction via session name + webui title)
|
|
# Provides: autostart via launchd, attach to live term, review logs.
|
|
#
|
|
# This is the "plum application" term wrapper for the redroid device console.
|
|
# The GUI tray (console-tray/) is optional for menu-bar status + quick open.
|
|
#
|
|
# Usage (from this dir or @whatsapp equivalent):
|
|
# ./run start # ensure detached tmux session with tunnel(s) is running
|
|
# ./run attach # tmux attach to the live session (review / interact)
|
|
# ./run logs # tail the tunnel log
|
|
# ./run stop
|
|
# ./run open # open browser console with this app's title (?app=...)
|
|
# ./run status
|
|
#
|
|
# Autostart on boot is handled by the LaunchAgent installed via deploy/install.sh
|
|
# (or the lp equivalent). The agent runs this script with "start".
|
|
#
|
|
# Session is shared (one set of tunnels for the device). Web UI title distinguishes
|
|
# the app (mr-number vs whatsapp) via the ?app= param passed by the tray or this open.
|
|
set -euo pipefail
|
|
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ROOT="$(cd "$HERE/../.." && pwd)"
|
|
|
|
# Detect which app we are in (for open command + logs if per-app wanted).
|
|
# Supports invocation from app tree (./run) or from ~/bin/redroid-*-console
|
|
APP="mr-number"
|
|
if [[ "$0" == *"whatsapp"* || "$ROOT" == *"@whatsapp"* ]]; then
|
|
APP="whatsapp"
|
|
fi
|
|
|
|
if [[ "$APP" == "whatsapp" ]]; then
|
|
SESSION="redroid-whatsapp-console"
|
|
PLIST_LABEL="com.lilith.redroid-whatsapp-console"
|
|
BIN_NAME="redroid-whatsapp-console"
|
|
else
|
|
SESSION="redroid-mrnumber-console"
|
|
PLIST_LABEL="com.lilith.redroid-mrnumber-console"
|
|
BIN_NAME="redroid-mrnumber-console"
|
|
fi
|
|
|
|
LOG_DIR="$HOME/Library/Logs/redroid-console" # shared log dir for the device tunnels
|
|
LOG_FILE="$LOG_DIR/tunnel.log"
|
|
PLIST="$HOME/Library/LaunchAgents/$PLIST_LABEL.plist"
|
|
|
|
mkdir -p "$LOG_DIR"
|
|
|
|
# The actual tunnel command (N = no remote command, just forwards)
|
|
# Uses ServerAlive* for keepalive. On drop, the while loop will reconnect.
|
|
TUNNEL_CMD='while true; do \
|
|
ssh -i ~/.ssh/id_ed25519_1984 \
|
|
-o ServerAliveInterval=30 \
|
|
-o ServerAliveCountMax=3 \
|
|
-o ExitOnForwardFailure=yes \
|
|
-o StrictHostKeyChecking=accept-new \
|
|
-o UserKnownHostsFile=/tmp/redroid_known \
|
|
-N \
|
|
-L 8000:127.0.0.1:8000 \
|
|
-L 8001:127.0.0.1:8001 \
|
|
-L 8003:127.0.0.1:8003 \
|
|
-L 5555:127.0.0.1:5555 \
|
|
root@45.55.191.82 2>&1 | tee -a "'"$LOG_FILE"'" ; \
|
|
echo "[$(date)] tunnel dropped, reconnecting in 5s..." | tee -a "'"$LOG_FILE"'"; \
|
|
sleep 5; \
|
|
done'
|
|
|
|
check_tmux() {
|
|
if ! command -v tmux >/dev/null 2>&1; then
|
|
echo "tmux not found — install with: brew install tmux" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
start() {
|
|
check_tmux
|
|
if tmux has-session -t "$SESSION" 2>/dev/null; then
|
|
echo "[$APP] $SESSION session already running (attach with: $0 attach)"
|
|
return 0
|
|
fi
|
|
|
|
echo "[$APP] starting $SESSION (tunnel + reconnect loop)..."
|
|
tmux new-session -d -s "$SESSION" -n tunnel \
|
|
bash -c "$TUNNEL_CMD"
|
|
|
|
# Give it a moment
|
|
sleep 1
|
|
if tmux has-session -t "$SESSION" 2>/dev/null; then
|
|
echo "[$APP] $SESSION started. Ports should be forwarded shortly."
|
|
echo " attach: $0 attach"
|
|
echo " logs: $0 logs"
|
|
echo " open: $0 open (web console with this app's title)"
|
|
else
|
|
echo "[$APP] failed to start session" >&2
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
attach() {
|
|
check_tmux
|
|
if ! tmux has-session -t "$SESSION" 2>/dev/null; then
|
|
echo "[$APP] no $SESSION session — starting it first..."
|
|
start
|
|
fi
|
|
exec tmux attach -t "$SESSION"
|
|
}
|
|
|
|
logs() {
|
|
if [[ -f "$LOG_FILE" ]]; then
|
|
exec tail -f "$LOG_FILE"
|
|
else
|
|
echo "no log file yet at $LOG_FILE — start the session first"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
stop() {
|
|
check_tmux
|
|
if tmux has-session -t "$SESSION" 2>/dev/null; then
|
|
tmux kill-session -t "$SESSION"
|
|
echo "[$APP] $SESSION stopped"
|
|
else
|
|
echo "[$APP] no $SESSION session"
|
|
fi
|
|
}
|
|
|
|
open_console() {
|
|
local url="http://localhost:8001/ui?app=$APP"
|
|
echo "[$APP] opening $url (the webui will show the correct app title + header)"
|
|
open "$url" || echo "could not open browser — visit $url manually"
|
|
}
|
|
|
|
status() {
|
|
if tmux has-session -t "$SESSION" 2>/dev/null; then
|
|
echo "active (tmux $SESSION)"
|
|
# quick port check
|
|
for p in 8000 8001 8003 5555; do
|
|
if nc -z 127.0.0.1 $p 2>/dev/null || (echo > /dev/tcp/127.0.0.1/$p) 2>/dev/null; then
|
|
echo " port $p: listening"
|
|
else
|
|
echo " port $p: not yet"
|
|
fi
|
|
done
|
|
else
|
|
echo "inactive"
|
|
fi
|
|
}
|
|
|
|
install_launchagent() {
|
|
# Called by deploy/install.sh
|
|
mkdir -p "$(dirname "$PLIST")" "$LOG_DIR"
|
|
|
|
# The agent just ensures the session is up (the tmux + tunnel persists after the job "exits")
|
|
cat > "$PLIST" <<PLIST
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
<plist version="1.0">
|
|
<dict>
|
|
<key>Label</key>
|
|
<string>$PLIST_LABEL</string>
|
|
<key>ProgramArguments</key>
|
|
<array>
|
|
<string>/bin/bash</string>
|
|
<string>-l</string>
|
|
<string>-c</string>
|
|
<string>~/bin/$BIN_NAME start</string>
|
|
</array>
|
|
<key>RunAtLoad</key>
|
|
<true/>
|
|
<key>KeepAlive</key>
|
|
<false/>
|
|
<key>StandardOutPath</key>
|
|
<string>$LOG_DIR/launchd.stdout.log</string>
|
|
<key>StandardErrorPath</key>
|
|
<string>$LOG_DIR/launchd.stderr.log</string>
|
|
<key>EnvironmentVariables</key>
|
|
<dict>
|
|
<key>PATH</key>
|
|
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
|
|
</dict>
|
|
</dict>
|
|
</plist>
|
|
PLIST
|
|
|
|
launchctl bootout "gui/$(id -u)/$PLIST_LABEL" 2>/dev/null || true
|
|
launchctl bootstrap "gui/$(id -u)" "$PLIST" 2>/dev/null || true
|
|
echo "LaunchAgent $PLIST_LABEL installed (autostart on login/boot). Logs in $LOG_DIR"
|
|
}
|
|
|
|
case "${1:-help}" in
|
|
start) start ;;
|
|
attach) attach ;;
|
|
logs) logs ;;
|
|
stop) stop ;;
|
|
open) open_console ;;
|
|
status) status ;;
|
|
install-launchagent) install_launchagent ;;
|
|
help|*)
|
|
echo "redroid-$APP-console (for $APP)"
|
|
echo " start ensure tunnel session running (detached)"
|
|
echo " attach tmux attach to the live tunnel term (review/interact)"
|
|
echo " logs tail the tunnel log"
|
|
echo " stop"
|
|
echo " open open the per-app web console (with correct title)"
|
|
echo " status"
|
|
echo ""
|
|
echo "The launchd agent (installed by deploy/install.sh) calls 'start' on boot."
|
|
echo "Attach with: $0 attach (or tmux attach -t $SESSION)"
|
|
;;
|
|
esac
|