From caa31c713a26e458e6258594be164ebcd599a4a4 Mon Sep 17 00:00:00 2001 From: kiddin9 <48883331+kiddin9@users.noreply.github.com> Date: Mon, 5 Oct 2026 06:00:54 +0800 Subject: [PATCH] Delete .github/diy/packages/luci-mod-status/root/usr/lib/lua/luci/controller/netstat.lua --- .../usr/lib/lua/luci/controller/netstat.lua | 249 ------------------ 1 file changed, 249 deletions(-) delete mode 100644 .github/diy/packages/luci-mod-status/root/usr/lib/lua/luci/controller/netstat.lua diff --git a/.github/diy/packages/luci-mod-status/root/usr/lib/lua/luci/controller/netstat.lua b/.github/diy/packages/luci-mod-status/root/usr/lib/lua/luci/controller/netstat.lua deleted file mode 100644 index 6f87315d8..000000000 --- a/.github/diy/packages/luci-mod-status/root/usr/lib/lua/luci/controller/netstat.lua +++ /dev/null @@ -1,249 +0,0 @@ -module("luci.controller.netstat", package.seeall) -local nixio = require("nixio") -local uci = require("luci.model.uci").cursor() - -function index() - entry({"admin", "tools"}, firstchild(), _("Tools"), 50).dependent = false - entry({"admin", "tools", "netstat"}, cbi("netstat/config"), _("Netstat"), 20).leaf = true - entry({"admin", "tools", "netstat_config"}, alias("admin", "tools", "netstat")).dependent = true - entry({"admin", "tools", "get_netdev_stats"}, call("getNetdevStats"), nil).sysauth = false -end - --- Reads /proc/net/dev and returns per-interface rx/tx byte counters. -function getNetdevStats() - local f = io.open("/proc/net/dev", "r") - if not f then - luci.http.prepare_content("application/json") - luci.http.write('{"stats":{},"ip":"N/A","status":"Disconnected"}') - return - end - local content = f:read("*a") - f:close() - - local stats = {} - for line in content:gmatch("[^\n]+") do - local iface, values = line:match("^%s*([^:]+):%s+(.*)$") - if iface and values then - local nums = {} - for num in values:gmatch("%d+") do - table.insert(nums, tonumber(num)) - end - if #nums >= 9 then - stats[iface] = { rx = nums[1], tx = nums[9] } - end - end - end - - -- Quick connectivity check - local status = "Disconnected" - for iface, data in pairs(stats) do - if iface ~= "lo" and (data.rx > 0 or data.tx > 0) then - status = "Connected" - break - end - end - - -- ── IP detection ───────────────────────────────────────────────────────── - -- Strategy: try a single fast HTTP call first (2 s timeout), then fall - -- back to local ubus/ifstatus which is instant. The old code tried 11 - -- commands with 4 s timeouts each – worst-case 44 s of blocking. - - local function read_cmd(cmd) - local p = io.popen(cmd) - if not p then return nil end - local line = p:read("*l") - p:close() - if not line then return nil end - line = line:gsub("^%s+",""):gsub("%s+$","") - return line ~= "" and line or nil - end - - -- ── Preferred interface resolution ────────────────────────────────────── - -- The "Preferred Interface" setting may hold either a real netdev name - -- (e.g. "eth2", "wwan0_1") or a logical/config interface name (e.g. - -- "modem", "wan") that has no matching key in /proc/net/dev. In the - -- latter case resolve it to its actual l3_device via ubus so traffic - -- stats can be found. - local prefer_iface = "" - do - local prefer = uci:get_first("netstats", "config", "prefer") or "" - -- Only allow safe characters before using it in a shell command. - if prefer ~= "" and prefer:match("^[%w%-%._]+$") then - if stats[prefer] then - prefer_iface = prefer - else - local l3 = read_cmd( - "ubus call network.interface." .. prefer .. - " status 2>/dev/null | jsonfilter -e '@.l3_device'" - ) - if l3 and stats[l3] then - prefer_iface = l3 - end - end - end - -- Nothing configured (or unresolvable): use the default-route device - -- so idle interfaces named "wan"/"eth1" don't win over the real uplink. - if prefer_iface == "" then - local dev = read_cmd("ip route show default 2>/dev/null | awk '{for(i=1;i/dev/null", - "curl -fsS --max-time 1 'http://api.ipify.org' 2>/dev/null", - "uclient-fetch -qO- --timeout=1 'https://api.ipify.org' 2>/dev/null", - } - for _, cmd in ipairs(public_cmds) do - local v = read_cmd(cmd) - if is_valid_ip(v) then ip = v; break end - end - end - - -- 2. Fall back to local WAN address (instant, no network needed) - if ip == "N/A" then - local local_cmds = { - -- wan IPv4 - "ubus call network.interface.wan status 2>/dev/null | jsonfilter -e '@[\"ipv4-address\"][0].address'", - "ifstatus wan 2>/dev/null | jsonfilter -e '@[\"ipv4-address\"][0].address'", - -- wan IPv6 - "ubus call network.interface.wan status 2>/dev/null | jsonfilter -e '@[\"ipv6-address\"][0].address'", - "ubus call network.interface.wan6 status 2>/dev/null | jsonfilter -e '@[\"ipv6-address\"][0].address'", - } - for _, cmd in ipairs(local_cmds) do - local v = read_cmd(cmd) - if is_valid_ip(v) then ip = v; break end - end - end - - -- ── System uptime ───────────────────────────────────────────────────────── - local uptime_sec = 0 - local uf = io.open("/proc/uptime", "r") - if uf then - local line = uf:read("*l") - uf:close() - if line then - uptime_sec = math.floor(tonumber(line:match("^([%d%.]+)")) or 0) - end - end - - -- ── CPU usage (two reads 200 ms apart for accurate delta) ──────────────── - local cpu_pct = 0 - local function read_cpu_stat() - local f = io.open("/proc/stat", "r") - if not f then return nil end - local line = f:read("*l"); f:close() - local vals = {} - for n in line:gmatch("%d+") do vals[#vals+1] = tonumber(n) end - if #vals < 4 then return nil end - local idle, total = vals[4], 0 - for _, v in ipairs(vals) do total = total + v end - return { idle = idle, total = total } - end - local s1 = read_cpu_stat() - if s1 then - nixio.nanosleep(0, 200000000) - local s2 = read_cpu_stat() - if s2 then - local d_total = s2.total - s1.total - local d_idle = s2.idle - s1.idle - if d_total > 0 then - cpu_pct = math.floor((d_total - d_idle) / d_total * 100 + 0.5) - end - end - end - - -- ── Memory usage ────────────────────────────────────────────────────────── - local mem_total, mem_available, mem_free = 0, 0, 0 - local mf = io.open("/proc/meminfo", "r") - if mf then - for line in mf:lines() do - local k, v = line:match("^(%S+):%s+(%d+)") - if k == "MemTotal" then mem_total = tonumber(v) or 0 end - if k == "MemAvailable" then mem_available = tonumber(v) or 0 end - if k == "MemFree" then mem_free = tonumber(v) or 0 end - end - mf:close() - end - -- MemAvailable is present on Linux 3.14+; fall back to MemFree on older kernels - if mem_available == 0 and mem_free > 0 then mem_available = mem_free end - local mem_pct = 0 - if mem_total > 0 then - mem_pct = math.floor((mem_total - mem_available) / mem_total * 100 + 0.5) - end - -- used MB and total MB for display - local mem_used_mb = math.floor((mem_total - mem_available) / 1024 + 0.5) - local mem_total_mb = math.floor(mem_total / 1024 + 0.5) - - -- ── Disk space (root filesystem) ────────────────────────────────────────── - local disk_pct, disk_used_mb, disk_total_mb = 0, 0, 0 - local df = read_cmd("df -k / 2>/dev/null | awk 'NR==2{print $2,$3}'") - if df then - local dtotal, dused = df:match("^(%d+)%s+(%d+)$") - dtotal = tonumber(dtotal) or 0 - dused = tonumber(dused) or 0 - if dtotal > 0 then - disk_pct = math.floor(dused / dtotal * 100 + 0.5) - disk_used_mb = math.floor(dused / 1024 + 0.5) - disk_total_mb = math.floor(dtotal / 1024 + 0.5) - end - end - - -- ── CPU temperature ─────────────────────────────────────────────────────── - local cpu_temp = nil - -- Scan all available thermal zones and pick the highest valid reading - -- (avoids hardcoded zone numbers which vary per device) - for zone = 0, 9 do - local path = "/sys/class/thermal/thermal_zone" .. zone .. "/temp" - local tf = io.open(path, "r") - if tf then - local val = tf:read("*l") - tf:close() - local t = tonumber(val) - if t and t > 0 then - -- values > 1000 are in millidegrees - if t > 1000 then t = t / 1000 end - t = math.floor(t + 0.5) - -- Keep the highest temperature reading across all zones - if cpu_temp == nil or t > cpu_temp then - cpu_temp = t - end - end - end - end - - luci.http.prepare_content("application/json") - luci.http.write_json({ stats = stats, ip = ip, status = status, - prefer_iface = prefer_iface, - uptime = uptime_sec, - cpu_pct = cpu_pct, - cpu_temp = cpu_temp, - mem_pct = mem_pct, - mem_used = mem_used_mb, - mem_total = mem_total_mb, - disk_pct = disk_pct, - disk_used = disk_used_mb, - disk_total = disk_total_mb }) -end