123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- #!/usr/bin/lua
- local output_file = "/tmp/debug-report.txt"
- -- includes
- local nixio = require("nixio")
- local json = require("luci.jsonc")
- local uci = require("simple-uci").cursor()
- local site = require "gluon.site_config"
- local util = require "gluon.util"
- -- usefull variables
- local hostname = require("pretty_hostname").get(uci)
- local primary_mac = require("gluon.sysconfig").primary_mac
- local model = require("gluon.platform").get_model()
- local version = util.trim(io.open("/lib/gluon/gluon-version"):read("*a"))
- local release = util.trim(io.open("/lib/gluon/release"):read("*a"))
- -- get autoupdater branch
- local function autoupdate()
- local autoupdate = uci:get("autoupdater", "settings", "branch")
- if not uci:get_bool("autoupdater", "settings", "enabled") then
- autoupdate = "disabled (" .. autoupdater .. ")"
- end
- return autoupdate
- end
- -- get mesh IPs
- local function addresses()
- local addr = {}
- for line in io.popen("ip -family inet6 address show dev br-client"):lines() do
- local tmp = line:match("inet6%s+(%S+)%s+scope") or false
- if tmp then
- table.insert(addr, tmp)
- end
- end
- return addr
- end
- -- get memory usage
- local function memory()
- local fields = {}
- for k, v in io.open("/proc/meminfo"):read("*a"):gmatch("([^\n:]+):%s*(%d+) kB") do
- fields[k] = tonumber(v)
- end
- return string.format("%.1f %% used, %.1f %% free",(fields.MemTotal-fields.MemFree)/fields.MemTotal*100,fields.MemFree/fields.MemTotal*100)
- end
- -- get fastd public key
- local function pubkey()
- local key = util.trim(io.popen("/etc/init.d/fastd show_key mesh_vpn"):read("*a"))
- if key == "" then
- return "none"
- end
- return key
- end
- -- get location
- local function location()
- local text = "none"
- local locationid = uci:get_first("gluon-node-info", "location")
- if locationid then
- local location = uci:get_all("gluon-node-info", locationid)
- if uci:get_bool("gluon-node-info", locationid, "share_location") and location.latitude and location.longitude then
- text = location.latitude .. ", " .. location.longitude
- end
- end
- return text
- end
- -- get ip address type
- local function ip_proto(address)
- if address:match("%.") then
- return "IPv4"
- end
- if address:match(":") then
- return "IPv6"
- end
- return "???"
- end
- -- wrapper for calling systemcommands
- local function cmd(command)
- local l = io.popen(command .. " 2>&1"):read("*a")
- return "\n# " .. command .. "\n" .. l
- end
- -- read contents of a given file
- local function read_file(file)
- local l = io.open(file, "r"):read("*a")
- return "\n" .. file .. ":\n" .. l
- end
- -- blank variables
- local function blank(string, key)
- string = string:gsub(key .. "[^\n]+", key .. " -blanked-")
- return string
- end
- -- open output file in write mode
- print("Generating report ...")
- local out = io.open(output_file, "w")
- -- first of all, collect some generic information about the system
- out:write("---- BEGIN SYSTEM INFORMATION ----")
- out:write("\nHostname: " .. hostname)
- out:write("\nCommunity: " .. site.site_name)
- out:write("\nModel: " .. model)
- out:write("\nFirmware: " .. release .. " / " .. version)
- out:write("\nMAC: " .. primary_mac)
- out:write("\nContact: " .. uci:get_first("gluon-node-info", "owner", "contact", "none"))
- out:write("\nUptime: " .. util.trim(io.popen("uptime"):read("*a")))
- out:write("\nAutoupdater: " .. autoupdate())
- out:write("\nLocation: " .. location())
- out:write("\nIPs: " .. table.concat(addresses(), "\n "))
- out:write("\nPubkey: " .. pubkey())
- out:write("\nMemory: " .. memory())
- out:write("\n---- END SYSTEM INFORMATION ----\n\n")
- -- show cron jobs
- out:write("---- BEGIN CRON JOBS ----")
- for name in io.popen("ls /usr/lib/micron.d/"):lines() do
- out:write(read_file("/usr/lib/micron.d/" .. name))
- end
- out:write("---- END CRON JOBS ----\n\n")
- -- get autoupdater status
- out:write("---- BEGIN AUTOUPDATER INFORMATION ----")
- out:write(cmd("uci show autoupdater"))
- out:write(cmd("uci show autoupdater-wifi-fallback"))
- out:write("---- END AUTOUPDATER INFORMATION ----\n\n")
- -- now get some information about the network status
- out:write("---- BEGIN IP AND ROUTUNG INFORMATION ----")
- out:write(cmd("uci show network"))
- out:write(cmd("ip addr show"))
- out:write(cmd("ip route show"))
- out:write(cmd("ip -6 route show"))
- out:write("---- END IP AND ROUTUNG INFORMATION ----\n\n")
- -- get wireless status
- out:write("---- BEGIN WIRELESS INFORMATION ----")
- out:write(blank(cmd("uci show wireless"), "\.key="))
- for ifname in io.popen("iw dev"):read("*a"):gmatch("Interface%s([^\n]+)") do
- out:write(cmd("iwinfo " .. ifname .. " info"))
- if ifname:match("ibss") or ifname:match("mesh") then
- out:write(cmd("iwinfo " .. ifname .. " assoclist 2>&1"))
- end
- end
- out:write("---- END WIRELESS INFORMATION ----\n\n")
- -- get batman status
- out:write("---- BEGIN BATMAN STATUS ----")
- out:write(cmd("uci show batman-adv"))
- out:write(cmd("batctl gateways"))
- out:write(cmd("batctl neighbors"))
- out:write(cmd("batctl interface"))
- out:write("---- END BATMAN STATUS ----\n\n")
- -- get fastd status
- out:write("---- BEGIN FASTD STATUS ----")
- out:write(blank(cmd("uci show fastd"), "\.secret="))
- out:write(cmd("uci show simple-tc"))
- local stat, fastd_status = pcall(
- function()
- local fastd_sock = nixio.socket("unix", "stream")
- assert(fastd_sock:connect("/var/run/fastd.mesh_vpn.socket"))
- local decoder = json.new()
- local sink = decoder:sink()
- while true do
- local chunk = fastd_sock:read(2048)
- if not chunk or chunk:len() == 0 then break end
- sink(chunk)
- end
- return assert(decoder:get())
- end
- )
- if stat then
- out:write(string.format("\nfastd running for %.1f minutes\n", fastd_status.uptime/60000))
- local peers = 0
- local connections = 0
- for key, peer in pairs(fastd_status.peers) do
- peers = peers + 1
- if peer.connection then
- connections = connections + 1
- end
- end
- out:write(string.format("There are %i peers configured, of which %i are connected:\n", peers, connections))
- for key, peer in pairs(fastd_status.peers) do
- out:write(peer.name .. ": ")
- if peer.connection then
- out:write(string.format("connected for %.1f minutes via %s\n", peer.connection.established/60000, ip_proto(peer.address)))
- else
- out:write("not connected\n")
- end
- end
- else
- out:write("\nfastd not running\n")
- end
- out:write("---- END FASTD STATUS ----\n\n")
- -- get processes
- out:write("---- BEGIN PROCESS INFORMATION ----")
- out:write(cmd("ps ww"))
- out:write("---- END PROCESS INFORMATION ----\n\n")
- -- get log
- out:write("---- BEGIN LOG ----")
- out:write(cmd("logread"))
- out:write(cmd("dmesg"))
- out:write("---- END LOG ----\n\n")
- -- finish, close file and inform the user
- out:close()
- print("Your report has been stored at: " .. output_file )
- os.exit(0)
|