599 lines
19 KiB
Bash
599 lines
19 KiB
Bash
#!/usr/bin/env sh
|
||
set -eu
|
||
|
||
ROOT_DIR="$(CDPATH= cd -- "$(dirname "$0")" && pwd)"
|
||
WATCHTHIS_DIR="$ROOT_DIR/dash/staging/watchthis"
|
||
POST_JAILBREAK_ROOT="$ROOT_DIR/dash/staging/post-jailbreak-root"
|
||
KTERM_STAGING_DIR="$ROOT_DIR/dash/staging/kterm"
|
||
SSH_HELPERS_DIR="$ROOT_DIR/scripts/kindle"
|
||
SYNC_SCRIPT="$ROOT_DIR/scripts/sync-layered-clock-to-kindle.sh"
|
||
THEMES_JSON="$ROOT_DIR/calendar/config/themes.json"
|
||
KTERM_GITHUB_REPO="bfabiszewski/kterm"
|
||
|
||
MODE="all"
|
||
VOLUME_PATH="/Volumes/Kindle"
|
||
HOST_TARGET="kindle"
|
||
THEME_ID=""
|
||
ORIENTATION=""
|
||
KTERM_PACKAGE=""
|
||
DOWNLOAD_KTERM=false
|
||
KTERM_VERSION="latest"
|
||
SHOW_BACKGROUND=true
|
||
START_DASHBOARD=false
|
||
|
||
print_usage() {
|
||
cat <<'EOF'
|
||
用法:
|
||
sh bootstrap-new-kindle.sh [模式] [选项]
|
||
|
||
模式:
|
||
all 默认。能预置 USB 存储就先预置;能连 SSH 就继续做 SSH 后半段
|
||
prepare-storage 只做 USB 存储预置
|
||
post-ssh 只做 SSH 打通后的自动化收尾;默认要求设备上已存在 prepare-storage 预置的 dashboard 基础运行时
|
||
|
||
选项:
|
||
-v, --volume <path> Kindle 挂载目录,默认 /Volumes/Kindle
|
||
-k, --kindle <host> Kindle SSH 主机名,默认 kindle
|
||
-t, --theme <theme-id> SSH 阶段切换到指定主题;默认使用 themes.json 的默认主题
|
||
-o, --orientation <value> SSH 阶段切换到指定方向;默认使用 themes.json 的默认方向
|
||
--kterm-package <path> 指定 KTerm 安装包;官方 release 用 .zip,也兼容外部 .bin
|
||
--download-kterm 在 Mac 侧联网下载 KTerm 到 dash/staging/kterm/,再预置到 Kindle
|
||
--kterm-version <tag> 下载指定 KTerm 版本;默认 latest
|
||
--no-background SSH 阶段同步后不立即切主题出图
|
||
--start-dashboard SSH 阶段额外后台启动 dashboard 主循环;默认要求设备上已有完整 dashboard 运行时
|
||
-h, --help 查看帮助
|
||
|
||
说明:
|
||
这不是 100% 零交互刷机脚本。
|
||
受 Kindle 本机流程限制,下面这些步骤仍然必须人工完成:
|
||
1. 进入 demo mode / WatchThis 流程
|
||
2. 在正确时机执行 Sideload Content
|
||
3. 触发 Get Started 完成越狱
|
||
4. 搜索 ;log mrpi 安装 KUAL / MRPI / USBNetwork
|
||
5. 首次进 KTerm 执行 sh /mnt/us/ssh-force-dropbear-22.sh
|
||
|
||
关于 KTerm:
|
||
1. 当前仓库默认不自带 KTerm 安装包。
|
||
2. 官方 KTerm release 使用 .zip,解压后是 kterm/ 扩展目录。
|
||
3. 如果你手头已经有 KTerm 安装包,可以:
|
||
- 放到 dash/staging/kterm/ 目录下,脚本会自动尝试拾取
|
||
- 或执行时显式传:--kterm-package /绝对路径/kterm-kindle-*.zip
|
||
4. 如果你希望脚本直接从网上拉,可以执行:
|
||
--download-kterm --kterm-version latest
|
||
或:
|
||
--download-kterm --kterm-version v2.6
|
||
5. 下载发生在 Mac 侧,文件会缓存到 dash/staging/kterm/,然后再解压或复制到 Kindle。
|
||
6. 对这台 Voyage 5.13.6,脚本默认优先选择“不带 armhf 后缀”的 zip。
|
||
7. 如果脚本没有检测到 KTerm 包,会明确提示“这一步仍需手工补装 KTerm”。
|
||
|
||
关于 post-ssh:
|
||
1. 它当前会同步 dashboard 的 shell 脚本、KUAL 菜单和主题包。
|
||
2. 它不会回补 prepare-storage 阶段预置的原生二进制,例如 next-wakeup、xh。
|
||
3. 因此最稳的用法仍然是:先跑 prepare-storage,完成设备侧步骤后,再跑 post-ssh。
|
||
|
||
推荐操作顺序:
|
||
|
||
阶段 A:先做 USB 预置
|
||
1. 用 USB 线把 Kindle 接到 Mac。
|
||
2. 确认 Finder 里已经出现 Kindle,默认挂载目录是 /Volumes/Kindle。
|
||
3. 执行:
|
||
sh bootstrap-new-kindle.sh prepare-storage
|
||
4. 预期结果:
|
||
- Kindle 根目录出现 Update_hotfix_watchthis_custom.bin
|
||
- Kindle 根目录出现 ssh-force-dropbear-22.sh 等脚本
|
||
- Kindle 根目录出现 dashboard/、extensions/、mrpackages/
|
||
- Kindle 根目录出现 .demo/KV-5.13.6.zip、.demo/demo.json、.demo/goodreads/
|
||
- 如果提供了 KTerm zip,extensions/ 里会被解压出 kterm/
|
||
- 如果提供了外部 KTerm bin,mrpackages/ 里会出现对应文件
|
||
5. 安全弹出 Kindle。
|
||
|
||
阶段 B:在 Kindle 上完成 WatchThis 和越狱
|
||
1. 恢复出厂。
|
||
2. 语言只选 English (United Kingdom)。
|
||
3. 到 Wi-Fi 页面时,不要真的联网;先按 WatchThis 文档进入 demo mode。
|
||
4. 搜索 ;demo,进入 demo menu -> Sideload Content。
|
||
5. 到这个页面后再接 USB;因为阶段 A 已经预置好 .demo 内容,这里只需确认文件存在。
|
||
6. 弹出 Kindle,在设备上点 Done,退出 demo menu。
|
||
7. 进入 ;dsts -> Help & User Guides -> Get Started。
|
||
8. 按设备提示继续完成 register this demo -> Skip -> standard。
|
||
9. 重启后如果看到 Configure Device,用隐藏手势回到主页。
|
||
10. 搜索 ;uzb,再接 USB,把 Update_hotfix_watchthis_custom.bin 放到根目录。
|
||
11. 弹出设备后,进入 ;dsts -> Device Options -> Update Your Kindle。
|
||
|
||
阶段 C:安装 KUAL / MRPI / USBNetwork / dashboard
|
||
1. 在 Kindle 首页搜索:
|
||
;log mrpi
|
||
2. 等 MRPI 安装完成。
|
||
3. 预期结果:
|
||
- 首页出现 KUAL
|
||
- KUAL 菜单里有 Rename OTA Binaries
|
||
- KUAL 菜单里有 kindle-dash
|
||
- 如果本次预置了 KTerm 安装包,首页或搜索里应能找到 KTerm
|
||
4. 先在 KUAL 中执行:
|
||
Rename OTA Binaries -> Rename
|
||
|
||
阶段 D:打通 Wi-Fi 和 SSH
|
||
1. 让 Kindle 连到和 Mac 同一个主 Wi-Fi,不要用 Guest 网络。
|
||
2. 打开 KTerm。
|
||
3. 在 KTerm 执行:
|
||
sh /mnt/us/ssh-force-dropbear-22.sh
|
||
4. 回到 Mac,先测试:
|
||
ssh kindle
|
||
5. 如果这一步还不通,不要继续盲试,先回看:
|
||
dash/docs/kindle-voyage-5.13.6-dual-ssh-playbook-zh.md
|
||
|
||
阶段 E:SSH 打通后自动同步并出图
|
||
1. 执行:
|
||
sh bootstrap-new-kindle.sh post-ssh -t simple -o portrait
|
||
2. 预期结果:
|
||
- 自动同步 dashboard shell 脚本、KUAL 菜单和主题包
|
||
- Kindle 立即切到 simple / portrait
|
||
- 屏幕马上显示背景和时钟
|
||
3. 如果还希望后台常驻 dashboard 主循环,再执行:
|
||
sh bootstrap-new-kindle.sh post-ssh -t simple -o portrait --start-dashboard
|
||
这一步默认建立在 prepare-storage 已经把完整 dashboard 基础运行时放进设备上的前提上。
|
||
|
||
最省事的直接用法:
|
||
1. USB 挂载时先运行:
|
||
sh bootstrap-new-kindle.sh all -t simple -o portrait
|
||
这会先做完能做的 USB 预置。
|
||
2. 等你在 Kindle 上完成越狱、MRPI、Wi-Fi、KTerm 拉起 SSH 后,
|
||
再重新运行同一条命令:
|
||
sh bootstrap-new-kindle.sh all -t simple -o portrait
|
||
这时它会自动继续做 SSH 后半段。
|
||
|
||
最容易做错的地方:
|
||
1. `Get Started` 只负责触发越狱脚本;真正退出 demo 状态还要再执行一次 `Update Your Kindle` 安装 custom hotfix。
|
||
2. `Update Your Kindle` 之前,先确认根目录里是真正的 `Update_hotfix_watchthis_custom.bin`,不要把 `._Update_hotfix_watchthis_custom.bin` 误当成正确文件。
|
||
3. 首次 SSH 最稳的入口是 KTerm,不是 USB 直连盲试。
|
||
4. post-ssh 阶段如果不带 -t/-o,会退回 themes.json 里的默认主题和方向。
|
||
5. 如果本轮没有预置 KTerm 包,阶段 C 结束后仍需你手工补装 KTerm。
|
||
6. post-ssh 不是“从零补齐 dashboard”的入口;next-wakeup、xh 这类原生二进制仍来自 prepare-storage。
|
||
|
||
示例:
|
||
sh bootstrap-new-kindle.sh prepare-storage
|
||
sh bootstrap-new-kindle.sh prepare-storage --kterm-package ~/Downloads/kterm-kindle-2.6.zip
|
||
sh bootstrap-new-kindle.sh prepare-storage --download-kterm --kterm-version latest
|
||
sh bootstrap-new-kindle.sh all -t simple -o portrait
|
||
sh bootstrap-new-kindle.sh post-ssh -k kindle --start-dashboard
|
||
EOF
|
||
}
|
||
|
||
log_step() {
|
||
printf '\n[%s] %s\n' "$1" "$2"
|
||
}
|
||
|
||
require_path() {
|
||
target_path=$1
|
||
label=$2
|
||
if [ ! -e "$target_path" ]; then
|
||
echo "缺少${label}: $target_path" >&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
detect_kterm_package() {
|
||
if [ -n "$KTERM_PACKAGE" ]; then
|
||
if [ ! -f "$KTERM_PACKAGE" ]; then
|
||
echo "指定的 KTerm 安装包不存在: $KTERM_PACKAGE" >&2
|
||
exit 1
|
||
fi
|
||
printf '%s\n' "$KTERM_PACKAGE"
|
||
return 0
|
||
fi
|
||
|
||
if [ ! -d "$KTERM_STAGING_DIR" ]; then
|
||
return 1
|
||
fi
|
||
|
||
set +e
|
||
set -- "$KTERM_STAGING_DIR"/*.zip "$KTERM_STAGING_DIR"/*.bin
|
||
status=$?
|
||
set -e
|
||
|
||
if [ "$status" -ne 0 ] || [ ! -e "$1" ]; then
|
||
return 1
|
||
fi
|
||
|
||
printf '%s\n' "$1"
|
||
}
|
||
|
||
download_kterm_if_requested() {
|
||
if [ "$DOWNLOAD_KTERM" != true ]; then
|
||
return
|
||
fi
|
||
|
||
mkdir -p "$KTERM_STAGING_DIR"
|
||
metadata_json="$KTERM_STAGING_DIR/kterm-release-${KTERM_VERSION}.json"
|
||
|
||
case "$KTERM_VERSION" in
|
||
latest)
|
||
release_api_url="https://api.github.com/repos/$KTERM_GITHUB_REPO/releases/latest"
|
||
;;
|
||
*)
|
||
release_api_url="https://api.github.com/repos/$KTERM_GITHUB_REPO/releases/tags/$KTERM_VERSION"
|
||
;;
|
||
esac
|
||
|
||
echo "正在从 GitHub 获取 KTerm release 元数据: $release_api_url"
|
||
curl -fsSL "$release_api_url" -o "$metadata_json"
|
||
|
||
release_info="$(python3 - "$metadata_json" <<'PY'
|
||
import json
|
||
import pathlib
|
||
import sys
|
||
|
||
path = pathlib.Path(sys.argv[1])
|
||
data = json.loads(path.read_text())
|
||
assets = data.get("assets", [])
|
||
|
||
preferred = None
|
||
fallback = None
|
||
for asset in assets:
|
||
name = asset.get("name", "")
|
||
url = asset.get("browser_download_url", "")
|
||
if not name.endswith(".zip"):
|
||
continue
|
||
if fallback is None:
|
||
fallback = (name, url)
|
||
if "armhf" not in name.lower():
|
||
preferred = (name, url)
|
||
break
|
||
|
||
selected = preferred or fallback
|
||
if not selected:
|
||
raise SystemExit("未找到可用的 KTerm zip 资产")
|
||
|
||
tag = data.get("tag_name", "unknown")
|
||
print(f"TAG={tag}")
|
||
print(f"NAME={selected[0]}")
|
||
print(f"URL={selected[1]}")
|
||
PY
|
||
)"
|
||
|
||
downloaded_tag=""
|
||
downloaded_name=""
|
||
downloaded_url=""
|
||
while IFS='=' read -r key value; do
|
||
case "$key" in
|
||
TAG)
|
||
downloaded_tag=$value
|
||
;;
|
||
NAME)
|
||
downloaded_name=$value
|
||
;;
|
||
URL)
|
||
downloaded_url=$value
|
||
;;
|
||
esac
|
||
done <<EOF
|
||
$release_info
|
||
EOF
|
||
|
||
if [ -z "$downloaded_name" ] || [ -z "$downloaded_url" ]; then
|
||
echo "无法解析 KTerm 下载地址。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
downloaded_path="$KTERM_STAGING_DIR/$downloaded_name"
|
||
echo "下载 KTerm: tag=$downloaded_tag asset=$downloaded_name"
|
||
curl -fL "$downloaded_url" -o "$downloaded_path"
|
||
KTERM_PACKAGE="$downloaded_path"
|
||
}
|
||
|
||
kindle_volume_available() {
|
||
[ -d "$VOLUME_PATH" ]
|
||
}
|
||
|
||
ssh_reachable() {
|
||
ssh -o BatchMode=yes -o ConnectTimeout=5 "$HOST_TARGET" true >/dev/null 2>&1
|
||
}
|
||
|
||
resolve_theme_selection() {
|
||
python3 - "$THEMES_JSON" "$THEME_ID" "$ORIENTATION" <<'PY'
|
||
import json
|
||
import pathlib
|
||
import sys
|
||
|
||
path = pathlib.Path(sys.argv[1])
|
||
requested_theme = sys.argv[2]
|
||
requested_orientation = sys.argv[3]
|
||
data = json.loads(path.read_text())
|
||
|
||
themes = {theme["id"]: theme for theme in data.get("themes", [])}
|
||
theme_id = requested_theme or data.get("defaultThemeId", "")
|
||
if theme_id not in themes:
|
||
raise SystemExit(f"未知主题: {theme_id}")
|
||
|
||
orientations = list(themes[theme_id].get("variants", {}).keys())
|
||
if not orientations:
|
||
raise SystemExit(f"主题 {theme_id} 没有任何方向配置")
|
||
|
||
orientation = requested_orientation or data.get("defaultOrientation", "")
|
||
if orientation not in orientations:
|
||
orientation = orientations[0]
|
||
|
||
print(f"THEME_ID={theme_id}")
|
||
print(f"ORIENTATION={orientation}")
|
||
PY
|
||
}
|
||
|
||
load_theme_selection() {
|
||
resolved_output="$(resolve_theme_selection)"
|
||
RESOLVED_THEME_ID=""
|
||
RESOLVED_ORIENTATION=""
|
||
|
||
while IFS='=' read -r key value; do
|
||
case "$key" in
|
||
THEME_ID)
|
||
RESOLVED_THEME_ID=$value
|
||
;;
|
||
ORIENTATION)
|
||
RESOLVED_ORIENTATION=$value
|
||
;;
|
||
esac
|
||
done <<EOF
|
||
$resolved_output
|
||
EOF
|
||
|
||
if [ -z "$RESOLVED_THEME_ID" ] || [ -z "$RESOLVED_ORIENTATION" ]; then
|
||
echo "无法解析主题和方向。" >&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
copy_watchthis_payload() {
|
||
require_path "$WATCHTHIS_DIR/KV-5.13.6/KV-5.13.6.zip" "WatchThis payload"
|
||
require_path "$WATCHTHIS_DIR/KV-5.13.6/demo.json" "WatchThis demo.json"
|
||
require_path "$WATCHTHIS_DIR/Update_hotfix_watchthis_custom.bin" "WatchThis hotfix"
|
||
|
||
mkdir -p "$VOLUME_PATH/.demo/goodreads"
|
||
cp "$WATCHTHIS_DIR/KV-5.13.6/KV-5.13.6.zip" "$VOLUME_PATH/.demo/"
|
||
cp "$WATCHTHIS_DIR/KV-5.13.6/demo.json" "$VOLUME_PATH/.demo/"
|
||
cp "$WATCHTHIS_DIR/Update_hotfix_watchthis_custom.bin" "$VOLUME_PATH/"
|
||
}
|
||
|
||
copy_post_jailbreak_bundle() {
|
||
require_path "$POST_JAILBREAK_ROOT/extensions" "post-jailbreak extensions"
|
||
require_path "$POST_JAILBREAK_ROOT/mrpackages" "post-jailbreak mrpackages"
|
||
require_path "$POST_JAILBREAK_ROOT/dashboard" "post-jailbreak dashboard"
|
||
|
||
mkdir -p "$VOLUME_PATH/extensions" "$VOLUME_PATH/mrpackages" "$VOLUME_PATH/dashboard"
|
||
|
||
rsync -av --no-o --no-g "$POST_JAILBREAK_ROOT/extensions/" "$VOLUME_PATH/extensions/"
|
||
rsync -av --no-o --no-g "$POST_JAILBREAK_ROOT/mrpackages/" "$VOLUME_PATH/mrpackages/"
|
||
rsync -av --no-o --no-g "$POST_JAILBREAK_ROOT/dashboard/" "$VOLUME_PATH/dashboard/"
|
||
}
|
||
|
||
install_kterm_package_if_available() {
|
||
detected_kterm_package=$(detect_kterm_package || true)
|
||
if [ -z "$detected_kterm_package" ]; then
|
||
echo "未检测到 KTerm 安装包;本轮只预置 SSH 恢复脚本,KTerm 仍需手工补装。"
|
||
return
|
||
fi
|
||
|
||
case "$detected_kterm_package" in
|
||
*.zip)
|
||
mkdir -p "$VOLUME_PATH/extensions"
|
||
unzip -oq "$detected_kterm_package" -d "$VOLUME_PATH/extensions"
|
||
echo "已预置 KTerm 扩展包并解压到 extensions/: $(basename "$detected_kterm_package")"
|
||
;;
|
||
*.bin)
|
||
mkdir -p "$VOLUME_PATH/mrpackages"
|
||
cp "$detected_kterm_package" "$VOLUME_PATH/mrpackages/"
|
||
echo "已预置 KTerm bin 到 mrpackages/: $(basename "$detected_kterm_package")"
|
||
;;
|
||
*)
|
||
echo "不支持的 KTerm 安装包格式: $detected_kterm_package" >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
}
|
||
|
||
copy_ssh_helpers() {
|
||
require_path "$SSH_HELPERS_DIR/ssh-force-dropbear-22.sh" "SSH helper scripts"
|
||
|
||
rsync -av --no-o --no-g "$SSH_HELPERS_DIR/" "$VOLUME_PATH/"
|
||
}
|
||
|
||
print_storage_next_steps() {
|
||
cat <<'EOF'
|
||
|
||
下一步请在 Kindle 上继续:
|
||
1. 按 [dash/docs/kindle-voyage-5.13.6-watchthis-zh.md] 的流程进入 demo mode。
|
||
2. 走到真正的 Sideload Content 时,脚本已预置好:
|
||
- .demo/KV-5.13.6.zip
|
||
- .demo/demo.json
|
||
- .demo/goodreads/
|
||
3. 触发 Get Started 完成越狱。
|
||
4. 搜索 `;log mrpi` 安装 KUAL / MRPI / USBNetwork / dashboard。
|
||
5. 先在 KUAL 里执行 `Rename OTA Binaries -> Rename`。
|
||
6. 连上 Wi-Fi。
|
||
7. 打开 KTerm,执行:
|
||
sh /mnt/us/ssh-force-dropbear-22.sh
|
||
8. 回到 Mac 后,再运行:
|
||
sh bootstrap-new-kindle.sh post-ssh
|
||
EOF
|
||
}
|
||
|
||
prepare_storage() {
|
||
if ! kindle_volume_available; then
|
||
echo "未找到 Kindle 挂载目录: $VOLUME_PATH" >&2
|
||
exit 1
|
||
fi
|
||
|
||
log_step "USB" "检查并下载 KTerm 安装包"
|
||
download_kterm_if_requested
|
||
|
||
log_step "USB" "预置 WatchThis payload"
|
||
copy_watchthis_payload
|
||
|
||
log_step "USB" "预置越狱后安装包"
|
||
copy_post_jailbreak_bundle
|
||
|
||
log_step "USB" "检查并预置 KTerm 安装包"
|
||
install_kterm_package_if_available
|
||
|
||
log_step "USB" "预置 SSH 恢复脚本"
|
||
copy_ssh_helpers
|
||
|
||
log_step "完成" "USB 存储预置已完成:$VOLUME_PATH"
|
||
print_storage_next_steps
|
||
}
|
||
|
||
prepare_remote_helpers() {
|
||
ssh "$HOST_TARGET" "chmod +x /mnt/us/ssh-collect.sh /mnt/us/ssh-fix-all-keys.sh /mnt/us/ssh-force-dropbear-22.sh /mnt/us/ssh-stop-all.sh 2>/dev/null || true"
|
||
ssh "$HOST_TARGET" "if [ -f /mnt/us/ssh-fix-all-keys.sh ]; then sh /mnt/us/ssh-fix-all-keys.sh; fi"
|
||
}
|
||
|
||
sync_dashboard_runtime() {
|
||
if [ -n "$THEME_ID" ]; then
|
||
if [ -n "$ORIENTATION" ]; then
|
||
sh "$SYNC_SCRIPT" "$HOST_TARGET" --theme "$THEME_ID" --orientation "$ORIENTATION"
|
||
else
|
||
sh "$SYNC_SCRIPT" "$HOST_TARGET" --theme "$THEME_ID"
|
||
fi
|
||
else
|
||
sh "$SYNC_SCRIPT" "$HOST_TARGET"
|
||
fi
|
||
}
|
||
|
||
show_background_once() {
|
||
load_theme_selection
|
||
ssh "$HOST_TARGET" "/mnt/us/dashboard/switch-theme.sh '$RESOLVED_THEME_ID' '$RESOLVED_ORIENTATION'"
|
||
}
|
||
|
||
start_dashboard_loop() {
|
||
# 当前仓库里最稳的是 SSH 触发启动;这里后台拉起,便于 bootstrap 脚本直接返回。
|
||
ssh "$HOST_TARGET" "mkdir -p /mnt/us/dashboard/logs && cd /mnt/us/dashboard && nohup ./start.sh >/mnt/us/dashboard/logs/bootstrap-start.log 2>&1 </dev/null &"
|
||
}
|
||
|
||
print_post_ssh_summary() {
|
||
load_theme_selection
|
||
cat <<EOF
|
||
|
||
SSH 阶段已完成:
|
||
- 主机:$HOST_TARGET
|
||
- 已同步 dashboard shell 脚本、KUAL 菜单与主题包
|
||
- 当前用于出图的主题:$RESOLVED_THEME_ID / $RESOLVED_ORIENTATION
|
||
|
||
如果你要继续验证:
|
||
- SSH 登录:ssh $HOST_TARGET
|
||
- 立即切主题:ssh $HOST_TARGET '/mnt/us/dashboard/switch-theme.sh $RESOLVED_THEME_ID $RESOLVED_ORIENTATION'
|
||
- 抓图到本地:sh snapshot.sh -t $RESOLVED_THEME_ID -o $RESOLVED_ORIENTATION
|
||
EOF
|
||
}
|
||
|
||
post_ssh() {
|
||
if ! ssh_reachable; then
|
||
echo "当前还无法通过 SSH 连接 ${HOST_TARGET}。" >&2
|
||
echo "请先在 Kindle 上连上 Wi-Fi,并在 KTerm 执行 sh /mnt/us/ssh-force-dropbear-22.sh" >&2
|
||
exit 1
|
||
fi
|
||
|
||
log_step "SSH" "修复设备侧 SSH 辅助脚本权限与 authorized_keys"
|
||
prepare_remote_helpers
|
||
|
||
log_step "同步" "同步 dashboard shell 脚本、KUAL 菜单和主题包到 Kindle"
|
||
sync_dashboard_runtime
|
||
|
||
if [ "$SHOW_BACKGROUND" = true ]; then
|
||
log_step "显示" "立即切到当前主题并出图"
|
||
show_background_once
|
||
fi
|
||
|
||
if [ "$START_DASHBOARD" = true ]; then
|
||
log_step "启动" "后台启动 dashboard 主循环"
|
||
start_dashboard_loop
|
||
fi
|
||
|
||
log_step "完成" "SSH 阶段自动化已完成"
|
||
print_post_ssh_summary
|
||
}
|
||
|
||
while [ "$#" -gt 0 ]; do
|
||
case "$1" in
|
||
all|prepare-storage|post-ssh)
|
||
MODE=$1
|
||
;;
|
||
-v|--volume)
|
||
shift
|
||
VOLUME_PATH=${1:?"missing volume path"}
|
||
;;
|
||
-k|--kindle)
|
||
shift
|
||
HOST_TARGET=${1:?"missing kindle host"}
|
||
;;
|
||
-t|--theme)
|
||
shift
|
||
THEME_ID=${1:?"missing theme id"}
|
||
;;
|
||
-o|--orientation)
|
||
shift
|
||
ORIENTATION=${1:?"missing orientation"}
|
||
;;
|
||
--kterm-package)
|
||
shift
|
||
KTERM_PACKAGE=${1:?"missing KTerm package path"}
|
||
;;
|
||
--download-kterm)
|
||
DOWNLOAD_KTERM=true
|
||
;;
|
||
--kterm-version)
|
||
shift
|
||
KTERM_VERSION=${1:?"missing KTerm version"}
|
||
;;
|
||
--no-background)
|
||
SHOW_BACKGROUND=false
|
||
;;
|
||
--start-dashboard)
|
||
START_DASHBOARD=true
|
||
;;
|
||
-h|--help)
|
||
print_usage
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo "未知参数: $1" >&2
|
||
print_usage >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
shift
|
||
done
|
||
|
||
require_path "$THEMES_JSON" "themes.json"
|
||
require_path "$SYNC_SCRIPT" "sync-layered-clock-to-kindle.sh"
|
||
|
||
case "$MODE" in
|
||
prepare-storage)
|
||
prepare_storage
|
||
;;
|
||
post-ssh)
|
||
post_ssh
|
||
;;
|
||
all)
|
||
did_anything=false
|
||
|
||
if kindle_volume_available; then
|
||
prepare_storage
|
||
did_anything=true
|
||
else
|
||
log_step "跳过" "未检测到 Kindle 存储挂载:$VOLUME_PATH"
|
||
fi
|
||
|
||
if ssh_reachable; then
|
||
post_ssh
|
||
did_anything=true
|
||
else
|
||
log_step "等待" "SSH 还未打通;等 Kindle 连上 Wi-Fi 并在 KTerm 执行 sh /mnt/us/ssh-force-dropbear-22.sh 后,再重跑本脚本或执行 post-ssh。"
|
||
fi
|
||
|
||
if [ "$did_anything" != true ]; then
|
||
echo "既没有检测到 Kindle 存储挂载,也没有检测到可用 SSH。" >&2
|
||
echo "请先通过 USB 挂载 Kindle,或先恢复 SSH 后再执行。" >&2
|
||
exit 1
|
||
fi
|
||
;;
|
||
esac
|