#!/opt/lnxall_app/bin/lua -- Created by hongbo.he@lnxall.com -- 2025/11/24 local invoker = require "invoker" local g_config_file = '/etc/frpc.toml' local g_oldconfig_file = '/etc/frpc.ini' local g_maxretries = 5 local function get_random_string(length) math.randomseed(os.time()) local chars = "abcdefghijklmnopqrstuvwxyz0123456789" local rstr = '' for i = 1, length do local rand = math.random(1, #chars) rstr = rstr .. string.sub(chars, rand, rand) end return rstr end local function get_gateway_sn() local gwsn = nil local eval, output = invoker.invoke(invoker.NOSTDIO + invoker.OUTPUT, "factory", "get") if eval == 0 and type(output) == "string" then gwsn = string.match(output, "SN=(%x+)") end if not gwsn then output = invoker.readfile("/app/config/fac.ini") if type(output) == "string" then gwsn = string.match(output, "sn%s*=%s*(%x+)") end end if not gwsn then io.stderr:write("Error, failed to determine gateway SN!\n") io.stderr:flush() return nil end io.stdout:write(string.format("Gateway SN: %s\n", gwsn)) io.stdout:flush() return gwsn end local function set_config_subdomain(rstr) if not rstr then return false end local content = invoker.readfile(g_config_file) if content then local domain = string.match(content, 'subdomain%s*=%s*"([^\n"]*)"') if domain then if domain == '' or #domain ~= 10 then content = string.gsub(content, 'subdomain%s*=%s*"[^\n"]*"', 'subdomain = "' .. rstr .. '"') local fp = io.open(g_config_file, 'wb'); if fp then fp:write(content) fp:close() io.stdout:write(string.format("set 'subdomain': %s => %s\n", domain, rstr)) io.stdout:flush() return true end end else io.stderr:write(string.format("Error, no 'subdomain' word, please check: %s\n", g_config_file)) io.stderr:flush() end end return false end local function set_config_user(gwsn) if not gwsn then return false end local content = invoker.readfile(g_config_file) if content then local _, user = string.match(content, '([^%.]user)%s*=%s*"([^\n"]*)"') print(user) if user then if user == '' or user ~= gwsn then content = string.gsub(content, '([^%.]user)%s*=%s*"[^\n"]*"', '%1 = "' .. gwsn .. '"') local fp = io.open(g_config_file, 'wb') if fp then fp:write(content) fp:close() io.stdout:write(string.format("set 'user': %s\n", gwsn)) io.stdout:flush() return true end return false end else io.stderr:write(string.format("Error, no 'user' word, please check: %s\n", g_config_file)) io.stderr:flush() end end return true end local function set_config() local link = invoker.readlink(g_config_file) if type(link) ~= 'string' or #link == 0 or not string.find(link, g_config_file) then io.stderr:write(string.format("Error, %s is not a real frpc.toml\n", g_config_file)) io.stderr:flush() return false end local gwsn = get_gateway_sn() if gwsn then set_config_user(gwsn) end local output = invoker.readfile(g_config_file) if not output or output == "" then io.stderr:write(string.format("Error, read config: %s\n", g_config_file)) io.stderr:flush() return false end local rstr = get_random_string(10) if rstr then set_config_subdomain(rstr) end return true end local function start_frpc() local _, output = invoker.invoke(invoker.OUTPUT, '/usr/bin/frpc', '-v') if type(output) ~= 'string' or #output == 0 then io.stderr:write("Error, 'frpc' execute failed\n") io.stderr:flush() return false end -- if old frpc version if string.find(output, '0.25.3') then io.stdout:write(string.format("Warn, 'frpc' version: %s\n", output)) io.stdout:flush() invoker.invoke(invoker.NOFORK, 'frpc', '-c', g_oldconfig_file) return false end local retries = 0 while retries < g_maxretries do if set_config() then invoker.invoke(invoker.NOFORK, 'frpc', '-c', g_config_file) end retries = retries + 1 invoker.msleep(2000) end io.stderr:write(string.format("Error, reach to max retries: %d\n", g_maxretries)) io.stderr:flush() return false end start_frpc() os.exit(1)