×

飞牛影视重复媒体与启动失败排查:一条 .curlrc 代理配置引发的连锁故障

Falcon 2026-09-09 views:
自动摘要

正在生成中……

飞牛影视媒体库中突然出现大量重复项目,同一视频在界面中显示两三次,但文件系统里只有一个源文件。随后,应用中心的影视应用也无法正常启用,一直停留在“启动中”,最终提示“本地应用启动失败”。最初看起来像媒体数据库损坏,实际根因却是一条全局 curl 代理配置。

问题背景

故障表现可以归纳为:

  • 影视媒体库出现大量重复项目,同一个视频文件在界面中显示两到三次;
  • 文件管理器中实际只有一个源文件,没有重复文件或硬链接;
  • 影视应用在应用中心显示“未启用”;
  • 点击“启用”后一直停留在“启动中”;
  • 最终提示“本地应用启动失败”;
  • 后台出现多个 trim-media 进程;
  • 强制终止后,进程有时又会被重新拉起。

一、确认重复的是索引,而不是文件

首先检查媒体源目录,确认同名视频在文件系统中只有一个实体,并不存在重复文件或硬链接。

进一步检查影视数据库后发现:

  • 相同文件路径对应多个不同的媒体 GUID;
  • CleanVideos 中有 19 个文件路径发生重复;
  • 共存在 38 条多余数据库记录;
  • 部分文件在界面中正好显示三次。

因此可以确定:重复媒体来自影视数据库索引,而不是磁盘上的源文件。这也意味着,直接删除源视频不仅不能解决问题,反而可能造成数据损失。

二、发现多个 trim-media 进程

检查影视进程和 8005 端口:

pgrep -a -x trim-media
ss -ltnp 'sport = :8005'

结果显示,系统中同时存在多个 trim-media 进程,但只有第一个进程成功监听 8005。

影视日志中出现了明确的端口冲突:

listen tcp :8005: bind: address already in use
listen udp 0.0.0.0:7359: bind: address already in use

问题在于,后续进程虽然无法绑定端口,却没有立即退出,仍然可能继续运行文件监听、扫描和数据库任务。

于是形成了这样的结果:

多个 trim-media 实例
→ 同时扫描同一个媒体目录
→ 分别向数据库写入媒体记录
→ 同一路径生成多个 GUID
→ 媒体库出现重复项目

三、是谁在重复启动 trim-media

通过进程父子关系,找到了完整启动链:

systemd
└─ /usr/trim/bin/trim_app_center
   └─ /var/apps/trim.media/cmd/main start
      └─ trim-media

真正发起启动的是飞牛应用中心服务:trim_app_center.service。影视并没有单独的 systemd 服务,而是由应用中心调用应用自带的控制脚本启动。

影视控制脚本位于:

/var/apps/trim.media/cmd/main
/var/apps/trim.media/cmd/common

控制脚本通过下面的请求判断影视是否启动成功:

curl -s --max-time 3 localhost:8005/v/api/v1/sys/pid

正常情况下,该接口应该返回当前 trim-media 的 PID。但实际现象是:

  • 影视已经成功监听 8005;
  • PID 接口检查却一直失败;
  • 控制脚本不断记录 trim.media is not running
  • 应用中心因此长期停留在“启动中”;
  • 自动重试或再次点击“启用”时,又会启动新的实例。

更麻烦的是,启动脚本没有单实例锁,状态检查也没有核对 PID 文件或现有进程。因此,只要 PID 接口检查失败,每次启动任务都可能创建一个新的 trim-media

四、PID 接口真的坏了吗

原本很自然会怀疑 localhost:8005/v/api/v1/sys/pid 接口可能出现了兼容性问题。但使用详细模式测试后发现,curl 并没有直接访问本机 8005,而是连接到了 Mihomo 的 SOCKS5 代理:

Trying <MIHOMO_IP>:7890...
SOCKS5 connect to localhost:8005

继续检查 root 用户的配置:

nl -ba /root/.curlrc

发现其中配置了全局代理:

-x socks5h://<MIHOMO_IP>:7890

这就是整个问题的关键。

为什么 socks5h 会影响 localhost

socks5h 中的 h 表示由代理端解析目标主机名。因此,当系统执行:

curl localhost:8005

请求流程实际上变成了:

飞牛主机
→ Mihomo SOCKS5 代理
→ 代理端解析 localhost
→ localhost 指向代理所在环境,而不是飞牛主机

影视的 8005 端口明明监听在飞牛主机上,但请求却被送到了代理端的 localhost,自然无法获得 PID。

应用中心运行在 root 身份下,因此它调用的 curl 会自动读取:

/root/.curlrc

这也解释了为什么手动访问影视正常,而应用中心始终判断启动失败。

五、最终解决方法

最终同时采用了两层修复。

1. 为本机地址设置代理例外

/root/.curlrc 中加入:

--noproxy localhost,127.0.0.1,::1

完整配置可以写成:

--connect-timeout 10
--noproxy localhost,127.0.0.1,::1
-x socks5h://<MIHOMO_IP>:7890

这样:

  • 外部网络请求仍然经过 Mihomo;
  • localhost127.0.0.1::1 始终直接连接本机;
  • 其他依赖 curl 的本地系统服务也不会被错误送入代理。

2. 让影视控制脚本忽略 .curlrc

