#!/opt/lnxall_app/bin/lua -- Created by jiaqiang.ye@lnxall.com -- Simple upstart for application installation -- 2025/08/12 local invoker = require "invoker" local gfmt = string.format local g_shell = "/bin/bash" local g_UPDIR = "/opt/lnxall_app/app/upstart" local g_UPTAG = nil local g_UPLOCK = "/tmp/.upstart.lock" local g_TMPDIR = "/tmp/.upstart.home" local g_lockfd = nil local function lupstart_init() -- Created temporary directory: invoker.mkdir(g_TMPDIR) if not invoker.chdir(g_TMPDIR) then io.stderr:write(gfmt("Error, directory not found: %s\n", g_TMPDIR)) io.stderr:flush() os.exit(1) end -- Get UPSTART Directory from environment variable: local updir = os.getenv("LUPSTART_DIR") if type(updir) == "string" and #updir > 0 then g_UPDIR = updir end -- Get UPSTART TAG Directory from environment variable: updir = os.getenv("LUPSTART_TAGDIR") if type(updir) == "string" and #updir > 0 then g_UPTAG = updir else g_UPTAG = g_UPDIR end -- determine shell executable if not invoker.statfile(g_shell) then g_shell = "/bin/sh" end -- close any lingering file descriptors for ifd = 3, 64 do invoker.closefd(ifd) end io.stdout:write(gfmt("UPSTART_DIR: %s, TAGDIR: %s\n", g_UPDIR, g_UPTAG)) io.stdout:flush() -- acquire file system lock local lockfd = invoker.waitlock(g_UPLOCK) if not lockfd then io.stderr:write(gfmt("Error, failed to acquire file-lock: %s\n", g_UPLOCK)) io.stderr:flush() os.exit(2) end g_lockfd = lockfd return true end local function lupstart_run(ups, upfile, tagfile) io.stdout:write(gfmt("Running upstart script: %s ...\n", upfile)) io.stdout:flush() local pid = invoker.invoke(invoker.NOWAIT, g_shell, ups, "install") if not pid then io.stderr:write(gfmt("Error, failed to run script: %s\n", ups)) io.stderr:flush() return false end local exited, exitval = false, 0 local wbegin, dokill = invoker.uptime() + 90, true while wbegin > invoker.uptime() do exited, exitval = invoker.waitpid(pid, true) if exited == nil or exited then dokill = false break end invoker.msleep(320) end if dokill then exitval = 2024 if not invoker.kill(pid, 9) then invoker.kill(pid, 9) end io.stderr:write(gfmt("Error, killing upstart script: %s\n", ups)) io.stderr:flush() invoker.waitpid(pid, false) end if type(exitval) ~= "number" then exitval = 2025 end local tfp = io.open(tagfile, "wb") if not tfp then io.stderr:write(gfmt("Error, failed to open tagfile: %s\n", tagfile)) io.stderr:flush() return false end tfp:write(gfmt("%s: %s => exited with: %d\n", os.date(), upfile, exitval)) tfp:close(); tfp = nil io.stdout:write(gfmt("Script '%s' exited with: %d\n", upfile, exitval)) io.stdout:flush() return true end local function lupstart_main() local lups = invoker.glob(gfmt("%s/*.sh", g_UPDIR)) if type(lups) ~= "table" then io.stderr:write(gfmt("Error, no upstart scripts found in %s\n", g_UPDIR)) io.stderr:flush() return false end for _, upscript in ipairs(lups) do local scriptn = string.match(upscript, "/([^/]+)$") or "NOTFOUND" local tagpath = gfmt("%s/.%s.done", g_UPTAG, scriptn) local typf, size = invoker.statfile(upscript) if typf == "regular" and size > 0 and not invoker.statfile(tagpath) then lupstart_run(upscript, scriptn, tagpath) end end return true end lupstart_init() lupstart_main() os.exit(0)