mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-09 21:47:59 +08:00
🍕 Sync 2026-10-01 13:33:56
This commit is contained in:
1 parent
9057fa94b1
commit
1f3a4e8fb4
24 files changed
+731
-83
No files matched your search
@@ -8,6 +8,11 @@ local M = {}
|
||||
|
||||
M.TIMEOUT = 2 -- 每个目标的超时(秒)
|
||||
|
||||
-- 批量探测时同时存在的子进程上限。
|
||||
-- 每个探测占 1 个进程 + 1 个管道 fd,节点数由订阅内容决定(可上千),
|
||||
-- 不限并发会把路由器的 fd/进程额度打满,之后 io.popen 静默失败。
|
||||
M.MAX_PARALLEL = 16
|
||||
|
||||
-- shell 引号:用单引号转义(util.shq),配合 safe_host 校验,双重防命令注入。
|
||||
-- 不能用 string.format("%q"):它生成双引号字符串,sh 在双引号内仍会做 $() / ``
|
||||
-- 命令替换,实测可注入。
|
||||
@@ -145,26 +150,39 @@ end
|
||||
-- 返回结果数组 { name=, server=, port=, latency=number|nil }
|
||||
function M.probe(nodes, mode)
|
||||
local jobs = {}
|
||||
-- 分批:一批最多 MAX_PARALLEL 个进程,读完并关闭这一批再起下一批。
|
||||
--
|
||||
-- 原来是「先把全部节点的 io.popen 起完,再统一读取」。并行度确实最高
|
||||
-- (总耗时≈单节点超时),但代价是无界的:每个节点占 1 个进程 + 1 个管道 fd,
|
||||
-- 而节点数由订阅内容决定(上千个很常见)。路由器上 fd 与进程数都是硬上限,
|
||||
-- 打满之后 io.popen 直接失败 —— 表现是一大片节点探测不出来,
|
||||
-- 而不是报错。分批后并发度封顶,总耗时仍是「批数 × 单节点超时」。
|
||||
local out = {}
|
||||
local batch = {}
|
||||
local function drain()
|
||||
for _, j in ipairs(batch) do
|
||||
local latency
|
||||
if j.f then
|
||||
local raw = j.f:read("*a") or ""
|
||||
j.f:close()
|
||||
latency = j.parse and j.parse(raw) or nil
|
||||
end
|
||||
out[#out + 1] = {
|
||||
name = j.name, server = j.server, port = j.port, latency = latency,
|
||||
}
|
||||
end
|
||||
batch = {}
|
||||
end
|
||||
for _, n in ipairs(nodes or {}) do
|
||||
local cmd, parse = build_job(mode, n.server, n.port)
|
||||
local f = cmd and io.popen(cmd) or nil
|
||||
jobs[#jobs + 1] = {
|
||||
batch[#batch + 1] = {
|
||||
f = f, parse = parse,
|
||||
name = n.name or "", server = n.server or "", port = n.port or "",
|
||||
}
|
||||
if #batch >= M.MAX_PARALLEL then drain() end
|
||||
end
|
||||
local out = {}
|
||||
for _, j in ipairs(jobs) do
|
||||
local latency
|
||||
if j.f then
|
||||
local raw = j.f:read("*a") or ""
|
||||
j.f:close()
|
||||
latency = j.parse and j.parse(raw) or nil
|
||||
end
|
||||
out[#out + 1] = {
|
||||
name = j.name, server = j.server, port = j.port, latency = latency,
|
||||
}
|
||||
end
|
||||
drain()
|
||||
return out
|
||||
end
|
||||
|
||||
|
||||
Reference in new issue
Block a user