-- acf model for displaying logfiles recusivly module (..., package.seeall) require("fs") require("date") require("format") local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin " -- ############################################################### -- Private functions local function querycmd ( cmdline ) local cmd = io.popen( path..format.escapespecialcharacters(cmdline) ) local cmd_result = cmd:read("*a") or "unknown" cmd:close() return cmd_result end local function indexversion ( ) local cmd = io.popen( path.."apk version --index 2>/dev/null" ) local cmd_result = cmd:read("*a") if cmd_result == "" then cmd_result = nil end cmd:close() return cmd_result end local function diskfree ( media ) if not (media) then media = "" end local cmd = io.popen( path.."df -h " .. format.escapespecialcharacters(media) ) local cmd_result = cmd:read("*a") or "unknown" cmd:close() return cmd_result end local function memusage () local mult = { kB=1024, MB=1048576, GB=1073741824 } local fd = io.open("/proc/meminfo") local res = {} local field, value, unit for line in fd:lines() do field,value, unit = string.match(line, "([^: ]*):%s*(%d+)%s(%a+)") if field ~= nil and value ~= nil then res[field] = tonumber(value) if unit ~= nil then res[field] = res[field] * mult[unit] end end end fd:close() return res end -- ############################################################### -- Public functions get_system = function (self) local system = {} local meminfo = memusage() system.uptime = cfe({ value=querycmd("uptime"), label="Uptime" }) system.date = cfe({ value=querycmd("date"), label="Date" }) local indexver = indexversion() system.version = cfe({ value=indexver or fs.read_file("/etc/alpine-release") or "Unknown", label="Version" }) system.timezone = cfe({ value=date.what_tz(), label="Time Zone" }) system.uname = cfe({ value=querycmd("uname -a"), label="UName" }) system.memory = cfe({ value=querycmd("free"), label="Memory usage" }) system.memory.free = math.floor(100 * meminfo["MemFree"] / meminfo["MemTotal"]) system.memory.buffers = math.floor(100 * (meminfo["Buffers"] + meminfo["Cached"]) / meminfo["MemTotal"]) system.memory.used = 100 - math.floor(100 * (meminfo["MemFree"] + meminfo["Buffers"] + meminfo["Cached"]) / meminfo["MemTotal"]) return cfe({ type="group", value=system }) end get_storage = function (self) local storage = {} local disk = diskfree() .. "\n" local other = {} local lines = format.string_to_table(disk, "\n") local i = 1 -- skip the first line while i < #lines do i = i+1 line = lines[i] or "" if lines[i+1] and string.match(lines[i+1], "^%s") then i = i+1 line = line .. "\n" .. lines[i] end if string.match(line, "^/dev/fd%d+") then if not storage.floppy then storage.floppy = cfe({ type="group", value={}, label="Floppy drives" }) end local name = string.match(line, "^(/dev/fd%d+)") storage.floppy.value[name] = cfe({ value=string.match(disk, "[^\n]*\n")..line, label="Floppy Capacity" }) storage.floppy.value[name].used = string.match(line, name.."%s*%S*%s*%S*%s*%S*%s*(%S*)%%") elseif string.match(line, "^/dev/none") or string.match(line, "^tmpfs") then if not storage.ramdisk then storage.ramdisk = cfe({ type="group", value={}, label="RAM disks" }) end local name = string.match(line, "^(%S+)") storage.ramdisk.value[name] = cfe({ value=string.match(disk, "[^\n]*\n")..line, label="RAM Disk Capacity" }) storage.ramdisk.value[name].used = string.match(line, name.."%s*%S*%s*%S*%s*%S*%s*(%S*)%%") elseif string.match(line, "^/dev/") and not string.match(line, "^/dev/cdrom") and not string.match(line, "^/dev/loop") then if not storage.hd then storage.hd = cfe({ type="group", value={}, label="Hard drives" }) end local name = string.match(line, "^(%S+)") storage.hd.value[name] = cfe({ value=string.match(disk, "[^\n]*\n")..line, label="Hard Drive Capacity" }) storage.hd.value[name].used = string.match(line, name.."%s*%S*%s*%S*%s*%S*%s*(%S*)%%") end end storage.partitions = cfe({ value=fs.read_file("/proc/partitions") or "", label="Partitions" }) return cfe({ type="group", value=storage }) end get_network = function (self) local network = {} network.interfaces = cfe({ value=querycmd("ip addr"), label="Interfaces" }) network.routes = cfe({ value=querycmd("ip route"), label="Routes" }) network.tunnel = cfe({ value=querycmd("ip tunnel"), label="Tunnels" }) return cfe({ type="group", value=network }) end get_proc = function (self) local proc = {} proc.processor = cfe({ value=fs.read_file("/proc/cpuinfo") or "", label="Processor" }) proc.memory = cfe({ value=fs.read_file("/proc/meminfo") or "", label="Memory" }) return cfe({ type="group", value=proc }) end get_networkstats = function () local stats = cfe({ type="structure", value={}, label="Network Stats", timestamp=os.time() }) local result = fs.read_file("/proc/net/dev") or "" -- parse the result local i=0 for line in string.gmatch(result, "[^\n]+\n?") do if i>1 then local intf = string.match(line, "([^%s:]+):") line = string.match(line, ":(.*)$") local words = {} for word in string.gmatch(line, "%S+") do words[#words+1] = word end stats.value[intf] = {} stats.value[intf].RX = {bytes=words[1], packets=words[2]} stats.value[intf].TX = {bytes=words[9], packets=words[10]} end i=i+1 end return stats end