一键导入
sub-store-diagnostic
Sub-Store 诊断 Skill。通过 ssh-tools 连接 NAS 上的 Sub-Store Docker 容器进行诊断:查看日志、检查节点、探测 geo、测试代理延迟。当需要诊断 Sub-Store 节点问题、分析订阅解析、分析代理连通性时调用此 Skill。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Sub-Store 诊断 Skill。通过 ssh-tools 连接 NAS 上的 Sub-Store Docker 容器进行诊断:查看日志、检查节点、探测 geo、测试代理延迟。当需要诊断 Sub-Store 节点问题、分析订阅解析、分析代理连通性时调用此 Skill。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
核心基础设施Skill:所有远程设备访问、SSH命令执行、文件上传下载的唯一标准入口。当用户要求"连接NAS"、"查看路由器/OpenWrt配置"、"在远程设备上执行命令"(如重启服务、查日志、部署容器)、或需要在不同设备间传输文件时,必须无条件优先调用此Skill。内含所有设备的IP和统一凭证。
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations. It can also be used to validate, package, and manage existing skills in the .claude/skills directory.
基于 SOC 职业分类
| name | sub-store-diagnostic |
| description | Sub-Store 诊断 Skill。通过 ssh-tools 连接 NAS 上的 Sub-Store Docker 容器进行诊断:查看日志、检查节点、探测 geo、测试代理延迟。当需要诊断 Sub-Store 节点问题、分析订阅解析、分析代理连通性时调用此 Skill。 |
| allowed-tools | ["Bash(.claude/skills/ssh-tools/scripts/exec.py nas *)"] |
通过 NAS 上的 Docker 容器诊断 Sub-Store。
# 快捷方式
python3 .claude/skills/ssh-tools/scripts/exec.py nas "<command>"
# 查看容器运行状态
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker ps -a --filter name=sub-store --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'"
# 实时资源占用
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker stats sub-store --no-stream --format 'cpu={{.CPUPerc}} mem={{.MemUsage}} net={{.NetIO}}'"
# 实时跟踪日志(最新 50 行)
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker logs --tail 50 sub-store 2>&1"
# 错误级别日志
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker logs --tail 100 --since 30m sub-store 2>&1 | grep -iE 'error|fail|warn'"
# 指定时间范围日志
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker logs --since '2026-04-30T10:00:00' sub-store 2>&1 | tail -100"
# 查看容器内 Sub-Store 数据目录
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker exec sub-store ls -la /app/data/"
# 查看订阅文件
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker exec sub-store find /app/data/subscriptions -type f | head -20"
# 查看解析后的代理节点数
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker exec sub-store find /app/data/proxies -type f | wc -l"
# 测试指定节点(替换 proxy json)
python3 .claude/skills/ssh-tools/scripts/exec.py nas 'docker exec sub-store sh -c "curl -X POST http://127.0.0.1:9876/start -H '\''Content-Type: application/json'\'' -d '\''{\"proxies\":[{\"type\":\"vmess\",\"server\":\"93.179.103.179\",\"port\":10038,\"uuid\":\"b4d3be5d-b4e2-4daf-8878-6ba9889b1461\",\"alterId\":0}],\"timeout\":15000}'\''"'
# 通过 META 代理请求目标站,检测 geo 出口
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker exec sub-store sh -c \"curl -s --proxy http://127.0.0.1:65534 'http://ip-api.com/json?lang=zh-CN' --max-time 8000\""
# 查看 META 进程日志
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker exec sub-store cat /tmp/http-meta.*.log 2>/dev/null | tail -30"
{"type":"vmess","server":"93.179.103.179","port":10038,"uuid":"b4d3be5d-b4e2-4daf-8878-6ba9889b1461","alterId":0}{"type":"ss","server":"67.209.184.142","port":10038,"cipher":"aes-256-gcm","password":"xWsZferpKq7DX9Nx"}# 在容器内测试 DNS 解析
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker exec sub-store nslookup sub.store 8.8.8.8"
# 测试到目标站点的 TCP 连通性
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker exec sub-store sh -c \"nc -zv host 443 -w 5 && echo OK || echo FAIL\""
# 上传测试脚本到容器
python3 .claude/skills/ssh-tools/scripts/copy.py nas /tmp/test.js /tmp/test.js
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker cp /tmp/test.js sub-store:/tmp/test.js"
# 从容器下载文件
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker cp sub-store:/app/data/export.json /tmp/sub_store_export.json"
2026-04-30 经验总结
# 查看 Sub-Store 日志(推荐)
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker logs --tail 100 sub-store 2>&1"
# 查看 parser.js 日志(带 [PARSER] 前缀)
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker logs --tail 100 sub-store 2>&1 | grep -E '\[PARSER\]'"
# 实时跟踪(中断用 Ctrl+C)
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker logs -f sub-store 2>&1 | grep -E '\[PARSER\]'"
https://cdn.jsdelivr.net/gh/rz467fzs7d/openwrt-network-stack@HEAD/sub-store/scripts/parser.js
当前 commit: e8e5cb9
# 列出所有用 parser.js 的 collection 及其参数
python3 .claude/skills/ssh-tools/scripts/exec.py nas 'echo "const fs=require(\"fs\");const d=JSON.parse(fs.readFileSync(\"/opt/app/data/sub-store.json\",\"utf8\"));const c=d.collections||[];c.forEach(x=>{(x.process||[]).forEach(p=>{if(p.type&&p.type.includes(\"Script\")&&p.args&&p.args.content&&p.args.content.includes(\"parser.js\")){console.log(\"=== collection:\",x.name);console.log(\"content:\",p.args.content);console.log(\"fragment:\",(p.args.content||\"\").split(\"#\")[1]||\"\");console.log(\"arguments:\",JSON.stringify(p.args.arguments));console.log();}});});" | docker exec -i sub-store node'
# 查找独立(非 riolu)用 parser.js 的 collection
python3 .claude/skills/ssh-tools/scripts/exec.py nas 'echo "const fs=require(\"fs\");const d=JSON.parse(fs.readFileSync(\"/opt/app/data/sub-store.json\",\"utf8\"));const c=d.collections||[];c.forEach(x=>{if(x.name&&!x.name.includes(\"riolu\")){(x.process||[]).forEach(p=>{if(p.type&&p.type.includes(\"Script\")&&p.args&&p.args.content&&p.args.content.includes(\"parser.js\")){console.log(\"=== collection:\",x.name);console.log(\"content:\",p.args.content);}});}});" | docker exec -i sub-store node'
Sub-Store 里 Script Operator 的配置结构:
{
"type": "Script Operator",
"args": {
"content": "parser.js#c=-&cache=false&f={region}{i:2d}",
"arguments": { "c": "-", "cache": "false", ... }
}
}
# 后面的参数)→ 传给脚本的 $arguments$arguments结论:cache=false 必须放在 URL fragment 里,放在 arguments JSON 里脚本读不到。
子订阅 502/超时 → collection 认为无节点 → 跳过 parser.js → 直接返回空
解决:把子订阅的"失败时作为 empty 处理"选项打开。
ignoreFailedRemoteSub: false → 任一子订阅失败,整体失败ignoreFailedRemoteSub: true → 子订阅失败不影响整体$arguments.cache(URL fragment)
↑
脚本参数: ipinfo_api_token(arguments JSON 或 URL fragment)
↑
环境变量: IPINFO_API_TOKEN(docker-compose.yml)
const useCache = ($arguments.cache === undefined) || ($arguments.cache === 'true');
const noCache = !useCache || !scriptCache;
// cache=false → noCache=true → 跳过缓存强制重新探测
// 不传 cache → noCache=false → 使用缓存
在 Sub-Store Collection 的 Script Operator URL 中:
parser.js#c=-&cache=false&f={region}{i:2d}&s=latency ASC&l=100
注意:URL 中
#只出现一次,cache=false在 fragment 中,不要被 URL 编码内容截断。
cd sub-store/scripts && node parser.test.js
# 28 cases, 0 failures
方式 1:环境变量(推荐,重启容器生效)
# docker-compose.yml
environment:
- IPINFO_API_TOKEN=your_token_here
方式 2:脚本参数(Sub-Store arguments JSON)
{ "ipinfo_api_token": "your_token_here" }
const api_token = $arguments.ipinfo_api_token
?? (typeof process !== 'undefined' ? process.env.IPINFO_API_TOKEN : null)
?? '';
| 字段 | ip-api.com | ipinfo.io |
|---|---|---|
| 国家码 | countryCode: "CN" | country_code: "CN" |
| ISP | isp: "China Mobile" | as_name: "China Mobile" |
parser.js 已内置映射:country_code → countryCode,as_name → isp
原因:子订阅全部失败,collection 直接返回空,跳过 parser.js
检查:
# 看是否有 502/超时错误
python3 .claude/skills/ssh-tools/scripts/exec.py nas "docker logs --tail 50 sub-store 2>&1 | grep -E '502|timeout|fail'"
解决:把子订阅的"失败时作为 empty"选项打开
检查步骤:
grep parser.js sub-store.json | grep fe80566#c=-&cache=false&...ip-api.com 免费版 45 req/min,容易触发限速。
解决:换 ipinfo.io(免费版 50k req/month),配置 IPINFO_API_TOKEN 环境变量。
riolu 订阅提供商的 API 不稳定,此时组合订阅无法工作。
临时方案:在 collection 中删除或禁用有问题的 riolu 子订阅。
1. 抓日志:docker logs --tail 100 sub-store | grep PARSER
2. 无 PARSER → 子订阅全失败 → 查 502/超时
3. 有 PARSER 但 cache=undefined → URL 未更新或 cache 参数位置错误
4. cache=false → noCache=true → 缓存跳过成功
5. 有真实探测结果 → 验证 ipinfo.io 响应格式