mirror of
https://gitcode.com/JianFeeeee/homeagent-sdk.git
synced 2026-09-30 06:13:14 +00:00
## 现象
线上关停必超时:systemd 报 `State 'stop-sigterm' timed out. Killing.`,
其中只有 bili 报 `[proc] bili SIGKILL 后 2s 仍未被收割`,之后近 90 秒无日志。
## 根因
本插件用 `exec.Command("yt-dlp", ...)` + `cmd.Run()`:
- 无 CommandContext ⇒ Stop 无法取消
- 无 Setpgid ⇒ yt-dlp 与本插件同进程组
- Stop() 是 `return nil` ⇒ 内核 Kill 插件本体时,yt-dlp 变孤儿
yt-dlp 还会再 fork ffmpeg,**孙进程继承本插件的 stdout 管道写端**。
插件被 SIGKILL 后孙进程仍持有写端 ⇒ 内核 readLoop 永远等不到 EOF
⇒ `Kill()` 末尾的 readerWG.Wait 永不返回 ⇒ 整个关停挂死。
## 改法
1. 两处 `exec.Command` → `exec.CommandContext`,Stop 里 cancel 能掐掉
2. `setPgid` 让命令自成进程组:yt-dlp 拉起的 ffmpeg 也在组内,
kill(-pgid) 能一次带走整棵子进程树,不留孤儿
3. `Stop()` 不再是空实现:cancel 之后**必须 wait**。
只 cancel 不 wait 的话内核会先释放共享段,而 yt-dlp 还在写 stdout ——
那正是内核 readLoop 挂死的成因。`runWG` 等它真正退出。
顺带:取消时返回明确文案("已取消(插件停止)")而不是含糊的 exec 错误。
内核侧的三处修法(Setpgid / 杀进程组 / readerWG 超时)在主仓 ceeef0b,
对所有 8 个同样 exec.Command 且无进程组隔离的插件都有效。
验证:hmapdev build 通过;主仓部署后实测关停 90s → 1s、
`[homed] stopped` 打出、孙进程无残留。
bili · B站视频下载
用 yt-dlp 把 B 站视频下载到本地。
前置依赖
需要系统里装有 yt-dlp:
pip install -U yt-dlp # 或 apt install yt-dlp
工具
| 工具 | 说明 |
|---|---|
bili_video |
下载 B 站视频;不指定 format 时先返回可用清晰度列表,指定后真正下载并返回文件路径 |
参数:
| 参数 | 说明 |
|---|---|
url |
视频地址 |
format |
格式 ID。常用:30112/30080=1080P、30064=720P、30032=480P、30016=360P。不指定则自动选最优 |
配置项
| 键 | 默认 | 说明 |
|---|---|---|
output_dir |
/tmp/bili_videos |
下载目录 |
proxy |
空 | yt-dlp 使用的 HTTP 代理(如 http://127.0.0.1:7890)。留空则不设代理 |
实现要点
output_dir有安全校验:它是配置项,但会拒绝被配成系统目录,避免 yt-dlp 往任意位置写文件。- 两阶段用法:先不传
format拿到清晰度清单(format_id+format_note),再带上选定的 ID 下载。这样模型不会盲选一个不存在的格式。 - B 站在部分网络环境下需要代理,见上面的
proxy。
构建
hmapdev build