# dsh-termux-fix **Repository Path**: goodboy-admin/dsh-termux-fix ## Basic Information - **Project Name**: dsh-termux-fix - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-06 - **Last Updated**: 2026-09-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # dsh-termux-fix 让 [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness)(dsh)在 **Termux / Android** 上正常保存会话历史。 ## 问题 dsh 在 Termux 中每轮运行结束报错,会话历史无法落盘: ``` EACCES: permission denied, link '.../session.v2.jsonl.zstd..tmp' -> '.../session.v2.jsonl.zstd' ``` 根因:Android 6.0 起 SELinux 策略禁止普通应用调用 `link()`(硬链接)系统调用 (见 [termux/termux-app#837](https://github.com/termux/termux-app/issues/837))。 dsh 的会话持久化层(`@deepseek-ai/dsh-session-persistence-jsonl`)用 `link()+unlink()` 原子发布日志文件,因此被拒。 本仓库提供两种修复: | 方式 | 文件 | 适用 | |---|---|---| | 运行时热修 | `hotfix/dsh-android-link-hotfix.cjs` | 普通用户,立即生效,无需改 dsh | | 源码补丁 | `patch/android-link-fallback.patch` | 想自行构建/提上游 PR 的人 | ## 快速使用(Termux) ```sh # 方式一:克隆后一键安装(自动装到 ~/.dsh 并配置 dshh 别名) git clone https://gitee.com/goodboy-admin/dsh-termux-fix.git cd dsh-termux-fix sh install.sh # 之后用 dshh 代替 dsh: dshh --profile demo ``` ```sh # 方式二:不克隆,直接拉取单个文件(raw 链接) curl -fsSL -o ~/.dsh/dsh-android-link-hotfix.cjs \ https://gitee.com/goodboy-admin/dsh-termux-fix/raw/master/hotfix/dsh-android-link-hotfix.cjs # 手动带环境变量启动(可写入 ~/.bashrc 作别名) NODE_OPTIONS="--require=$HOME/.dsh/dsh-android-link-hotfix.cjs" dsh --profile demo ``` ## 热修原理 Node 的 ESM 具名导入(`import { link } from 'node:fs/promises'`)会跟随 `--require` 预载脚本的运行时包装。热修脚本包装 `fs.promises.link`: - 真实 `link()` 成功 → 原语义不变(普通 Linux 桌面/服务器零影响) - `link()` 被拒且 errno 为 `EACCES`/`EPERM` → 确认目标不存在(存在则抛 `EEXIST`,保留防覆盖语义)后用 `rename()` 发布——正是 dsh 「临时文件 → 发布」模式期望的行为 - 其他错误(含 `EEXIST` 碰撞)→ 原样抛出 环境变量: - `DSH_LINK_HOTFIX_VERBOSE=1`:启动时打印包装确认 - `DSH_LINK_FORCE_RENAME=1`:强制走回退路径(非 Android 环境验证用) ## 源码补丁(面向上游) `patch/android-link-fallback.patch` 基于 `dsh-v0.1.3-alpha.1` 标签,修改 `packages/session/session-persistence-jsonl` 的两个 `link()` 调用点: ```sh git clone https://github.com/deepseek-ai/deepseek-harness.git cd deepseek-harness git checkout dsh-v0.1.3-alpha.1 git apply /path/to/android-link-fallback.patch # 跑该包测试后按正常流程构建 ``` `docs/upstream-issue-draft.md` 是可直接提交给 deepseek-harness 的英文 issue 草稿(含根因分析与修复建议)。 ## 已验证 - 热修:7 项断言通过(正常硬链接不受影响 / ESM 拦截生效 / rename 回退 正确 / 碰撞抛 EEXIST 不覆盖) - 补丁:`git apply --check` 干净应用 ## 许可 随上游(Apache-2.0 与 deepseek-harness 保持一致)。