update at 2026-03-15 14:54:51
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
{
|
{
|
||||||
"items": [
|
"items": [
|
||||||
{"name": "Kindle Dashboard", "action": "/mnt/us/dashboard/start.sh"}
|
{"name": "Kindle Dashboard", "action": "/mnt/us/dashboard/start.sh"},
|
||||||
|
{"name": "Dashboard Debug On", "action": "/mnt/us/dashboard/debug-on.sh"},
|
||||||
|
{"name": "Dashboard Debug Off", "action": "/mnt/us/dashboard/debug-off.sh"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -43,6 +43,16 @@ If you're using KUAL you can use simple extension to start this Dashboard
|
|||||||
|
|
||||||
1. Copy folder `kindle-dash` from `KUAL` folder to the kual `extensions` folder. (located in `/mnt/us/extensions`)
|
1. Copy folder `kindle-dash` from `KUAL` folder to the kual `extensions` folder. (located in `/mnt/us/extensions`)
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
For on-device debugging without suspending the Kindle, set `DISABLE_SYSTEM_SUSPEND=true` in `local/env.sh`.
|
||||||
|
The dashboard loop will keep running and use a normal `sleep` between refreshes instead of writing to `/sys/power/state`.
|
||||||
|
|
||||||
|
If you're connected over SSH you can also run `DEBUG=true ./start.sh` to keep the process in the foreground with shell tracing enabled.
|
||||||
|
If you're launching from KUAL, use `Dashboard Debug On` before a normal start to persistently disable suspend in `local/env.sh`, and `Dashboard Debug Off` when you want to restore the normal low-power behavior.
|
||||||
|
Both actions stop the current dashboard process so the new setting takes effect on the next start.
|
||||||
|
If you're connected over SSH and only want a one-off foreground session, you can still run `/mnt/us/dashboard/start-debug.sh`.
|
||||||
|
|
||||||
## How this works
|
## How this works
|
||||||
|
|
||||||
* This code periodically downloads a dashboard image from an HTTP(s) endpoint.
|
* This code periodically downloads a dashboard image from an HTTP(s) endpoint.
|
||||||
@@ -53,6 +63,7 @@ If you're using KUAL you can use simple extension to start this Dashboard
|
|||||||
|
|
||||||
* The releases contain a pre-compiled binary of the [ht](https://github.com/ducaale/ht) command-line HTTP client. This fully supports modern HTTPS crypto, wheras the built-in `curl` and `wget` commands don't (because they rely on a very old `openssl` library).
|
* The releases contain a pre-compiled binary of the [ht](https://github.com/ducaale/ht) command-line HTTP client. This fully supports modern HTTPS crypto, wheras the built-in `curl` and `wget` commands don't (because they rely on a very old `openssl` library).
|
||||||
* For a detailed Kindle Voyage 5.13.6 jailbreak and deployment walkthrough, see [docs/kindle-voyage-5.13.6-watchthis-zh.md](./docs/kindle-voyage-5.13.6-watchthis-zh.md).
|
* For a detailed Kindle Voyage 5.13.6 jailbreak and deployment walkthrough, see [docs/kindle-voyage-5.13.6-watchthis-zh.md](./docs/kindle-voyage-5.13.6-watchthis-zh.md).
|
||||||
|
* For a detailed same-device dashboard/SSH troubleshooting playbook based on the 2026-03-15 session, see [docs/kindle-voyage-5.13.6-dual-ssh-playbook-zh.md](./docs/kindle-voyage-5.13.6-dual-ssh-playbook-zh.md).
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
412
dash/docs/kindle-voyage-5.13.6-dual-ssh-playbook-zh.md
Normal file
412
dash/docs/kindle-voyage-5.13.6-dual-ssh-playbook-zh.md
Normal file
@@ -0,0 +1,412 @@
|
|||||||
|
# Kindle Voyage 5.13.6 Dashboard/SSH 一次成操作手册
|
||||||
|
|
||||||
|
本文基于 2026-03-15 的一次实机排障整理,目标是让下次同型号 Kindle 在安装 dashboard、开启调试、打通 SSH 时尽量一次完成,不再重复今天这 5 个小时的试错过程。
|
||||||
|
|
||||||
|
## 适用范围
|
||||||
|
|
||||||
|
- Kindle Voyage
|
||||||
|
- 固件 5.13.6
|
||||||
|
- 已完成越狱
|
||||||
|
- 已安装 KUAL
|
||||||
|
- 通过 MRPI 安装扩展
|
||||||
|
- 目标项目为本仓库 `dash/`
|
||||||
|
|
||||||
|
## 最终结论
|
||||||
|
|
||||||
|
今天最终打通的稳定路径不是 USB 直连 SSH,而是:
|
||||||
|
|
||||||
|
1. Kindle 本机先通过 KTerm 拉起 `dropbear`
|
||||||
|
2. 让 `dropbear` 监听 `*:22`
|
||||||
|
3. 从 Mac 通过 Kindle 的 Wi-Fi 地址登录
|
||||||
|
4. 使用 `~/.ssh/id_ed25519_git` 这把 key
|
||||||
|
|
||||||
|
最终验证通过的登录方式:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ssh -i ~/.ssh/id_ed25519_git root@192.168.72.3
|
||||||
|
```
|
||||||
|
|
||||||
|
后续为了简化操作,已在本机 [~/.ssh/config](/Users/gavin/.ssh/config) 中加入:
|
||||||
|
|
||||||
|
```sshconfig
|
||||||
|
Host kindle
|
||||||
|
HostName 192.168.72.3
|
||||||
|
User root
|
||||||
|
IdentityFile ~/.ssh/id_ed25519_git
|
||||||
|
IdentitiesOnly yes
|
||||||
|
PreferredAuthentications publickey
|
||||||
|
PasswordAuthentication no
|
||||||
|
KbdInteractiveAuthentication no
|
||||||
|
```
|
||||||
|
|
||||||
|
所以当前可直接:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ssh kindle
|
||||||
|
```
|
||||||
|
|
||||||
|
## 下次同型号设备的推荐顺序
|
||||||
|
|
||||||
|
### 1. 路由器和网络先处理
|
||||||
|
|
||||||
|
先确认这几项:
|
||||||
|
|
||||||
|
- Kindle 和 Mac 在同一个主 Wi-Fi
|
||||||
|
- 不是 Guest Wi-Fi
|
||||||
|
- ASUS Lyra Trio 中 `禁止无线用户互通` 为关闭
|
||||||
|
|
||||||
|
这一步的意义是先保证 Mac 能访问 Kindle 的 Wi-Fi 地址。今天前期大量时间都浪费在这里。
|
||||||
|
|
||||||
|
注意:
|
||||||
|
|
||||||
|
- Kindle 有时不回 `ping`
|
||||||
|
- 但这不等于 SSH 不通
|
||||||
|
- 真正应检查的是 `arp`、`nc -vz <ip> 22`、`ssh`
|
||||||
|
|
||||||
|
### 2. Kindle 端必装内容
|
||||||
|
|
||||||
|
建议固定安装:
|
||||||
|
|
||||||
|
- KUAL
|
||||||
|
- USBNetwork
|
||||||
|
- KTerm
|
||||||
|
- 本仓库 dashboard 文件
|
||||||
|
|
||||||
|
其中:
|
||||||
|
|
||||||
|
- USBNetwork 用于提供 `usbnet` 和调试工具
|
||||||
|
- KTerm 是本地 root shell,是真正的兜底入口
|
||||||
|
|
||||||
|
今天的结论是:
|
||||||
|
一旦外部 SSH 不通,不要继续盲猜,直接进 KTerm 才是最快路线。
|
||||||
|
|
||||||
|
### 3. Dashboard 调试先关闭自动挂起
|
||||||
|
|
||||||
|
调试 dashboard 时,先在 KUAL 中执行:
|
||||||
|
|
||||||
|
1. `Dashboard Debug On`
|
||||||
|
2. `Kindle Dashboard`
|
||||||
|
|
||||||
|
调试结束后再执行:
|
||||||
|
|
||||||
|
1. `Dashboard Debug Off`
|
||||||
|
2. `Kindle Dashboard`
|
||||||
|
|
||||||
|
相关脚本:
|
||||||
|
|
||||||
|
- [dash/src/debug-on.sh](/Users/gavin/kindle-dash/dash/src/debug-on.sh)
|
||||||
|
- [dash/src/debug-off.sh](/Users/gavin/kindle-dash/dash/src/debug-off.sh)
|
||||||
|
- [dash/src/start-debug.sh](/Users/gavin/kindle-dash/dash/src/start-debug.sh)
|
||||||
|
- [dash/KUAL/kindle-dash/menu.json](/Users/gavin/kindle-dash/dash/KUAL/kindle-dash/menu.json)
|
||||||
|
|
||||||
|
核心经验:
|
||||||
|
|
||||||
|
- 调试时不要让设备自动 suspend
|
||||||
|
- 否则 KUAL 很容易刚打开就被挂起打断
|
||||||
|
|
||||||
|
## 今天确认过的关键事实
|
||||||
|
|
||||||
|
### 1. KUAL 的 `sshd up/down` 不是最终真相
|
||||||
|
|
||||||
|
今天多次出现:
|
||||||
|
|
||||||
|
- KUAL 显示 `sshd up`
|
||||||
|
- 但设备本机并没有 `sshd` 或 `dropbear` 进程
|
||||||
|
|
||||||
|
所以后续一律以本机 shell 为准:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
/mnt/us/usbnet/bin/lsof -n -P -iTCP:22
|
||||||
|
ps -ef | grep -E 'sshd|dropbear'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. `169.254.148.176` 不是 Kindle 的 USBNetwork 地址
|
||||||
|
|
||||||
|
这是今天最关键的坑之一。
|
||||||
|
|
||||||
|
我们最后确认:
|
||||||
|
|
||||||
|
- `169.254.148.176` 是 Mac 自己 USB 网卡的链路本地地址
|
||||||
|
- Kindle 在 `usbnet` 模式下的真实 USB IP 是 `192.168.15.244`
|
||||||
|
|
||||||
|
这个值来自当天在 Kindle 本机采集到的 `collect.log`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
usb0 inet addr:192.168.15.244
|
||||||
|
```
|
||||||
|
|
||||||
|
以及 `usbnet` 配置:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
KINDLE_IP=192.168.15.244
|
||||||
|
```
|
||||||
|
|
||||||
|
也就是说:
|
||||||
|
|
||||||
|
- 之前对 `169.254.148.176` 的 SSH 测试,实际上是在连 Mac 自己那块接口
|
||||||
|
- 这就是为什么前面很多现象互相矛盾
|
||||||
|
|
||||||
|
### 3. USBNetwork 直连链路没有最终打通
|
||||||
|
|
||||||
|
即使:
|
||||||
|
|
||||||
|
- Mac 端给 `en8`/`en11` 配了 `192.168.15.201/24`
|
||||||
|
- Kindle 端 `dropbear` 看起来监听了 `*:22`
|
||||||
|
|
||||||
|
最终 ARP 仍然不通,表现为:
|
||||||
|
|
||||||
|
- `arp` 中 `192.168.15.244` 为 `incomplete`
|
||||||
|
- `nc -vz 192.168.15.244 22` 超时
|
||||||
|
|
||||||
|
所以这次真正可用的 SSH 入口,不是 USB 直连,而是 Wi-Fi。
|
||||||
|
|
||||||
|
### 4. 真正成功的是 Wi-Fi 上的 DropBear
|
||||||
|
|
||||||
|
最终确认:
|
||||||
|
|
||||||
|
- Wi-Fi IP 是 `192.168.72.3`
|
||||||
|
- 服务端 banner 是 `dropbear_2020.81`
|
||||||
|
- 成功接受的密钥是 `~/.ssh/id_ed25519_git`
|
||||||
|
|
||||||
|
验证结果:
|
||||||
|
|
||||||
|
- `nc -vz 192.168.72.3 22` 成功
|
||||||
|
- `ssh -i ~/.ssh/id_ed25519_git root@192.168.72.3 true` 成功
|
||||||
|
- 可拿到 `uid=0(root)`
|
||||||
|
|
||||||
|
### 5. 设备实际跑的是手工拉起的 DropBear
|
||||||
|
|
||||||
|
最终有效进程不是系统默认那份 OpenSSH,而是我们在 Kindle 本机手工拉起的:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
bin/dropbearmulti dropbear -F -E -p 22 -P /mnt/us/usbnet/run/dropbear-force-22.pid -n
|
||||||
|
```
|
||||||
|
|
||||||
|
其中:
|
||||||
|
|
||||||
|
- `-p 22` 监听 22 端口
|
||||||
|
- `-n` 是这个 Kindle hack 里的“禁用密码检查”开关
|
||||||
|
|
||||||
|
`dropbear -h` 已实机确认:
|
||||||
|
|
||||||
|
```text
|
||||||
|
-n Disable password checking (/!\ Kindle hack, don't use this!)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 一次成的推荐操作
|
||||||
|
|
||||||
|
### A. 第一次准备
|
||||||
|
|
||||||
|
1. 越狱
|
||||||
|
2. 安装 KUAL
|
||||||
|
3. 安装 USBNetwork
|
||||||
|
4. 安装 KTerm
|
||||||
|
5. 同步 dashboard 到 `/mnt/us/dashboard`
|
||||||
|
6. 同步 KUAL 菜单到 `/mnt/us/extensions/kindle-dash`
|
||||||
|
|
||||||
|
### B. Dashboard 调试
|
||||||
|
|
||||||
|
1. KUAL -> `Dashboard Debug On`
|
||||||
|
2. KUAL -> `Kindle Dashboard`
|
||||||
|
3. 调试完成后再 `Dashboard Debug Off`
|
||||||
|
|
||||||
|
### C. SSH 启动的最短稳定路线
|
||||||
|
|
||||||
|
如果外部 SSH 一开始就不通,不要继续折腾 USB。
|
||||||
|
|
||||||
|
先把仓库里的 Kindle 辅助脚本复制到设备根目录:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scp /Users/gavin/kindle-dash/scripts/kindle/*.sh kindle:/mnt/us/
|
||||||
|
```
|
||||||
|
|
||||||
|
如果这时还没有 `ssh kindle`,也可以先通过 USB 存储模式手动拷到 `/mnt/us/`。
|
||||||
|
|
||||||
|
然后在 Kindle 本机的 KTerm 里执行:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sh /mnt/us/ssh-force-dropbear-22.sh
|
||||||
|
/mnt/us/usbnet/bin/lsof -n -P -iTCP:22
|
||||||
|
```
|
||||||
|
|
||||||
|
必须看到类似:
|
||||||
|
|
||||||
|
```text
|
||||||
|
dropbear... TCP *:22 (LISTEN)
|
||||||
|
```
|
||||||
|
|
||||||
|
然后从 Mac 走 Wi-Fi 登录:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ssh -i ~/.ssh/id_ed25519_git root@192.168.72.3
|
||||||
|
```
|
||||||
|
|
||||||
|
或:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ssh kindle
|
||||||
|
```
|
||||||
|
|
||||||
|
### D. 登录成功后验证
|
||||||
|
|
||||||
|
登录后执行:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
id
|
||||||
|
uname -a
|
||||||
|
ps -ef | grep -E 'sshd|dropbear|telnetd' | grep -v grep
|
||||||
|
```
|
||||||
|
|
||||||
|
应至少看到:
|
||||||
|
|
||||||
|
- `uid=0(root)`
|
||||||
|
- `dropbearmulti dropbear ... -p 22 ...`
|
||||||
|
|
||||||
|
## 今天踩过的坑
|
||||||
|
|
||||||
|
### 1. 不要一开始就把重点放在 USB 直连 SSH
|
||||||
|
|
||||||
|
USBNetwork 的确安装了,但:
|
||||||
|
|
||||||
|
- USBMS 和 USBNetwork 是互斥的
|
||||||
|
- USB 侧 IP 容易看错
|
||||||
|
- Mac 侧可能出现多个候选接口
|
||||||
|
- 接口名、ARP、链路状态都容易误判
|
||||||
|
|
||||||
|
所以:
|
||||||
|
|
||||||
|
- USB 更适合拷文件
|
||||||
|
- 真正稳定的远程入口优先走 Wi-Fi SSH
|
||||||
|
|
||||||
|
### 2. 不要相信 `ping` 单独判断
|
||||||
|
|
||||||
|
今天实际情况是:
|
||||||
|
|
||||||
|
- 某些阶段 `ping` 不通
|
||||||
|
- 但 `ssh` 可以通
|
||||||
|
|
||||||
|
所以后续统一使用:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nc -vz <ip> 22
|
||||||
|
ssh <host>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 不要把 “出现 Password:” 等同于“密码一定对”
|
||||||
|
|
||||||
|
前期出现过:
|
||||||
|
|
||||||
|
```text
|
||||||
|
ssh root@...
|
||||||
|
Password:
|
||||||
|
```
|
||||||
|
|
||||||
|
这只能说明对端当时有 SSH 在监听。
|
||||||
|
不代表:
|
||||||
|
|
||||||
|
- 这就是正确的那份 SSH 服务
|
||||||
|
- 配置文件就是你刚改的那份
|
||||||
|
- 默认密码一定可用
|
||||||
|
|
||||||
|
### 4. 本机 shell 才是最终裁判
|
||||||
|
|
||||||
|
如果出现任何矛盾,比如:
|
||||||
|
|
||||||
|
- KUAL 说 `sshd up`
|
||||||
|
- Mac 连不上
|
||||||
|
- 改过配置却没生效
|
||||||
|
|
||||||
|
立即转入 KTerm,本机检查:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
id
|
||||||
|
ps -ef
|
||||||
|
/mnt/us/usbnet/bin/lsof -n -P -iTCP:22
|
||||||
|
cat /mnt/us/usbnet/etc/config
|
||||||
|
```
|
||||||
|
|
||||||
|
## 今天留下的可复用资产
|
||||||
|
|
||||||
|
### 1. Dashboard 调试入口
|
||||||
|
|
||||||
|
已在仓库中加入:
|
||||||
|
|
||||||
|
- [dash/src/debug-on.sh](/Users/gavin/kindle-dash/dash/src/debug-on.sh)
|
||||||
|
- [dash/src/debug-off.sh](/Users/gavin/kindle-dash/dash/src/debug-off.sh)
|
||||||
|
- [dash/src/start-debug.sh](/Users/gavin/kindle-dash/dash/src/start-debug.sh)
|
||||||
|
- [dash/KUAL/kindle-dash/menu.json](/Users/gavin/kindle-dash/dash/KUAL/kindle-dash/menu.json)
|
||||||
|
|
||||||
|
### 2. Mac 侧 USBNetwork 辅助脚本
|
||||||
|
|
||||||
|
已在仓库中加入:
|
||||||
|
|
||||||
|
- [scripts/connect-kindle-usbnet-mac.sh](/Users/gavin/kindle-dash/scripts/connect-kindle-usbnet-mac.sh)
|
||||||
|
|
||||||
|
### 3. Kindle 侧 SSH 救援脚本
|
||||||
|
|
||||||
|
已在仓库中加入:
|
||||||
|
|
||||||
|
- [scripts/kindle/ssh-collect.sh](/Users/gavin/kindle-dash/scripts/kindle/ssh-collect.sh)
|
||||||
|
- [scripts/kindle/ssh-fix-all-keys.sh](/Users/gavin/kindle-dash/scripts/kindle/ssh-fix-all-keys.sh)
|
||||||
|
- [scripts/kindle/ssh-force-openssh-22.sh](/Users/gavin/kindle-dash/scripts/kindle/ssh-force-openssh-22.sh)
|
||||||
|
- [scripts/kindle/ssh-force-dropbear-22.sh](/Users/gavin/kindle-dash/scripts/kindle/ssh-force-dropbear-22.sh)
|
||||||
|
- [scripts/kindle/ssh-stop-all.sh](/Users/gavin/kindle-dash/scripts/kindle/ssh-stop-all.sh)
|
||||||
|
|
||||||
|
推荐复制方式:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scp /Users/gavin/kindle-dash/scripts/kindle/*.sh kindle:/mnt/us/
|
||||||
|
```
|
||||||
|
|
||||||
|
作用:
|
||||||
|
|
||||||
|
- 自动尝试 `en8`、`en11`
|
||||||
|
- 给候选接口加 `192.168.15.201/24`
|
||||||
|
- 探测 `192.168.15.244:22`
|
||||||
|
- 如果 USB 链路能通,再继续尝试 SSH
|
||||||
|
|
||||||
|
这次虽然最终证明 USB 不是稳定入口,但这个脚本保留着仍有价值。
|
||||||
|
|
||||||
|
## 建议的下次标准流程
|
||||||
|
|
||||||
|
下次同型号设备,推荐严格按下面顺序:
|
||||||
|
|
||||||
|
1. 先关掉路由器无线隔离,确保 Kindle 和 Mac 在同一主 Wi-Fi。
|
||||||
|
2. 先把 dashboard 的 `Debug On/Off` 菜单装好。
|
||||||
|
3. 先装 KTerm,不要等 SSH 坏了才找本地终端。
|
||||||
|
4. 初次调试先用 `Dashboard Debug On`,避免设备自动挂起。
|
||||||
|
5. SSH 优先目标设为 Wi-Fi,不要优先押宝 USB 直连。
|
||||||
|
6. 外部 SSH 不通时,立即转 KTerm。
|
||||||
|
7. 在 KTerm 手工拉起 `dropbear` 后,再从 Mac 走 Wi-Fi 登录。
|
||||||
|
8. 登录成功后再考虑要不要继续优化 USBNetwork 或持久化 SSH 配置。
|
||||||
|
|
||||||
|
## 当前最短命令
|
||||||
|
|
||||||
|
### Kindle 端
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sh /mnt/us/ssh-force-dropbear-22.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mac 端
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ssh kindle
|
||||||
|
```
|
||||||
|
|
||||||
|
如果 `ssh kindle` 不通,先确认:
|
||||||
|
|
||||||
|
- Kindle 还连着 Wi-Fi
|
||||||
|
- 当前 IP 还是 `192.168.72.3`
|
||||||
|
- `dropbear` 还在 `*:22` 监听
|
||||||
|
|
||||||
|
## 最后一条经验
|
||||||
|
|
||||||
|
今天真正节省时间的做法不是“继续猜”,而是尽快把问题缩到:
|
||||||
|
|
||||||
|
- 这是网络层问题
|
||||||
|
- 这是进程问题
|
||||||
|
- 这是 key 问题
|
||||||
|
- 还是这是错误 IP 问题
|
||||||
|
|
||||||
|
一旦拿到本机 KTerm root shell,排障效率会比外部盲试高一个数量级。
|
||||||
@@ -13,6 +13,11 @@
|
|||||||
- 节点:`6:2`
|
- 节点:`6:2`
|
||||||
- 链接:`https://www.figma.com/design/3bXFNM5nM6mCq0TpL3nPYK/calendar?node-id=6-2&m=dev`
|
- 链接:`https://www.figma.com/design/3bXFNM5nM6mCq0TpL3nPYK/calendar?node-id=6-2&m=dev`
|
||||||
|
|
||||||
|
指针与表盘素材的拆分约束来自 Figma annotation:
|
||||||
|
|
||||||
|
- 节点:`23:418`
|
||||||
|
- 链接:`https://www.figma.com/design/3bXFNM5nM6mCq0TpL3nPYK/calendar?node-id=23-418&m=dev`
|
||||||
|
|
||||||
该节点 annotation 已明确:
|
该节点 annotation 已明确:
|
||||||
|
|
||||||
- `阳历当天`
|
- `阳历当天`
|
||||||
@@ -123,9 +128,64 @@
|
|||||||
- 分针每分钟一个角度,共 `60` 张
|
- 分针每分钟一个角度,共 `60` 张
|
||||||
- 时针如果要做到真正随分钟连续移动,需要 `12 * 60 = 720` 张
|
- 时针如果要做到真正随分钟连续移动,需要 `12 * 60 = 720` 张
|
||||||
- 这些都是小尺寸 patch,不是整屏图,体积可控
|
- 这些都是小尺寸 patch,不是整屏图,体积可控
|
||||||
|
- 所有素材统一放在 Kindle 本地 `assets/` 目录下
|
||||||
|
|
||||||
|
推荐目录:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/mnt/us/dashboard/assets/clock-face.png
|
||||||
|
/mnt/us/dashboard/assets/hour-hand/000.png ... 719.png
|
||||||
|
/mnt/us/dashboard/assets/minute-hand/00.png ... 59.png
|
||||||
|
```
|
||||||
|
|
||||||
如果后续确认 Kindle 端存在稳定的本地绘线工具,再考虑把指针改成算法绘制;当前版本不依赖这个前提。
|
如果后续确认 Kindle 端存在稳定的本地绘线工具,再考虑把指针改成算法绘制;当前版本不依赖这个前提。
|
||||||
|
|
||||||
|
### 3.4 指针锚点与缩放规则
|
||||||
|
|
||||||
|
这部分是 Kindle 端渲染能否正确对齐的关键约束,不能省略。
|
||||||
|
|
||||||
|
根据 Figma 节点 `23:418` 的 annotation 与素材结构:
|
||||||
|
|
||||||
|
- `hour-hand` 与 `minute-hand` 的中心位置不是素材端点
|
||||||
|
- 指针的旋转中心是素材内部的圆点中心
|
||||||
|
- Kindle 端贴图时,不能把图片底边、顶边或几何中心当作对齐基准
|
||||||
|
|
||||||
|
因此,运行时必须遵守下面的规则:
|
||||||
|
|
||||||
|
1. 每类指针素材都要记录自己的 `pivot`
|
||||||
|
2. 渲染时以 `pivot` 对齐表盘中心,而不是以素材端点对齐
|
||||||
|
3. 指针长度不能写死为某个绝对像素值,而是要随表盘大小同比例缩放
|
||||||
|
4. `pivot` 偏移量也必须和指针长度一起同比例缩放
|
||||||
|
|
||||||
|
也就是说,如果表盘从设计稿尺寸缩到 Kindle 运行时尺寸:
|
||||||
|
|
||||||
|
- 时针长度随表盘直径同比例缩放
|
||||||
|
- 分针长度随表盘直径同比例缩放
|
||||||
|
- 时针的 `pivot.x / pivot.y` 也按同一比例缩放
|
||||||
|
- 分针的 `pivot.x / pivot.y` 也按同一比例缩放
|
||||||
|
|
||||||
|
推荐缩放公式:
|
||||||
|
|
||||||
|
```text
|
||||||
|
scale = min(runtime_clock_width / design_clock_width, runtime_clock_height / design_clock_height)
|
||||||
|
|
||||||
|
rendered_hand_width = source_hand_width * scale
|
||||||
|
rendered_hand_height = source_hand_height * scale
|
||||||
|
rendered_pivot_x = source_pivot_x * scale
|
||||||
|
rendered_pivot_y = source_pivot_y * scale
|
||||||
|
```
|
||||||
|
|
||||||
|
其中:
|
||||||
|
|
||||||
|
- `design_clock_width / design_clock_height` 指 Figma 导出该套素材时所对应的基准表盘尺寸
|
||||||
|
- `runtime_clock_width / runtime_clock_height` 指 Kindle 端最终时钟区域尺寸
|
||||||
|
|
||||||
|
这意味着:
|
||||||
|
|
||||||
|
- 表盘主体和指针素材必须来自同一套基准设计尺寸
|
||||||
|
- 不能单独替换某一类不同倍率的指针图,否则时针、分针与刻度会失配
|
||||||
|
- 如果未来切换到别的机型或别的表盘尺寸,只需要换 `clockRegion` 与 `scale`,不需要重做对齐逻辑
|
||||||
|
|
||||||
## 4. 为什么不能只把表盘放进整页背景
|
## 4. 为什么不能只把表盘放进整页背景
|
||||||
|
|
||||||
这个问题必须单独说明。
|
这个问题必须单独说明。
|
||||||
@@ -275,14 +335,28 @@ kindle local:
|
|||||||
"height": 220
|
"height": 220
|
||||||
},
|
},
|
||||||
"clockFace": {
|
"clockFace": {
|
||||||
"path": "clock-face.png",
|
"path": "assets/clock-face.png",
|
||||||
"managedOnKindle": true
|
"managedOnKindle": true,
|
||||||
|
"designWidth": 220,
|
||||||
|
"designHeight": 220
|
||||||
},
|
},
|
||||||
"clockHands": {
|
"clockHands": {
|
||||||
"hourPattern": "assets/hour-hand/%03d.png",
|
"hourPattern": "assets/hour-hand/%03d.png",
|
||||||
"minutePattern": "assets/minute-hand/%02d.png",
|
"minutePattern": "assets/minute-hand/%02d.png",
|
||||||
"refreshIntervalMinutes": 1,
|
"refreshIntervalMinutes": 1,
|
||||||
"networkRequired": false
|
"networkRequired": false,
|
||||||
|
"anchorMode": "pivot",
|
||||||
|
"scaleWithClockFace": true,
|
||||||
|
"hourHand": {
|
||||||
|
"sourceDesignWidth": 220,
|
||||||
|
"sourceDesignHeight": 220,
|
||||||
|
"pivotSource": "figma-annotation-center-dot"
|
||||||
|
},
|
||||||
|
"minuteHand": {
|
||||||
|
"sourceDesignWidth": 220,
|
||||||
|
"sourceDesignHeight": 220,
|
||||||
|
"pivotSource": "figma-annotation-center-dot"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -291,6 +365,8 @@ kindle local:
|
|||||||
|
|
||||||
- `x/y/width/height` 先按设计稿记录
|
- `x/y/width/height` 先按设计稿记录
|
||||||
- 真正接入 Kindle 时,要换算成最终截图分辨率下的实际像素值
|
- 真正接入 Kindle 时,要换算成最终截图分辨率下的实际像素值
|
||||||
|
- `pivotSource` 表示指针锚点来自 Figma 素材内部圆点中心,而不是素材端点
|
||||||
|
- `scaleWithClockFace=true` 表示运行时必须按表盘尺寸同步缩放指针长度与 `pivot`
|
||||||
|
|
||||||
## 8. Kindle 侧刷新策略
|
## 8. Kindle 侧刷新策略
|
||||||
|
|
||||||
@@ -332,12 +408,13 @@ MobileRead Wiki 明确写了:
|
|||||||
- `hour_index = ((hour % 12) * 60 + minute) = 000..719`
|
- `hour_index = ((hour % 12) * 60 + minute) = 000..719`
|
||||||
3. 在固定坐标先画:
|
3. 在固定坐标先画:
|
||||||
- `clock-face.png`
|
- `clock-face.png`
|
||||||
4. 再画:
|
4. 根据当前 `clockRegion` 与素材基准尺寸计算统一缩放比例
|
||||||
|
5. 以素材内部 `pivot` 对齐表盘中心,先画:
|
||||||
- `hour-hand/<hour_index>.png`
|
- `hour-hand/<hour_index>.png`
|
||||||
5. 再画:
|
6. 再以素材内部 `pivot` 对齐表盘中心,画:
|
||||||
- `minute-hand/<minute_index>.png`
|
- `minute-hand/<minute_index>.png`
|
||||||
6. 默认做局部/普通刷新
|
7. 默认做局部/普通刷新
|
||||||
7. 每 `10` 到 `15` 分钟对时钟区域补一次全刷,清理残影
|
8. 每 `10` 到 `15` 分钟对时钟区域补一次全刷,清理残影
|
||||||
|
|
||||||
### 8.3 功耗模型
|
### 8.3 功耗模型
|
||||||
|
|
||||||
@@ -412,6 +489,8 @@ export CLOCK_FULL_REFRESH_INTERVAL_MINUTES=15
|
|||||||
|
|
||||||
- 产出 `clock-face.png`
|
- 产出 `clock-face.png`
|
||||||
- 产出 `hour-hand` 与 `minute-hand` 素材库
|
- 产出 `hour-hand` 与 `minute-hand` 素材库
|
||||||
|
- 明确每类指针素材的 `pivot` 与基准表盘尺寸
|
||||||
|
- 确保时针、分针长度能随表盘尺寸同比例缩放适配
|
||||||
|
|
||||||
输出:
|
输出:
|
||||||
|
|
||||||
@@ -443,7 +522,7 @@ export CLOCK_FULL_REFRESH_INTERVAL_MINUTES=15
|
|||||||
- 本地 `minute-hand/*.png`
|
- 本地 `minute-hand/*.png`
|
||||||
4. 分钟刷新时:
|
4. 分钟刷新时:
|
||||||
- 先重画表盘
|
- 先重画表盘
|
||||||
- 再重画时针
|
- 再按 `pivot + scale` 规则重画时针
|
||||||
- 再重画分针
|
- 再按 `pivot + scale` 规则重画分针
|
||||||
|
|
||||||
也就是说,**背景是远端低频资源,时钟是本地高频资源,二者不要混在同一个刷新链路里**。
|
也就是说,**背景是远端低频资源,时钟是本地高频资源,二者不要混在同一个刷新链路里**。
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ LOW_BATTERY_CMD="$DIR/local/low-battery.sh"
|
|||||||
REFRESH_SCHEDULE=${REFRESH_SCHEDULE:-"2,32 8-17 * * MON-FRI"}
|
REFRESH_SCHEDULE=${REFRESH_SCHEDULE:-"2,32 8-17 * * MON-FRI"}
|
||||||
FULL_DISPLAY_REFRESH_RATE=${FULL_DISPLAY_REFRESH_RATE:-0}
|
FULL_DISPLAY_REFRESH_RATE=${FULL_DISPLAY_REFRESH_RATE:-0}
|
||||||
SLEEP_SCREEN_INTERVAL=${SLEEP_SCREEN_INTERVAL:-3600}
|
SLEEP_SCREEN_INTERVAL=${SLEEP_SCREEN_INTERVAL:-3600}
|
||||||
|
DISABLE_SYSTEM_SUSPEND=${DISABLE_SYSTEM_SUSPEND:-false}
|
||||||
RTC=/sys/devices/platform/mxc_rtc.0/wakeup_enable
|
RTC=/sys/devices/platform/mxc_rtc.0/wakeup_enable
|
||||||
|
|
||||||
LOW_BATTERY_REPORTING=${LOW_BATTERY_REPORTING:-false}
|
LOW_BATTERY_REPORTING=${LOW_BATTERY_REPORTING:-false}
|
||||||
@@ -27,6 +28,10 @@ init() {
|
|||||||
|
|
||||||
echo "Starting dashboard with $REFRESH_SCHEDULE refresh..."
|
echo "Starting dashboard with $REFRESH_SCHEDULE refresh..."
|
||||||
|
|
||||||
|
if [ "$DISABLE_SYSTEM_SUSPEND" = true ]; then
|
||||||
|
echo "System suspend disabled, using normal sleep between refreshes."
|
||||||
|
fi
|
||||||
|
|
||||||
/etc/init.d/framework stop
|
/etc/init.d/framework stop
|
||||||
initctl stop webreader >/dev/null 2>&1
|
initctl stop webreader >/dev/null 2>&1
|
||||||
echo powersave >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
|
echo powersave >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
|
||||||
@@ -88,6 +93,9 @@ rtc_sleep() {
|
|||||||
|
|
||||||
if [ "$DEBUG" = true ]; then
|
if [ "$DEBUG" = true ]; then
|
||||||
sleep "$duration"
|
sleep "$duration"
|
||||||
|
elif [ "$DISABLE_SYSTEM_SUSPEND" = true ]; then
|
||||||
|
echo "Skipping system suspend, sleeping for ${duration}s instead"
|
||||||
|
sleep "$duration"
|
||||||
else
|
else
|
||||||
# shellcheck disable=SC2039
|
# shellcheck disable=SC2039
|
||||||
[ "$(cat "$RTC")" -eq 0 ] && echo -n "$duration" >"$RTC"
|
[ "$(cat "$RTC")" -eq 0 ] && echo -n "$duration" >"$RTC"
|
||||||
|
|||||||
41
dash/src/debug-off.sh
Executable file
41
dash/src/debug-off.sh
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 持久关闭调试模式:修改 env.sh,恢复正常的省电挂起行为。
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
ENV_FILE="$DIR/local/env.sh"
|
||||||
|
TMP_FILE="$DIR/local/env.sh.tmp"
|
||||||
|
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "未找到配置文件:$ENV_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 只替换目标配置,避免重复追加同一环境变量。
|
||||||
|
awk '
|
||||||
|
BEGIN {
|
||||||
|
updated = 0
|
||||||
|
}
|
||||||
|
/^export DISABLE_SYSTEM_SUSPEND=/ {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=false"
|
||||||
|
updated = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{
|
||||||
|
print
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (!updated) {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$ENV_FILE" > "$TMP_FILE"
|
||||||
|
|
||||||
|
mv "$TMP_FILE" "$ENV_FILE"
|
||||||
|
|
||||||
|
# 已运行的 dashboard 进程不会重新读取 env.sh,切换后先停掉它,
|
||||||
|
# 避免旧进程继续按旧配置运行。
|
||||||
|
pkill -f "$DIR/dash.sh" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "已关闭 Dashboard 调试模式。当前 Dashboard 已停止,请重新启动 Kindle Dashboard。"
|
||||||
41
dash/src/debug-on.sh
Executable file
41
dash/src/debug-on.sh
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 持久开启调试模式:修改 env.sh,让后续普通启动也不进入系统挂起。
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
ENV_FILE="$DIR/local/env.sh"
|
||||||
|
TMP_FILE="$DIR/local/env.sh.tmp"
|
||||||
|
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "未找到配置文件:$ENV_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 只替换目标配置,避免重复追加同一环境变量。
|
||||||
|
awk '
|
||||||
|
BEGIN {
|
||||||
|
updated = 0
|
||||||
|
}
|
||||||
|
/^export DISABLE_SYSTEM_SUSPEND=/ {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=true"
|
||||||
|
updated = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{
|
||||||
|
print
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (!updated) {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$ENV_FILE" > "$TMP_FILE"
|
||||||
|
|
||||||
|
mv "$TMP_FILE" "$ENV_FILE"
|
||||||
|
|
||||||
|
# 已运行的 dashboard 进程不会重新读取 env.sh,切换后先停掉它,
|
||||||
|
# 避免旧进程继续按旧配置进入系统挂起。
|
||||||
|
pkill -f "$DIR/dash.sh" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "已开启 Dashboard 调试模式。当前 Dashboard 已停止,请重新启动 Kindle Dashboard。"
|
||||||
@@ -13,6 +13,11 @@ export TIMEZONE=${TIMEZONE:-"Asia/Shanghai"}
|
|||||||
# 等图片尺寸与刷新逻辑确认无误后,再改回 4 之类的值以节省功耗。
|
# 等图片尺寸与刷新逻辑确认无误后,再改回 4 之类的值以节省功耗。
|
||||||
export FULL_DISPLAY_REFRESH_RATE=${FULL_DISPLAY_REFRESH_RATE:-0}
|
export FULL_DISPLAY_REFRESH_RATE=${FULL_DISPLAY_REFRESH_RATE:-0}
|
||||||
|
|
||||||
|
# 调试开关:设为 true 后,主循环仍会按计划拉图和刷新屏幕,
|
||||||
|
# 但不会把 Kindle 写入 /sys/power/state 进入系统挂起。
|
||||||
|
# 适合通过 KUAL 或普通 start.sh 连续观察效果,调试结束后再改回 false。
|
||||||
|
export DISABLE_SYSTEM_SUSPEND=${DISABLE_SYSTEM_SUSPEND:-false}
|
||||||
|
|
||||||
# When the time until the next wakeup is greater or equal to this number,
|
# When the time until the next wakeup is greater or equal to this number,
|
||||||
# the dashboard will not be refreshed anymore, but instead show a
|
# the dashboard will not be refreshed anymore, but instead show a
|
||||||
# 'kindle is sleeping' screen. This can be useful if your schedule only runs
|
# 'kindle is sleeping' screen. This can be useful if your schedule only runs
|
||||||
|
|||||||
8
dash/src/start-debug.sh
Executable file
8
dash/src/start-debug.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 调试启动脚本:强制关闭系统挂起,便于在 Kindle 上持续观察刷新效果。
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
|
||||||
|
export DISABLE_SYSTEM_SUSPEND=true
|
||||||
|
|
||||||
|
exec "$DIR/start.sh"
|
||||||
41
dash/staging/device/dashboard/debug-off.sh
Executable file
41
dash/staging/device/dashboard/debug-off.sh
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 持久关闭调试模式:修改 env.sh,恢复正常的省电挂起行为。
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
ENV_FILE="$DIR/local/env.sh"
|
||||||
|
TMP_FILE="$DIR/local/env.sh.tmp"
|
||||||
|
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "未找到配置文件:$ENV_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 只替换目标配置,避免重复追加同一环境变量。
|
||||||
|
awk '
|
||||||
|
BEGIN {
|
||||||
|
updated = 0
|
||||||
|
}
|
||||||
|
/^export DISABLE_SYSTEM_SUSPEND=/ {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=false"
|
||||||
|
updated = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{
|
||||||
|
print
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (!updated) {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$ENV_FILE" > "$TMP_FILE"
|
||||||
|
|
||||||
|
mv "$TMP_FILE" "$ENV_FILE"
|
||||||
|
|
||||||
|
# 已运行的 dashboard 进程不会重新读取 env.sh,切换后先停掉它,
|
||||||
|
# 避免旧进程继续按旧配置运行。
|
||||||
|
pkill -f "$DIR/dash.sh" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "已关闭 Dashboard 调试模式。当前 Dashboard 已停止,请重新启动 Kindle Dashboard。"
|
||||||
41
dash/staging/device/dashboard/debug-on.sh
Executable file
41
dash/staging/device/dashboard/debug-on.sh
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 持久开启调试模式:修改 env.sh,让后续普通启动也不进入系统挂起。
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
ENV_FILE="$DIR/local/env.sh"
|
||||||
|
TMP_FILE="$DIR/local/env.sh.tmp"
|
||||||
|
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "未找到配置文件:$ENV_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 只替换目标配置,避免重复追加同一环境变量。
|
||||||
|
awk '
|
||||||
|
BEGIN {
|
||||||
|
updated = 0
|
||||||
|
}
|
||||||
|
/^export DISABLE_SYSTEM_SUSPEND=/ {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=true"
|
||||||
|
updated = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{
|
||||||
|
print
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (!updated) {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$ENV_FILE" > "$TMP_FILE"
|
||||||
|
|
||||||
|
mv "$TMP_FILE" "$ENV_FILE"
|
||||||
|
|
||||||
|
# 已运行的 dashboard 进程不会重新读取 env.sh,切换后先停掉它,
|
||||||
|
# 避免旧进程继续按旧配置进入系统挂起。
|
||||||
|
pkill -f "$DIR/dash.sh" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "已开启 Dashboard 调试模式。当前 Dashboard 已停止,请重新启动 Kindle Dashboard。"
|
||||||
8
dash/staging/device/dashboard/start-debug.sh
Executable file
8
dash/staging/device/dashboard/start-debug.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 调试启动脚本:强制关闭系统挂起,便于在 Kindle 上持续观察刷新效果。
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
|
||||||
|
export DISABLE_SYSTEM_SUSPEND=true
|
||||||
|
|
||||||
|
exec "$DIR/start.sh"
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
{
|
{
|
||||||
"items": [
|
"items": [
|
||||||
{"name": "Kindle Dashboard", "action": "/mnt/us/dashboard/start.sh"}
|
{"name": "Kindle Dashboard", "action": "/mnt/us/dashboard/start.sh"},
|
||||||
|
{"name": "Dashboard Debug On", "action": "/mnt/us/dashboard/debug-on.sh"},
|
||||||
|
{"name": "Dashboard Debug Off", "action": "/mnt/us/dashboard/debug-off.sh"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
41
dash/staging/kindle-dash-release/debug-off.sh
Executable file
41
dash/staging/kindle-dash-release/debug-off.sh
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 持久关闭调试模式:修改 env.sh,恢复正常的省电挂起行为。
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
ENV_FILE="$DIR/local/env.sh"
|
||||||
|
TMP_FILE="$DIR/local/env.sh.tmp"
|
||||||
|
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "未找到配置文件:$ENV_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 只替换目标配置,避免重复追加同一环境变量。
|
||||||
|
awk '
|
||||||
|
BEGIN {
|
||||||
|
updated = 0
|
||||||
|
}
|
||||||
|
/^export DISABLE_SYSTEM_SUSPEND=/ {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=false"
|
||||||
|
updated = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{
|
||||||
|
print
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (!updated) {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$ENV_FILE" > "$TMP_FILE"
|
||||||
|
|
||||||
|
mv "$TMP_FILE" "$ENV_FILE"
|
||||||
|
|
||||||
|
# 已运行的 dashboard 进程不会重新读取 env.sh,切换后先停掉它,
|
||||||
|
# 避免旧进程继续按旧配置运行。
|
||||||
|
pkill -f "$DIR/dash.sh" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "已关闭 Dashboard 调试模式。当前 Dashboard 已停止,请重新启动 Kindle Dashboard。"
|
||||||
41
dash/staging/kindle-dash-release/debug-on.sh
Executable file
41
dash/staging/kindle-dash-release/debug-on.sh
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 持久开启调试模式:修改 env.sh,让后续普通启动也不进入系统挂起。
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
ENV_FILE="$DIR/local/env.sh"
|
||||||
|
TMP_FILE="$DIR/local/env.sh.tmp"
|
||||||
|
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "未找到配置文件:$ENV_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 只替换目标配置,避免重复追加同一环境变量。
|
||||||
|
awk '
|
||||||
|
BEGIN {
|
||||||
|
updated = 0
|
||||||
|
}
|
||||||
|
/^export DISABLE_SYSTEM_SUSPEND=/ {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=true"
|
||||||
|
updated = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{
|
||||||
|
print
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (!updated) {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$ENV_FILE" > "$TMP_FILE"
|
||||||
|
|
||||||
|
mv "$TMP_FILE" "$ENV_FILE"
|
||||||
|
|
||||||
|
# 已运行的 dashboard 进程不会重新读取 env.sh,切换后先停掉它,
|
||||||
|
# 避免旧进程继续按旧配置进入系统挂起。
|
||||||
|
pkill -f "$DIR/dash.sh" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "已开启 Dashboard 调试模式。当前 Dashboard 已停止,请重新启动 Kindle Dashboard。"
|
||||||
8
dash/staging/kindle-dash-release/start-debug.sh
Executable file
8
dash/staging/kindle-dash-release/start-debug.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 调试启动脚本:强制关闭系统挂起,便于在 Kindle 上持续观察刷新效果。
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
|
||||||
|
export DISABLE_SYSTEM_SUSPEND=true
|
||||||
|
|
||||||
|
exec "$DIR/start.sh"
|
||||||
41
dash/staging/post-jailbreak-root/dashboard/debug-off.sh
Executable file
41
dash/staging/post-jailbreak-root/dashboard/debug-off.sh
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 持久关闭调试模式:修改 env.sh,恢复正常的省电挂起行为。
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
ENV_FILE="$DIR/local/env.sh"
|
||||||
|
TMP_FILE="$DIR/local/env.sh.tmp"
|
||||||
|
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "未找到配置文件:$ENV_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 只替换目标配置,避免重复追加同一环境变量。
|
||||||
|
awk '
|
||||||
|
BEGIN {
|
||||||
|
updated = 0
|
||||||
|
}
|
||||||
|
/^export DISABLE_SYSTEM_SUSPEND=/ {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=false"
|
||||||
|
updated = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{
|
||||||
|
print
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (!updated) {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$ENV_FILE" > "$TMP_FILE"
|
||||||
|
|
||||||
|
mv "$TMP_FILE" "$ENV_FILE"
|
||||||
|
|
||||||
|
# 已运行的 dashboard 进程不会重新读取 env.sh,切换后先停掉它,
|
||||||
|
# 避免旧进程继续按旧配置运行。
|
||||||
|
pkill -f "$DIR/dash.sh" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "已关闭 Dashboard 调试模式。当前 Dashboard 已停止,请重新启动 Kindle Dashboard。"
|
||||||
41
dash/staging/post-jailbreak-root/dashboard/debug-on.sh
Executable file
41
dash/staging/post-jailbreak-root/dashboard/debug-on.sh
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 持久开启调试模式:修改 env.sh,让后续普通启动也不进入系统挂起。
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
ENV_FILE="$DIR/local/env.sh"
|
||||||
|
TMP_FILE="$DIR/local/env.sh.tmp"
|
||||||
|
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "未找到配置文件:$ENV_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 只替换目标配置,避免重复追加同一环境变量。
|
||||||
|
awk '
|
||||||
|
BEGIN {
|
||||||
|
updated = 0
|
||||||
|
}
|
||||||
|
/^export DISABLE_SYSTEM_SUSPEND=/ {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=true"
|
||||||
|
updated = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{
|
||||||
|
print
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (!updated) {
|
||||||
|
print "export DISABLE_SYSTEM_SUSPEND=true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$ENV_FILE" > "$TMP_FILE"
|
||||||
|
|
||||||
|
mv "$TMP_FILE" "$ENV_FILE"
|
||||||
|
|
||||||
|
# 已运行的 dashboard 进程不会重新读取 env.sh,切换后先停掉它,
|
||||||
|
# 避免旧进程继续按旧配置进入系统挂起。
|
||||||
|
pkill -f "$DIR/dash.sh" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "已开启 Dashboard 调试模式。当前 Dashboard 已停止,请重新启动 Kindle Dashboard。"
|
||||||
8
dash/staging/post-jailbreak-root/dashboard/start-debug.sh
Executable file
8
dash/staging/post-jailbreak-root/dashboard/start-debug.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 调试启动脚本:强制关闭系统挂起,便于在 Kindle 上持续观察刷新效果。
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
|
||||||
|
export DISABLE_SYSTEM_SUSPEND=true
|
||||||
|
|
||||||
|
exec "$DIR/start.sh"
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
{
|
{
|
||||||
"items": [
|
"items": [
|
||||||
{"name": "Kindle Dashboard", "action": "/mnt/us/dashboard/start.sh"}
|
{"name": "Kindle Dashboard", "action": "/mnt/us/dashboard/start.sh"},
|
||||||
|
{"name": "Dashboard Debug On", "action": "/mnt/us/dashboard/debug-on.sh"},
|
||||||
|
{"name": "Dashboard Debug Off", "action": "/mnt/us/dashboard/debug-off.sh"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
128
scripts/connect-kindle-usbnet-mac.sh
Executable file
128
scripts/connect-kindle-usbnet-mac.sh
Executable file
@@ -0,0 +1,128 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# 这个脚本用于在 Mac 上给 Kindle 的 USBNetwork 网卡补一个 192.168.15.x 地址,
|
||||||
|
# 然后立刻验证 22 端口和 SSH 公钥登录是否可用。
|
||||||
|
#
|
||||||
|
# 默认值适配当前这台 Kindle:
|
||||||
|
# - Kindle USB IP: 192.168.15.244
|
||||||
|
# - 本机别名 IP: 192.168.15.201
|
||||||
|
# - 默认网卡: en8
|
||||||
|
#
|
||||||
|
# 用法:
|
||||||
|
# sh scripts/connect-kindle-usbnet-mac.sh
|
||||||
|
# sh scripts/connect-kindle-usbnet-mac.sh auto 192.168.15.244 192.168.15.201
|
||||||
|
# sh scripts/connect-kindle-usbnet-mac.sh en8 192.168.15.244 192.168.15.201
|
||||||
|
#
|
||||||
|
# 参数说明:
|
||||||
|
# $1: Mac 上的 USB 网卡名,默认 auto(自动尝试 en8/en11)
|
||||||
|
# $2: Kindle 在 usbnet 模式下的 IP,默认 192.168.15.244
|
||||||
|
# $3: Mac 要补的别名 IP,默认 192.168.15.201
|
||||||
|
|
||||||
|
USB_IFACE="${1:-auto}"
|
||||||
|
KINDLE_IP="${2:-192.168.15.244}"
|
||||||
|
HOST_IP="${3:-192.168.15.201}"
|
||||||
|
|
||||||
|
KEY1="${HOME}/.ssh/id_ed25519"
|
||||||
|
KEY2="${HOME}/.ssh/id_ed25519_git"
|
||||||
|
|
||||||
|
pick_iface() {
|
||||||
|
if [ "${USB_IFACE}" != "auto" ]; then
|
||||||
|
echo "${USB_IFACE}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 当前这台 Mac 在 Kindle 插入后会出现多个活动的 USB 相关接口,
|
||||||
|
# 实测常见候选是 en8 和 en11。这里按顺序轮询,哪个能打通 22 端口就用哪个。
|
||||||
|
for iface in en8 en11; do
|
||||||
|
if ! ifconfig "${iface}" >/dev/null 2>&1; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo >&2
|
||||||
|
echo "== 尝试接口 ${iface} ==" >&2
|
||||||
|
sudo ifconfig "${iface}" inet "${HOST_IP}" netmask 255.255.255.0 alias >/dev/null 2>&1 || true
|
||||||
|
sudo arp -d "${KINDLE_IP}" >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
echo "当前网卡状态:" >&2
|
||||||
|
ifconfig "${iface}" >&2
|
||||||
|
|
||||||
|
echo >&2
|
||||||
|
echo "路由检查:" >&2
|
||||||
|
route -n get "${KINDLE_IP}" >&2 || true
|
||||||
|
|
||||||
|
echo >&2
|
||||||
|
echo "22 端口探测:" >&2
|
||||||
|
if nc -vz -G 5 "${KINDLE_IP}" 22; then
|
||||||
|
echo "${iface}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "接口 ${iface} 未打通,清理别名后继续尝试下一个。" >&2
|
||||||
|
sudo ifconfig "${iface}" -alias "${HOST_IP}" >/dev/null 2>&1 || true
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "== 配置 USB 网卡 =="
|
||||||
|
echo "接口参数: ${USB_IFACE}"
|
||||||
|
echo "Kindle IP: ${KINDLE_IP}"
|
||||||
|
echo "本机别名 IP: ${HOST_IP}"
|
||||||
|
|
||||||
|
FOUND_IFACE="$(pick_iface)" || {
|
||||||
|
echo
|
||||||
|
echo "未能在候选 USB 网卡上打通 ${KINDLE_IP}:22。"
|
||||||
|
echo "通常说明 Kindle 端的 sshd/dropbear 没有在跑,或者 USBNetwork 链路本身还没真正连起来。"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_IFACE="${FOUND_IFACE}"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== 选中的接口 =="
|
||||||
|
echo "${USB_IFACE}"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== 尝试使用第一把密钥登录 =="
|
||||||
|
if [ -f "${KEY1}" ]; then
|
||||||
|
if ssh -i "${KEY1}" \
|
||||||
|
-o BatchMode=yes \
|
||||||
|
-o IdentitiesOnly=yes \
|
||||||
|
-o StrictHostKeyChecking=no \
|
||||||
|
-o UserKnownHostsFile=/tmp/kindle_usbnet_known_hosts_1 \
|
||||||
|
root@"${KINDLE_IP}" true; then
|
||||||
|
echo "第一把密钥验证成功,进入交互登录。"
|
||||||
|
exec ssh -i "${KEY1}" \
|
||||||
|
-o IdentitiesOnly=yes \
|
||||||
|
-o StrictHostKeyChecking=no \
|
||||||
|
-o UserKnownHostsFile=/tmp/kindle_usbnet_known_hosts_1 \
|
||||||
|
root@"${KINDLE_IP}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "未找到密钥: ${KEY1}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== 尝试使用第二把密钥登录 =="
|
||||||
|
if [ -f "${KEY2}" ]; then
|
||||||
|
if ssh -i "${KEY2}" \
|
||||||
|
-o BatchMode=yes \
|
||||||
|
-o IdentitiesOnly=yes \
|
||||||
|
-o StrictHostKeyChecking=no \
|
||||||
|
-o UserKnownHostsFile=/tmp/kindle_usbnet_known_hosts_2 \
|
||||||
|
root@"${KINDLE_IP}" true; then
|
||||||
|
echo "第二把密钥验证成功,进入交互登录。"
|
||||||
|
exec ssh -i "${KEY2}" \
|
||||||
|
-o IdentitiesOnly=yes \
|
||||||
|
-o StrictHostKeyChecking=no \
|
||||||
|
-o UserKnownHostsFile=/tmp/kindle_usbnet_known_hosts_2 \
|
||||||
|
root@"${KINDLE_IP}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "未找到密钥: ${KEY2}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "两把密钥都未登录成功。"
|
||||||
|
exit 1
|
||||||
87
scripts/kindle/ssh-collect.sh
Normal file
87
scripts/kindle/ssh-collect.sh
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# 采集 Kindle 当前 SSH、网络、进程、配置等诊断信息。
|
||||||
|
# 输出目录会落在 /mnt/us/ssh-debug/<时间戳>/collect.log。
|
||||||
|
|
||||||
|
TS="$(date +%Y%m%d-%H%M%S 2>/dev/null || echo now)"
|
||||||
|
OUT_DIR="/mnt/us/ssh-debug/${TS}"
|
||||||
|
LOG_FILE="${OUT_DIR}/collect.log"
|
||||||
|
|
||||||
|
mkdir -p "${OUT_DIR}"
|
||||||
|
exec >"${LOG_FILE}" 2>&1
|
||||||
|
|
||||||
|
echo "=== BASIC ==="
|
||||||
|
date 2>/dev/null || true
|
||||||
|
id 2>/dev/null || true
|
||||||
|
uname -a 2>/dev/null || true
|
||||||
|
echo "HOME=${HOME:-}"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== ROOT PASSWD ENTRY ==="
|
||||||
|
grep '^root:' /etc/passwd 2>/dev/null || true
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== SSH BINARIES ==="
|
||||||
|
ls -l /usr/sbin/sshd /mnt/us/usbnet/sbin/sshd /usr/bin/dropbear /mnt/us/usbnet/bin/dropbearmulti 2>/dev/null || true
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== PROCESS LIST ==="
|
||||||
|
ps -ef 2>/dev/null || ps 2>/dev/null || true
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== LSOF TCP:22 ==="
|
||||||
|
if [ -x /mnt/us/usbnet/bin/lsof ]; then
|
||||||
|
/mnt/us/usbnet/bin/lsof -n -P -iTCP:22 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== LSOF ALL TCP LISTENERS ==="
|
||||||
|
if [ -x /mnt/us/usbnet/bin/lsof ]; then
|
||||||
|
/mnt/us/usbnet/bin/lsof -n -P -iTCP -sTCP:LISTEN 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== /PROC/NET/TCP ==="
|
||||||
|
cat /proc/net/tcp 2>/dev/null || true
|
||||||
|
cat /proc/net/tcp6 2>/dev/null || true
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== NETWORK ==="
|
||||||
|
ifconfig -a 2>/dev/null || ifconfig 2>/dev/null || true
|
||||||
|
route -n 2>/dev/null || netstat -rn 2>/dev/null || true
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== IPTABLES ==="
|
||||||
|
iptables -S 2>/dev/null || true
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== USBNET RUN DIR ==="
|
||||||
|
ls -la /mnt/us/usbnet/run 2>/dev/null || true
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== USBNET CONFIG FILES ==="
|
||||||
|
for f in /mnt/us/usbnet/etc/config /mnt/us/usbnet/etc/sshd_config /mnt/us/usbnet/etc/authorized_keys; do
|
||||||
|
echo "--- ${f} ---"
|
||||||
|
sed -n '1,200p' "${f}" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== SYSTEM SSHD -T ==="
|
||||||
|
/usr/sbin/sshd -T 2>&1 || true
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== USBNET SSHD -T ==="
|
||||||
|
/mnt/us/usbnet/sbin/sshd -T -f /mnt/us/usbnet/etc/sshd_config 2>&1 || true
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== COMMON SSH DIRS ==="
|
||||||
|
for d in /root/.ssh /var/local/root/.ssh "${HOME:-/root}/.ssh" /mnt/us/usbnet/etc/dot.ssh; do
|
||||||
|
echo "--- ${d} ---"
|
||||||
|
ls -la "${d}" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== DONE ==="
|
||||||
|
echo "${OUT_DIR}"
|
||||||
38
scripts/kindle/ssh-fix-all-keys.sh
Normal file
38
scripts/kindle/ssh-fix-all-keys.sh
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# 把 usbnet 共用的 authorized_keys 同步到几处常见 root SSH 目录,
|
||||||
|
# 避免不同 sshd/dropbear 读取路径不一致。
|
||||||
|
|
||||||
|
TS="$(date +%Y%m%d-%H%M%S 2>/dev/null || echo now)"
|
||||||
|
OUT_DIR="/mnt/us/ssh-debug/${TS}"
|
||||||
|
LOG_FILE="${OUT_DIR}/fix-all-keys.log"
|
||||||
|
SOURCE_KEYS="/mnt/us/usbnet/etc/authorized_keys"
|
||||||
|
|
||||||
|
mkdir -p "${OUT_DIR}"
|
||||||
|
exec >"${LOG_FILE}" 2>&1
|
||||||
|
|
||||||
|
ROOT_HOME="$(awk -F: '/^root:/{print $6}' /etc/passwd 2>/dev/null || true)"
|
||||||
|
[ -n "${ROOT_HOME}" ] || ROOT_HOME="/tmp/root"
|
||||||
|
|
||||||
|
echo "Root home: ${ROOT_HOME}"
|
||||||
|
echo "Source keys: ${SOURCE_KEYS}"
|
||||||
|
|
||||||
|
for target_dir in "${ROOT_HOME}/.ssh" /root/.ssh /var/local/root/.ssh /mnt/us/usbnet/etc/dot.ssh; do
|
||||||
|
echo "--- target: ${target_dir} ---"
|
||||||
|
mkdir -p "${target_dir}"
|
||||||
|
if [ -f "${target_dir}/authorized_keys" ]; then
|
||||||
|
cp "${target_dir}/authorized_keys" "${target_dir}/authorized_keys.bak.${TS}" || true
|
||||||
|
fi
|
||||||
|
cp "${SOURCE_KEYS}" "${target_dir}/authorized_keys"
|
||||||
|
chmod 700 "${target_dir}" 2>/dev/null || true
|
||||||
|
chmod 600 "${target_dir}/authorized_keys" 2>/dev/null || true
|
||||||
|
ls -ld "${target_dir}" "${target_dir}/authorized_keys" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
|
||||||
|
killall -HUP sshd 2>/dev/null || true
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== DONE ==="
|
||||||
|
echo "${OUT_DIR}"
|
||||||
44
scripts/kindle/ssh-force-dropbear-22.sh
Normal file
44
scripts/kindle/ssh-force-dropbear-22.sh
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# 强制清理残留 SSH 进程,然后在 22 端口拉起一份 usbnet 自带的 DropBear。
|
||||||
|
# 这里使用 Kindle hack 里的 -n,让其不走密码检查,方便恢复公钥访问。
|
||||||
|
|
||||||
|
TS="$(date +%Y%m%d-%H%M%S 2>/dev/null || echo now)"
|
||||||
|
OUT_DIR="/mnt/us/ssh-debug/${TS}"
|
||||||
|
LOG_FILE="${OUT_DIR}/force-dropbear-22.log"
|
||||||
|
PID_FILE="/mnt/us/usbnet/run/dropbear-force-22.pid"
|
||||||
|
|
||||||
|
mkdir -p "${OUT_DIR}" /mnt/us/usbnet/run
|
||||||
|
exec >"${LOG_FILE}" 2>&1
|
||||||
|
|
||||||
|
echo "=== FORCE DROPBEAR 22 ==="
|
||||||
|
date 2>/dev/null || true
|
||||||
|
id 2>/dev/null || true
|
||||||
|
|
||||||
|
killall sshd 2>/dev/null || true
|
||||||
|
killall dropbear 2>/dev/null || true
|
||||||
|
killall dropbearmulti 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
rm -f "${PID_FILE}" 2>/dev/null || true
|
||||||
|
iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT 2>/dev/null || true
|
||||||
|
|
||||||
|
(
|
||||||
|
cd /mnt/us/usbnet
|
||||||
|
exec bin/dropbearmulti dropbear -F -E -p 22 -P "${PID_FILE}" -n
|
||||||
|
) &
|
||||||
|
|
||||||
|
LAUNCHER_PID="$!"
|
||||||
|
echo "${LAUNCHER_PID}" > "${OUT_DIR}/launcher.pid"
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
echo "launcher pid: ${LAUNCHER_PID}"
|
||||||
|
echo "pid file: ${PID_FILE}"
|
||||||
|
if [ -x /mnt/us/usbnet/bin/lsof ]; then
|
||||||
|
/mnt/us/usbnet/bin/lsof -n -P -iTCP:22 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== DONE ==="
|
||||||
|
echo "${OUT_DIR}"
|
||||||
63
scripts/kindle/ssh-force-openssh-22.sh
Normal file
63
scripts/kindle/ssh-force-openssh-22.sh
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# 强制清理残留 SSH 进程,然后在 22 端口拉起一份 usbnet 自带的 OpenSSH。
|
||||||
|
# 这份 sshd 会优先读取 /mnt/us/usbnet/etc/dot.ssh/authorized_keys。
|
||||||
|
|
||||||
|
TS="$(date +%Y%m%d-%H%M%S 2>/dev/null || echo now)"
|
||||||
|
OUT_DIR="/mnt/us/ssh-debug/${TS}"
|
||||||
|
LOG_FILE="${OUT_DIR}/force-openssh-22.log"
|
||||||
|
PID_FILE="/mnt/us/usbnet/run/sshd-force-22.pid"
|
||||||
|
SOURCE_KEYS="/mnt/us/usbnet/etc/authorized_keys"
|
||||||
|
TARGET_KEYS="/mnt/us/usbnet/etc/dot.ssh/authorized_keys"
|
||||||
|
|
||||||
|
mkdir -p "${OUT_DIR}" /mnt/us/usbnet/run /mnt/us/usbnet/etc/dot.ssh
|
||||||
|
exec >"${LOG_FILE}" 2>&1
|
||||||
|
|
||||||
|
echo "=== FORCE OPENSSH 22 ==="
|
||||||
|
date 2>/dev/null || true
|
||||||
|
id 2>/dev/null || true
|
||||||
|
|
||||||
|
if [ -f "${SOURCE_KEYS}" ]; then
|
||||||
|
cp "${SOURCE_KEYS}" "${TARGET_KEYS}"
|
||||||
|
chmod 600 "${TARGET_KEYS}" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
chmod 755 /mnt/us/usbnet/etc/dot.ssh 2>/dev/null || true
|
||||||
|
|
||||||
|
killall sshd 2>/dev/null || true
|
||||||
|
killall dropbear 2>/dev/null || true
|
||||||
|
killall dropbearmulti 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
rm -f "${PID_FILE}" 2>/dev/null || true
|
||||||
|
iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT 2>/dev/null || true
|
||||||
|
|
||||||
|
(
|
||||||
|
exec /mnt/us/usbnet/sbin/sshd -D -e \
|
||||||
|
-f /mnt/us/usbnet/etc/sshd_config \
|
||||||
|
-o ListenAddress=0.0.0.0 \
|
||||||
|
-o Port=22 \
|
||||||
|
-o PidFile="${PID_FILE}" \
|
||||||
|
-o AuthorizedKeysFile="${TARGET_KEYS}" \
|
||||||
|
-o PasswordAuthentication=no \
|
||||||
|
-o KbdInteractiveAuthentication=no \
|
||||||
|
-o PubkeyAuthentication=yes \
|
||||||
|
-o PermitRootLogin=yes \
|
||||||
|
-o HostKey=/mnt/us/usbnet/etc/ssh_host_rsa_key \
|
||||||
|
-o HostKey=/mnt/us/usbnet/etc/ssh_host_ecdsa_key \
|
||||||
|
-o HostKey=/mnt/us/usbnet/etc/ssh_host_ed25519_key
|
||||||
|
) &
|
||||||
|
|
||||||
|
LAUNCHER_PID="$!"
|
||||||
|
echo "${LAUNCHER_PID}" > "${OUT_DIR}/launcher.pid"
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
echo "launcher pid: ${LAUNCHER_PID}"
|
||||||
|
echo "pid file: ${PID_FILE}"
|
||||||
|
if [ -x /mnt/us/usbnet/bin/lsof ]; then
|
||||||
|
/mnt/us/usbnet/bin/lsof -n -P -iTCP:22 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== DONE ==="
|
||||||
|
echo "${OUT_DIR}"
|
||||||
28
scripts/kindle/ssh-stop-all.sh
Normal file
28
scripts/kindle/ssh-stop-all.sh
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# 停掉常见 SSH 进程,并清理掉常见 pid 文件。
|
||||||
|
|
||||||
|
TS="$(date +%Y%m%d-%H%M%S 2>/dev/null || echo now)"
|
||||||
|
OUT_DIR="/mnt/us/ssh-debug/${TS}"
|
||||||
|
LOG_FILE="${OUT_DIR}/stop-all.log"
|
||||||
|
|
||||||
|
mkdir -p "${OUT_DIR}"
|
||||||
|
exec >"${LOG_FILE}" 2>&1
|
||||||
|
|
||||||
|
echo "=== STOP ALL SSH DAEMONS ==="
|
||||||
|
date 2>/dev/null || true
|
||||||
|
id 2>/dev/null || true
|
||||||
|
|
||||||
|
killall sshd 2>/dev/null || true
|
||||||
|
killall dropbear 2>/dev/null || true
|
||||||
|
killall dropbearmulti 2>/dev/null || true
|
||||||
|
|
||||||
|
rm -f /mnt/us/usbnet/run/sshd.pid 2>/dev/null || true
|
||||||
|
rm -f /mnt/us/usbnet/run/sshd-force-22.pid 2>/dev/null || true
|
||||||
|
rm -f /mnt/us/usbnet/run/dropbear-2222.pid 2>/dev/null || true
|
||||||
|
rm -f /mnt/us/usbnet/run/dropbear-force-22.pid 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "=== DONE ==="
|
||||||
|
echo "${OUT_DIR}"
|
||||||
Reference in New Issue
Block a user