원클릭으로
wsl-dev-environment
WSL 开发环境配置 — NTFS venv 权限、Clash 代理访问、DeepSeek ReAct 模式、PaddlePaddle 安装、>60s 长任务的 Hermes sandbox 限制、GitHub release 大文件下载
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
WSL 开发环境配置 — NTFS venv 权限、Clash 代理访问、DeepSeek ReAct 模式、PaddlePaddle 安装、>60s 长任务的 Hermes sandbox 限制、GitHub release 大文件下载
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Set up Alembic database migrations for FastAPI projects using async SQLAlchemy (asyncpg). Covers env.py configuration with async engine, autogenerate handling, greenfield vs brownfield migration strategies, and env var integration.
使用 CloakBrowser 绕过抖音反爬,获取真实视频 MP4 下载链接
Wan2.2 FLF2V (First/Last Frame to Video) 管线 — 生成首尾帧之间的插值视频,支持电影级镜头过渡
Use CloakBrowser (anti-detection Chromium) to access protected Chinese web platforms (Douyin/抖音, etc.) and extract structured data — intercepting API responses, extracting video/media URLs, and downloading content from sites that block standard Playwright/browser automation.
Install and diagnose Playwright-based packages (Playwright, CloakBrowser, etc.) on Linux/WSL — handles externally-managed Python, system deps, proxy-based binary downloads, and runtime troubleshooting
Exploratory QA of web apps: find bugs, evidence, reports.
| name | wsl-dev-environment |
| description | WSL 开发环境配置 — NTFS venv 权限、Clash 代理访问、DeepSeek ReAct 模式、PaddlePaddle 安装、>60s 长任务的 Hermes sandbox 限制、GitHub release 大文件下载 |
| category | devops |
| tags | ["wsl","venv","proxy","deepseek","react-agent","long-running","github-release"] |
WSL (Windows Subsystem for Linux) 上的开发环境配置与常见陷阱。
fish: $? is not the exit statusterminal(background=true) 起来后秒退cp 大文件 / 多文件目录到 /mnt/c/ /mnt/e/ 等 Windows NTFS 挂载盘,写入静默失败(目标文件不存在 / size 截断 / cp 进程 exit 0 但目标没生成)bash: 无法设定终端进程组 (-1): 对设备不适当的 ioctl 操作 + 此 shell 中无任务控制 → 误以为是失败$? 必踩的坑远端用户登录 shell 是 fish 时,inline 单引号命令里写 $? 会被 fish 拦截:
fish: $? is not the exit status. In fish, please use $status.
原因:ssh 把整个 command 作为 argv 传给远端登录 shell,fish 看到 $? 字面量就直接报错。命令根本没跑。
绕过(任选一):
# 1. 强制远端用 bash 而不是登录 shell
ssh user@host bash -c '...your code with $?...'
# 2. heredoc 强制走 /bin/sh
ssh user@host /bin/sh <<'EOF'
...your code with $?...
EOF
判断:远端命令 exit 127 + stderr 含 fish: $? is not the exit status = 几乎一定是这个问题,不是命令本身语法错。
kill-server 验证Hermes TUI 本身就跑在 WSL tmux 里。配置改动后想"清干净再加载"时:
# ❌ 错 — 杀掉整个 tmux server,Hermes 进程跟着死
tmux kill-server
tmux new-session -d -s _v fish -l
tmux source-file ~/.tmux.conf
后果:本会话直接断,Hermes 状态丢失,下一次用户在另一个 shell 继续。
# ✅ 对 — 在当前 server 上起一个命名临时 session 验证,再 kill 那个 session
tmux new-session -d -s _vverify fish -l
tmux source-file ~/.tmux.conf
tmux display-message -p "prefix=[#{prefix}] mouse=[#{mouse}] shell=[#{default-shell}]"
tmux kill-session -t _vverify
或者用独立 socket 完全隔离:tmux -L _test new-session -d ... + tmux -L _test kill-server,这只杀那个 socket 下的 server,不动默认。
如果想检查 $? 又在 fish 环境:用 tmux display-message -p 把检查嵌进 tmux 内部,fish 看不到 $? 就不会爆。
在 /mnt/c/、/mnt/e/ 等 Windows 盘上使用 uv sync 或 pip install 时报错:
Operation not permitted (os error 1)
Windows NTFS 文件系统不支持 Linux 的文件权限模型,导致 .venv/ 内的文件复制操作失败。
将 venv 创建在 Linux 原生文件系统(ext4)上,然后软链接到项目目录:
# 1. 删除项目下的 .venv
rm -rf .venv
# 2. 在 Linux 侧创建 venv
uv venv --python 3.13 /home/po/.venvs/<project-name>
# 3. 建立软链接
ln -sf /home/po/.venvs/<project-name> .venv
# 4. 正常安装依赖
uv sync
注意:pyproject.toml 和项目代码仍可放在 NTFS 盘上,只有 .venv/ 需要移到 Linux 侧。
Clash for Windows 的 HTTP 代理默认监听 127.0.0.1:7890,WSL 可直接访问。
curl -s --connect-timeout 1 http://127.0.0.1:7890
# 返回 HTTP 400 = 代理正常运行(对裸请求的预期响应)
# 返回 000 / 无响应 = 代理未启动
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
常见 Clash for Windows 端口:HTTP 7890 | SOCKS5 7891
参见 references/deepseek-react-patterns.md。核心陷阱:
stop=["PAUSE"] — DeepSeek 不会自然停在 PAUSE,会一次生成完整多轮对话(含幻觉 Observation): 和 :uv add vs uv pip install在 NTFS 挂载盘上的项目,不要用 uv add(它会尝试重建 NTFS 上的 .venv)。用 uv pip install 直接装到 Linux venv:
uv pip install <package> --python /home/po/.venvs/<project-name>/bin/python
某些 ML 项目(如 CosyVoice2 依赖的 matcha-tts)需要 Python 3.10(因为用到了 Python 3.12 移除的 distutils)。
# uv python install 3.10 从 GitHub 下载,国内网络可能超时
# 替代方案:用 conda 管理 Python 版本
conda create -n <project> python=3.10
conda activate <project>
# conda 环境中可能需要补装 pip
python -m ensurepip --upgrade
注意:conda 创建的 Python 在某些 ML 包上可能有兼容问题(如 PyTorch CUDA 支持),需要额外配置。
uv python install 国内网络超时uv python install 从 astral-sh 的 GitHub releases 下载 Python,国内网络可能 120s 超时。
解决:走代理
https_proxy=http://127.0.0.1:7890 uv python install 3.10
或跳过 uv 的 Python 管理,直接用 conda 或系统 Python。\n\n### Python 3.14 兼容问题
系统 Python 3.14 可能缺少某些包的 wheel(如 openai-whisper 缺少 pkg_resources)。用 uv 安装旧版 Python:
uv python install 3.12
uv venv --python 3.12 /home/po/.venvs/<name>
WSL 中启动的 Vite dev server 在 Windows 浏览器可能无法访问。
--hostnpx vite --host 0.0.0.0
# 不加 --host 时 Vite 只监听 localhost,Windows 端可能无法转发
不加 --host 时 ss -tlnp | grep 5173 显示端口未监听(虽然 Vite 打印了 ready 消息)。
| 优先级 | 地址 | 适用场景 |
|---|---|---|
| 1 | http://localhost:5173/ | WSL2 localhost 转发正常时 |
| 2 | http://<WSL_IP>:5173/ | localhost 转发失败时(用 ip addr show eth0 获取 IP) |
terminal(background=true) 启动 npx vite 可能静默退出(exit code 0,output 只有 bash ioctl 警告)。替代方案:在用户自己的 WSL 终端中手动运行 npx vite --host 0.0.0.0。
后台进程在 WSL 中静默退出是常见问题。排查流程:
python3 server.py 2>&1terminal(background=true)ss -tlnp | grep <port>症状:terminal(background=true) 起的进程在 60-90 秒后无任何报错地消失(exit_code=0,但 log 不更新,PID 查不到)。实测:SPC 8.1.2 生成整合包 5 分钟全过程跑得通,但 terminal(background=true, timeout=1500) 起来的实例 uptime 只有 69s 就被砍。
根因:Hermes TUI 给后台进程附加了 sandbox 监管(看 stderr 的 bash: 无法设定终端进程组 (-1): 对设备不适当的 ioctl 操作 + 此 shell 中无任务控制 这两行警告),超时后 SIGTERM。
⚠️ 关于那两行 ioctl 警告的"误报":Hermes 后台进程完成通知里也总是带这两行(
bash: 无法设定终端进程组 (-1)+此 shell 中无任务控制),即使命令真的成功跑完了。看到这两行不等于失败——判断成功与否要看 exit_code 和实际产出物(文件、port、log)。这条不是新坑,是 Hermes 的固定行为。
结论:
process action=poll 看进度timeout 580 java -jar ... 实测可用,600s 是 Hermes fg 命令上限delegate_task(会自动后台),或 cronjob(deliver='local' 不会发回 TUI,但任务真跑完)反模式:
# ❌ 看似后台、实际被砍
terminal(background=true, timeout=1800) java -jar foo.jar > log 2>&1
# uptime 69s 后 PID 不在了,log mtime 卡在 60s 处
正确做法:
# ✅ 前台跑 + 留余量
timeout 580 java -jar foo.jar > log 2>&1
# 或直接放后台用 nohup + setsid 完全脱钩(绕过 Hermes)
ModelScope(modelscope.cn)下载模型不需代理,且比 HuggingFace 更稳定(国内 CDN)。
在 WSL 国内网络环境下,HuggingFace 下载常失败。逐级尝试:
方案 1: hf-mirror Git Clone + LFS
git clone https://hf-mirror.com/<org>/<repo> checkpoints
cd checkpoints && git lfs pull
注意:GIT_LFS_SKIP_SMUDGE=1 会跳过 LFS 文件(只下载指针),网络不好时反而不行。
方案 2: Modelscope Git Clone + LFS
git clone https://www.modelscope.cn/<org>/<repo>.git checkpoints
cd checkpoints && git lfs pull
用 modelscope 的 git 服务,国内 CDN 更稳定。
方案 3: HuggingFace CLI 直下
export HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download <org>/<repo> --local-dir checkpoints
但 hf-mirror 经常超时导致静默失败(exit 0 但只下了一个小文件)。验证:du -sh checkpoints/ 应该在 GB 级。
方案 4: Modelscope Python SDK
from modelscope import snapshot_download
snapshot_download('<org>/<repo>', local_dir='checkpoints')
LFS 文件下载后在 .git/lfs/incomplete/ 中说明下载中断。删除 incomplete 目录重试:
rm -rf .git/lfs/incomplete && git lfs pull
成功的 LFS 文件应在 .git/lfs/objects/ 中,且根目录出现实际大文件(而非指针)。
uv sync exit code 0,但 .venv/lib/python3.12/site-packages/ 只有 _virtualenv.pth,没有任何实际包。
uv sync 在锁文件已存在时可能跳过实际安装(尤其在 NTFS 盘或网络不稳时)uv lock 在大型项目(如 PyTorch + CUDA 包依赖)上耗时极长(300s+ 超时)# 1. 创建 venv(不用 uv sync)
uv venv --python 3.12
# 2. 安装 pip
uv pip install --python .venv/bin/python pip
# 3. 用 pip 直装 PyTorch(CUDA 版)
.venv/bin/python -m pip install \
-i https://download.pytorch.org/whl/cu128 \
torch torchaudio \
--extra-index-url https://pypi.tuna.tsinghua.edu.cn/simple
# 4. 装其他依赖
.venv/bin/python -m pip install \
-i https://pypi.tuna.tsinghua.edu.cn/simple \
transformers fastapi soundfile ...
PyTorch 的 torchaudio .so 文件链接到 libcudart.so.12,但 pip 安装的 nvidia-cuda-runtime 可能提供 libcudart.so.13(CUDA 13.x 驱动)。
解决:设置 LD_LIBRARY_PATH 包含所有 nvidia pip 包的 lib 目录:
NVIDIA_LIB=$(find ~/.local/share/uv/python/cpython-3.12.*/lib/python3.12/site-packages/nvidia -name "lib" -type d | tr '\n' ':')
export LD_LIBRARY_PATH="${NVIDIA_LIB}/usr/lib/wsl/lib"
在 ML 项目中 pip 安装大包(如 nvidia-cudnn 366MB)时可能报 No space left on device。WSL 的 /tmp 通常是 tmpfs(7.8G),容易满。
解决:
mkdir -p ~/tmp
export TMPDIR=~/tmp
或者清理 modelscope 缓存:rm -rf /tmp/ms_cache
set -x 环境变量不生效Fish 的 set -x VAR val; cmd 在某些场景(如 uv tool upgrade)环境变量不会被命令继承。
用 env 前缀替代:
# ❌ 不生效
set -x UV_HTTP_TIMEOUT 300; uv tool upgrade astrbot
# ✅ 生效
env UV_HTTP_TIMEOUT=300 uv tool upgrade astrbot
[pip]
index-url = "https://pypi.tuna.tsinghua.edu.cn/simple"
创建于项目根目录即可。与 pyproject.toml 中的 [tool.uv] 冲突时 uv.toml 优先。
uv tool 命令走镜像(不依赖 uv.toml)uv tool upgrade/install 不受项目 uv.toml 控制。大包超时时直接设 UV_INDEX_URL:
env UV_HTTP_TIMEOUT=300 UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple uv tool upgrade astrbot --python 3.12
Hermes Agent 设置了全局 PYTHONPATH=/home/po/.hermes/hermes-agent,导致所有 Python 的 sys.path 都被注入该路径。在 WSL 中运行其他 Python 项目(尤其是 ML 项目)时,这会引发包版本冲突。
解决:启动其他 Python 应用时 unset:
PYTHONPATH= python3 server.py
# 或
unset PYTHONPATH
uv pip install 默认在项目目录找 .venv。如果 venv 在其他位置:
uv pip install --python /path/to/venv/bin/python <package>
Hermes 终端工具会检测命令中是否包含 uvicorn 并误判为长时服务器进程,拒绝执行。pip install uvicorn 或 pip show uvicorn 都会被拦截。
绕过:用 execute_code 工具调用 subprocess.run:
from hermes_tools import terminal
import subprocess
subprocess.run([venv_python, "-m", "pip", "install", "-i", mirror, "uvicorn"], ...)
或者用文件间接传递包名:echo 'uvicorn' > /tmp/pkg.txt && pip install -r /tmp/pkg.txt
uvicorn.run("server:app") 会导致模型加载两次:
__main__ 运行 server.pyserver 模块(不同 __name__)IndexTTS2() 实例 → VRAM ×2 → OOM正确写法:
if __name__ == "__main__":
# 加载模型
model = load_model()
# 传入 app 对象,不是 "module:app" 字符串
uvicorn.run(app, host="0.0.0.0", port=8800)
另外 uvicorn lifespan 有 5 秒默认超时,模型加载(~35s)不能放在 lifespan startup 中。
Windows 终端里想直接敲 hermes / claude / codex 调 WSL 里的 CLI(典型场景:WSL 配好了全套 env 和 venv,但人在 PowerShell 里),wsl <cmd> 这种直觉写法一连踩三个坑:
wsl <cmd> 找不到命令 — wsl 默认 PATH 不带 ~/.local/binwsl -e bash -lc "hermes" 启动的 shell 只继承 WSL 默认用户的 PATH(/usr/bin 等),不读 .bashrc 里的 export PATH 也不读 ~/.local/bin/env。hermes / claude / codex 全装在 ~/.local/bin/,直接报 未找到命令。
绕过:直接走绝对路径,不依赖 PATH 解析:
# ❌ 错
wsl hermes
wsl -e bash -lc "hermes"
# ✅ 对 — 直接调 venv 里的 entry point
wsl -e bash -lc "/home/po/.hermes/hermes-agent/venv/bin/hermes"
wsl -e bash -lc "~/..." 中 ~ 解析成 /root — wsl 默认登录用户是 rootwsl -e 不带 -u 时用 /etc/wsl.conf 的 default 用户(默认 root)。~ 在 bash -lc 字符串里被 root 用户解析成 /root,不是 /home/po,于是报 /root/.local/bin/hermes: 没有那个文件或目录。
绕过:绝对路径写死,或用 -u po 切用户(但切用户会丢 root 那边的 env,见坑 3)。
-u po 后丢失 API key / proxy / 各种 envhermes / claude 这类工具要读一堆 env(DEEPSEEK_API_KEY、BAILIAN_API_KEY、HTTPS_PROXY、NAPCAT_TOKEN、PYTHONPATH…)。WSL 默认 root 登录 shell 里这些 env 是齐的(写在 /etc/profile.d/ 或 root 的 .bashrc)。切到 -u po 后 po 的 shell 没这些 export,工具启动报"no API keys or providers found"。
最干净的解法:保持默认用户 root + 绝对路径调 po 的 venv,root 的 env 全在,po 的库全在:
# PowerShell $PROFILE 里加:
function hermes { wsl -e bash -lc "/home/po/.hermes/hermes-agent/venv/bin/hermes $($args -join ' ')" }
变体:
/home/po/.local/bin/claude(如果装在 ~/.local/bin 而非 venv)/home/po/.npm-global/bin/codex验证链路是否通:
wsl -e bash -lc '/home/po/.hermes/hermes-agent/venv/bin/hermes --version'
# 应输出 Hermes Agent v... 不报 file not found
不输出 version = 路径错了;version 出来了但还是 "no providers" = 坑 3,切用户了。
wsl -e bash -lc "..." 先进 fish 后才执行 hermes — -l + TTY 让 bash 卡在登录 shell 交互模式症状:用户报"PowerShell 函数执行时先进入 WSL 的 fish / 显示 welcome banner,等我退出后再进 hermes"。
原因:wsl -e bash -lc "cmd" 中 -l 让 bash 作为登录 shell 启动。bash 登录 shell 看到 stdin/stdout 是 TTY(PowerShell 传过来的就是)→ 进交互模式 → 先读 .bash_profile / .profile、打印 PS1 等用户输入 → 然后才把 -c 字符串作为命令执行。用户的默认登录 shell 是 fish 时,会先看到 fish 的 welcome / 主题渲染,命令才执行。
官方文档依据(Microsoft WSL docs):
"The Linux command following
wslis handled like any command run in WSL. Run as the WSL default user."wsl -e跳过默认 Linux shell,但仍会按你指定的 shell(bash)启动;如果加了-l它就走 login shell 路径。
修复:去掉 -l,用 bash -c 直接执行命令字符串:
# ❌ 错 — 触发登录 shell 交互模式
function hermes { wsl -e bash -lc "/home/po/.../hermes $($args -join ' ')" }
# ✅ 对 — bash -c 不读 .bash_profile,不进交互模式
function hermes { wsl -e bash -c "/home/po/.../hermes $($args -join ' ')" }
更优雅:直接走 wsl 默认 shell,把 HOME 用 env 前缀传给 hermes:
# 最简版:让 wsl 默认 shell(root 的 fish / bash)直接 exec hermes
function hermes { wsl HOME=/home/po /home/po/.hermes/hermes-agent/venv/bin/hermes $args }
HOME=val command 是 POSIX / fish / zsh / dash 通用语法,shell 看到就直接 exec hermes,不启新 shell。
副作用:bash -c(去掉 -l)不读 .bash_profile / .profile,所以 root 登录 shell 里 export 的 env(API key / proxy)会丢。如果 hermes 报"no API keys",需要显式透传:
# 把 PowerShell 的关键 env 透传给 WSL root
function hermes {
$envArgs = @()
foreach ($name in 'HTTPS_PROXY','HTTP_PROXY','BAILIAN_API_KEY','DEEPSEEK_API_KEY','NAPCAT_TOKEN') {
if ($env:$name) { $envArgs += '--env', "$name=$($env:$name)" }
}
& wsl.exe @envArgs -e bash -c "HOME=/home/po /home/po/.hermes/hermes-agent/venv/bin/hermes $($args -join ' ')"
}
但 hermes 默认优先读 ~/.hermes/config.yaml 里写死的 key,不一定依赖瞬时 env。先试最简版,报"未配置"再加 env 透传。
官方 env 共享机制(更系统化):PowerShell 那边设置 WSLENV 变量列表,决定哪些 Windows env 自动透传到 WSL:
$env:WSLENV = "HTTPS_PROXY/u:HTTP_PROXY/u:BAILIAN_API_KEY/u:DEEPSEEK_API_KEY/u:NAPCAT_TOKEN/u"
/u 标志表示"只在从 Win32 调用 WSL 时透传"。设一次,所有 wsl 命令都生效。
把 hermes 需要的 PATH 补进 /etc/profile.d/,所有用户登录都有:
sudo tee /etc/profile.d/hermes-env.sh <<'EOF'
export PATH="$HOME/.local/bin:$PATH"
# 其他需要持久化的 env 在这里 export
EOF
要 sudo,你自己粘贴进 WSL 跑。
references/deepseek-react-patterns.md — DeepSeek ReAct Agent 在 WSL 下的具体坑references/deepseek-api-patterns.md — DeepSeek API 的 ReAct/Function Calling 坑和写法(从 wsl-python-development 合并)references/mcp-fastmcp-api.md — MCP FastMCP 三种传输协议的现行 API(从 wsl-python-development 合并)references/paddlepaddle-setup.md — 百度飞桨在 WSL 上的安装、GPU 配置、3.3.0 API 已知坑references/indextts-deploy.md — Index-TTS 在 WSL 上的完整部署实录(依赖安装、模型下载、AstrBot 插件)references/powershell-wsl-launch.md — PowerShell 一行启动 WSL 里安装的 CLI(hermes / claude / codex 等)的 4 个连环坑(含 bash -lc 登录 shell 卡 PS1 / fish welcome)references/wsl-to-windows-file-copy.md — WSL → Windows NTFS 大文件传输的 cp 静默截断 + PowerShell SMB 路径(\\wsl.localhost\<distro>\...)解法references/github-release-download.md — GitHub release 资产下载的 JWT 签名陷阱(续传无效 / WSL 长连接慢)和 gh CLI + 浏览器替代方案templates/hello_paddle_mnist.py — 飞桨 3.3.0 兼容的 MNIST 训练模板