影视控制脚本中有两处 PID 请求,分别用于状态检查和停止服务。

将原命令:

RESPONSE=$(curl -s --max-time 3 $URL)

改为:

RESPONSE=$(curl -q -s --max-time 3 "$URL")

这里的 -q 必须放在第一个参数位置,其作用是禁止 curl 加载默认配置文件。

两处都需要修改:

/var/apps/trim.media/cmd/common

对应功能分别是:

  • daemon_status:判断服务是否已经启动;
  • stop_daemon:停止服务前获取 PID。

其中,--noproxy 解决系统范围的本机直连问题,curl -q 则为影视启动脚本增加一层独立保护。

需要注意:影视应用升级后,官方安装包可能覆盖控制脚本,因此 .curlrc 中的 --noproxy 规则才是更加持久的基础修复。

六、修复后的验证

修改完成后,分别测试普通 curl 和忽略配置文件的 curl:

curl -sv --max-time 3 \
  localhost:8005/v/api/v1/sys/pid

curl -q -sv --max-time 3 \
  localhost:8005/v/api/v1/sys/pid

两次请求均直接连接:

127.0.0.1:8005

接口返回:

HTTP/1.1 200 OK

并正确输出当前 PID。

最后检查应用状态:

pgrep -a -x trim-media
ss -ltnp 'sport = :8005'
appcenter-cli status trim.media

验证结果:

  • 只有一个 trim-media 进程;
  • 8005 只有一个监听者;
  • 应用中心状态为 running
  • 飞牛影视可以正常打开;
  • 不需要卸载重装。

七、排查过程中得到的经验

不要看到重复媒体就直接删除文件

应先判断重复发生在文件系统还是媒体数据库。相同路径对应多个数据库记录,通常意味着扫描器或多个服务实例重复写入。

UI 状态不等于实际状态

应用中心显示“启动中”时,服务可能已经启动。应同时检查:

pgrep
ss

以及日志。

不要连续点击“启用”

如果第一次启动已经创建了后台进程,但健康检查失败,重复点击可能继续创建新实例。

谨慎使用 root 用户的全局代理配置

/root/.curlrc 不只影响手动执行的命令,也可能影响所有以 root 身份调用 curl 的系统服务和应用脚本。

全局配置代理时,至少应排除:

localhost,127.0.0.1,::1

本地健康检查应避免继承用户配置

系统服务中的本地健康检查,更稳妥的写法是:

curl -q -s --max-time 3 \
  http://127.0.0.1:8005/v/api/v1/sys/pid

更完善的启动脚本还应加入:

  • PID 文件核验;
  • 进程唯一性检查;
  • flock 单实例锁;
  • 端口占用检查;
  • 启动失败后终止残留进程。

总结

这次故障表面上表现为三个独立问题:

  • 飞牛影视媒体库重复;
  • 应用中心一直停留在“启动中”;
  • 后台存在多个 trim-media 进程。

实际上,它们来自同一条故障链:

/root/.curlrc 强制 localhost 走 socks5h
→ PID 健康检查访问了错误的 localhost
→ 应用中心误判影视没有启动
→ 重复拉起 trim-media
→ 多个实例同时扫描和写数据库
→ 媒体库产生重复记录

最终通过为本机地址设置 --noproxy,并让影视控制脚本使用 curl -q,恢复了正确的状态检测和单实例运行。问题解决后,影视可以正常启动,无需重新安装。

原文链接:https://d.cellmean.com/p/d9208c3049d4

FAQ

1. 为什么同一个视频在飞牛影视中重复显示两三次,但文件系统里只有一个文件?

这是数据库索引重复,而不是磁盘文件重复。影视后台出现了多个 trim-media 实例,同时扫描同一个媒体目录,分别向数据库写入媒体记录,导致同一文件路径对应多个不同媒体 GUID。直接删除源文件不能解决问题,反而可能造成数据损失。

2. 为什么影视应用一直显示“启动中”,最后提示“本地应用启动失败”?

影视实际可能已经启动并监听 8005 端口,但应用中心控制脚本的健康检查失败。原因是脚本执行的 curl localhost:8005/root/.curlrc 中的 socks5h:// 代理转发到代理端,请求没有到达飞牛本机的影视服务。应用中心误判影视没有启动,不断重新拉起新实例,进而导致端口冲突和后台多进程问题。

3. 为什么 .curlrc 里配置了 socks5h 代理,会导致 curl localhost 访问不到本机服务?

因为 socks5h 中的 h 表示目标主机名由代理服务器解析。请求 curl localhost:8005 时,代理会在代理所在环境中解析 localhost,最终指向代理端,而不是飞牛主机本身,因此无法访问飞牛影视的 8005 PID 接口。

4. 这次故障最终是如何修复的?

有两层修复:

  • /root/.curlrc 中加入 --noproxy localhost,127.0.0.1,::1,保证本机地址不走代理;
  • 修改 /var/apps/trim.media/cmd/common 中两处 PID 请求,把 curl 改为 curl -q,让影视控制脚本忽略 /root/.curlrc

5. 影视应用升级后,是否需要重新修改控制脚本?

有可能需要。影视应用升级后,官方安装包可能覆盖控制脚本,因此 curl -q 的修改可能丢失。更持久的基础修复是在 /root/.curlrc 中配置 --noproxy localhost,127.0.0.1,::1,让本机地址始终直连。

本文收录于