Refactoring. Added respawn option to init-script.

This commit is contained in:
gSpot
2025-09-25 22:38:53 +03:00
parent cb7dbba054
commit 1720662f73
12 changed files with 198 additions and 152 deletions

View File

@@ -20,22 +20,22 @@ Internet-detector is an application for checking the availability of the Interne
## Installation notes:
opkg update
wget --no-check-certificate -O /tmp/internet-detector_1.6.4-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector_1.6.4-r1_all.ipk
opkg install /tmp/internet-detector_1.6.4-r1_all.ipk
rm /tmp/internet-detector_1.6.4-r1_all.ipk
wget --no-check-certificate -O /tmp/internet-detector_1.6.5-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector_1.6.5-r1_all.ipk
opkg install /tmp/internet-detector_1.6.5-r1_all.ipk
rm /tmp/internet-detector_1.6.5-r1_all.ipk
service internet-detector start
service internet-detector enable
wget --no-check-certificate -O /tmp/luci-app-internet-detector_1.6.4-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-app-internet-detector_1.6.4-r1_all.ipk
opkg install /tmp/luci-app-internet-detector_1.6.4-r1_all.ipk
rm /tmp/luci-app-internet-detector_1.6.4-r1_all.ipk
wget --no-check-certificate -O /tmp/luci-app-internet-detector_1.6.5-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-app-internet-detector_1.6.5-r1_all.ipk
opkg install /tmp/luci-app-internet-detector_1.6.5-r1_all.ipk
rm /tmp/luci-app-internet-detector_1.6.5-r1_all.ipk
service rpcd restart
i18n-ru:
wget --no-check-certificate -O /tmp/luci-i18n-internet-detector-ru_1.6.4-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-i18n-internet-detector-ru_1.6.4-r1_all.ipk
opkg install /tmp/luci-i18n-internet-detector-ru_1.6.4-r1_all.ipk
rm /tmp/luci-i18n-internet-detector-ru_1.6.4-r1_all.ipk
wget --no-check-certificate -O /tmp/luci-i18n-internet-detector-ru_1.6.5-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-i18n-internet-detector-ru_1.6.5-r1_all.ipk
opkg install /tmp/luci-i18n-internet-detector-ru_1.6.5-r1_all.ipk
rm /tmp/luci-i18n-internet-detector-ru_1.6.5-r1_all.ipk
## Screenshots:
@@ -47,9 +47,9 @@ i18n-ru:
**Dependences:** modemmanager.
wget --no-check-certificate -O /tmp/internet-detector-mod-modem-restart_1.6.4-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-modem-restart_1.6.4-r1_all.ipk
opkg install /tmp/internet-detector-mod-modem-restart_1.6.4-r1_all.ipk
rm /tmp/internet-detector-mod-modem-restart_1.6.4-r1_all.ipk
wget --no-check-certificate -O /tmp/internet-detector-mod-modem-restart_1.6.5-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-modem-restart_1.6.5-r1_all.ipk
opkg install /tmp/internet-detector-mod-modem-restart_1.6.5-r1_all.ipk
rm /tmp/internet-detector-mod-modem-restart_1.6.5-r1_all.ipk
service internet-detector restart
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/04.jpg)
@@ -58,9 +58,9 @@ i18n-ru:
**Dependences:** mailsend.
wget --no-check-certificate -O /tmp/internet-detector-mod-email_1.6.4-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-email_1.6.4-r1_all.ipk
opkg install /tmp/internet-detector-mod-email_1.6.4-r1_all.ipk
rm /tmp/internet-detector-mod-email_1.6.4-r1_all.ipk
wget --no-check-certificate -O /tmp/internet-detector-mod-email_1.6.5-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-email_1.6.5-r1_all.ipk
opkg install /tmp/internet-detector-mod-email_1.6.5-r1_all.ipk
rm /tmp/internet-detector-mod-email_1.6.5-r1_all.ipk
service internet-detector restart
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/05.jpg)
@@ -69,9 +69,9 @@ i18n-ru:
**Dependences:** curl.
wget --no-check-certificate -O /tmp/internet-detector-mod-telegram_1.6.4-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-telegram_1.6.4-r1_all.ipk
opkg install /tmp/internet-detector-mod-telegram_1.6.4-r1_all.ipk
rm /tmp/internet-detector-mod-telegram_1.6.4-r1_all.ipk
wget --no-check-certificate -O /tmp/internet-detector-mod-telegram_1.6.5-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-telegram_1.6.5-r1_all.ipk
opkg install /tmp/internet-detector-mod-telegram_1.6.5-r1_all.ipk
rm /tmp/internet-detector-mod-telegram_1.6.5-r1_all.ipk
service internet-detector restart
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/06.jpg)

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector-mod-email
PKG_VERSION:=1.6.4
PKG_VERSION:=1.6.5
PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector-mod-modem-restart
PKG_VERSION:=1.6.4
PKG_VERSION:=1.6.5
PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector-mod-telegram
PKG_VERSION:=1.6.4
PKG_VERSION:=1.6.5
PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>

View File

@@ -120,16 +120,23 @@ end
function Module:httpRequest(url)
local retCode = 1, data
local fh = io.popen(string.format(
'%s --connect-timeout %s %s "%s"; printf "\n$?";', self.curlExec, self.connectTimeout, self.curlParams, url), "r")
'%s --connect-timeout %s %s "%s"; printf "\n$?";',
self.curlExec,
self.connectTimeout,
self.curlParams,
url
), "r")
if fh then
data = fh:read("*a")
fh:close()
if data ~= nil then
local s, e = data:find("[0-9]+\n?$")
retCode = tonumber(data:sub(s))
data = data:sub(0, s - 2)
if not data or data == "" then
data = nil
end
end
else
retCode = 1
end

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector
PKG_VERSION:=1.6.4
PKG_VERSION:=1.6.5
PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>

View File

@@ -11,6 +11,8 @@ run_instance() {
if [ $enabled = "1" ]; then
procd_open_instance "$1"
procd_set_param command "$PROG" "-a" "nodaemon" "-i" "$1"
procd_set_param respawn
procd_set_param term_timeout 60
procd_close_instance
fi
}

View File

@@ -51,11 +51,15 @@ local InternetDetector = {
modules = {},
parsedHosts = {},
uiCounter = 0,
pidFile = nil,
statusFile = nil,
}
InternetDetector.configDir = string.format("/etc/%s", InternetDetector.appName)
InternetDetector.modulesDir = string.format(
"%s/%s/modules", InternetDetector.libDir, InternetDetector.appName)
InternetDetector.commonDir = string.format("/tmp/run/%s", InternetDetector.appName)
InternetDetector.appNamePattern = InternetDetector.appName:gsub("-", "%%-")
InternetDetector.pidFilePattern = "^" .. InternetDetector.appNamePattern .. ".-%.pid$"
-- Loading settings from UCI
@@ -79,11 +83,9 @@ elseif err then
io.stderr:write(string.format("Error: %s\n", err))
end
local _RUNNING
function InternetDetector:prequire(package)
local retVal, pkg = pcall(require, package)
return retVal and pkg
local ok, pkg = pcall(require, package)
return ok and pkg
end
function InternetDetector:loadUCIConfig(sType, instance)
@@ -107,10 +109,6 @@ function InternetDetector:loadUCIConfig(sType, instance)
end
)
self.serviceConfig.instance = instance
self.pidFile = string.format(
"%s/%s.%s.pid", self.commonDir, self.appName, instance)
self.statusFile = string.format(
"%s/%s.%s.status", self.commonDir, self.appName, instance)
return success
end
@@ -317,25 +315,16 @@ function InternetDetector:TCPConnectionToHost(host, port)
return retCode
end
function InternetDetector:checkHosts()
local checkFunc = (self.serviceConfig.check_type == 1) and self.pingHost or self.TCPConnectionToHost
local retCode = 1
for k, v in ipairs(self.parsedHosts) do
for i = 1, self.serviceConfig.connection_attempts do
if checkFunc(self, v.addr, v.port) == 0 then
retCode = 0
break
function InternetDetector:exit()
for _, e in ipairs(self.modules) do
e:onExit()
end
self:removeProcessFiles()
if self.loggingLevel > 0 then
self:writeLogMessage("info", "stoped")
syslog.closelog()
end
if retCode == 0 then
break
end
end
return retCode
end
function InternetDetector:breakMainLoop(signo)
_RUNNING = false
os.exit(0)
end
function InternetDetector:resetUiCounter(signo)
@@ -343,9 +332,9 @@ function InternetDetector:resetUiCounter(signo)
end
function InternetDetector:mainLoop()
signal.signal(signal.SIGTERM, function(signo) self:breakMainLoop(signo) end)
signal.signal(signal.SIGINT, function(signo) self:breakMainLoop(signo) end)
signal.signal(signal.SIGQUIT, function(signo) self:breakMainLoop(signo) end)
signal.signal(signal.SIGTERM, function(signo) self:exit(signo) end)
signal.signal(signal.SIGINT, function(signo) self:exit(signo) end)
signal.signal(signal.SIGQUIT, function(signo) self:exit(signo) end)
signal.signal(signal.SIGUSR1, function(signo) self:resetUiCounter(signo) end)
local lastStatus, currentStatus, mTimeNow, mTimeDiff, mLastTime, uiTimeNow, uiLastTime
@@ -353,24 +342,75 @@ function InternetDetector:mainLoop()
local modulesStatus = {}
local counter = 0
local inetChecked = false
_RUNNING = true
while _RUNNING do
local checking = false
local hostNum = 1
local attempt = 1
local checkFunc = (self.serviceConfig.check_type == 1) and self.pingHost or self.TCPConnectionToHost
while true do
if counter == 0 or counter >= interval then
checking = true
end
if checking then
local newStatus = 1
local checkCompleted = false
if hostNum <= #self.parsedHosts then
if attempt <= self.serviceConfig.connection_attempts then
local addr = self.parsedHosts[hostNum].addr
local port = self.parsedHosts[hostNum].port
local retCode = 1
if self.debug then
currentStatus = self:checkHosts()
retCode = checkFunc(self, addr, port)
else
local ret, status = pcall(self.checkHosts, self, currentStatus)
if ret then
currentStatus = status
local ok, status = pcall(checkFunc, self, addr, port)
if ok then
retCode = status
else
self:writeLogMessage("err", "Unknown error while checking host!")
self:writeLogMessage("err", string.format(
"An error occurred while checking the host %s: %s",
tostring(addr),
tostring(status))
)
end
end
if retCode == 0 then
attempt = 1
hostNum = 1
checking = false
newStatus = 0
counter = 0
checkCompleted = true
else
attempt = attempt + 1
if attempt > self.serviceConfig.connection_attempts then
attempt = 1
hostNum = hostNum + 1
end
end
else
attempt = 1
hostNum = hostNum + 1
end
if hostNum > #self.parsedHosts then
hostNum = 1
checking = false
counter = 0
checkCompleted = true
end
else
hostNum = 1
checking = false
counter = 0
checkCompleted = true
end
if checkCompleted then
currentStatus = newStatus
if not stat.stat(self.statusFile) then
self:writeValueToFile(self.statusFile, self:statusJson(
currentStatus, self.serviceConfig.instance))
end
if currentStatus == 0 then
interval = self.serviceConfig.interval_up
if currentStatus ~= lastStatus then
@@ -386,7 +426,7 @@ function InternetDetector:mainLoop()
self:writeLogMessage("notice", "Disconnected")
end
end
counter = 0
end
end
mTimeDiff = 0
@@ -402,9 +442,10 @@ function InternetDetector:mainLoop()
if self.debug then
e:run(currentStatus, lastStatus, mTimeDiff, mTimeNow, inetChecked)
else
local ret = pcall(e.run, e, currentStatus, lastStatus, mTimeDiff, mTimeNow, inetChecked)
if not ret then
self:writeLogMessage("err", string.format("%s: Unknown error!", e.name))
local ok, err = pcall(e.run, e, currentStatus, lastStatus, mTimeDiff, mTimeNow, inetChecked)
if not ok then
self:writeLogMessage("err", string.format(
"%s: Module error: %s", e.name, tostring(err)))
end
end
end
@@ -421,9 +462,12 @@ function InternetDetector:mainLoop()
currentStatus, self.serviceConfig.instance, modulesStatus))
end
lastStatus = currentStatus
unistd.sleep(1)
if not checking then
lastStatus = currentStatus
counter = counter + 1
end
if self.mode == 2 then
uiTimeNow = time.clock_gettime(time.CLOCK_MONOTONIC).tv_sec
@@ -434,25 +478,22 @@ function InternetDetector:mainLoop()
end
uiLastTime = uiTimeNow
if self.uiCounter >= self.uiRunTime then
self:breakMainLoop(signal.SIGTERM)
self:exit(signal.SIGTERM)
end
end
end
end
function InternetDetector:removeProcessFiles()
os.remove(string.format(
"%s/%s.%s.pid", self.commonDir, self.appName, self.serviceConfig.instance))
os.remove(string.format(
"%s/%s.%s.status", self.commonDir, self.appName, self.serviceConfig.instance))
os.remove(self.statusFile)
os.remove(self.pidFile)
end
function InternetDetector:status()
local ok, commonDir = pcall(dirent.files, self.commonDir)
if ok then
local appName = self.appName:gsub("-", "%%-")
for item in commonDir do
if item:match("^" .. appName .. ".-%.pid$") then
if item:match(self.pidFilePattern) then
return "running"
end
end
@@ -464,10 +505,10 @@ function InternetDetector:inetStatus()
local inetStat = '{"instances":[]}'
local ok, commonDir = pcall(dirent.files, self.commonDir)
if ok then
local appName = self.appName:gsub("-", "%%-")
local statusFilePattern = "^" .. self.appNamePattern .. ".-%.status$"
local lines = {}
for item in commonDir do
if item:match("^" .. appName .. ".-%.status$") then
if item:match(statusFilePattern) then
lines[#lines + 1] = self:readValueFromFile(
string.format("%s/%s", self.commonDir, item))
end
@@ -478,7 +519,7 @@ function InternetDetector:inetStatus()
end
function InternetDetector:stopInstance(pidFile)
local retVal
local retVal = false, pidValue
if stat.stat(pidFile) then
pidValue = self:readValueFromFile(pidFile)
if pidValue then
@@ -497,6 +538,8 @@ function InternetDetector:stopInstance(pidFile)
os.remove(pidFile)
end
retVal = true
else
os.remove(pidFile)
end
end
if not pidValue then
@@ -508,22 +551,22 @@ function InternetDetector:stopInstance(pidFile)
end
function InternetDetector:stop()
local appName = self.appName:gsub("-", "%%-")
local success
for i = 0, 10 do
success = true
local nopids = false
for i = 0, 100 do
nopids = true
local ok, commonDir = pcall(dirent.files, self.commonDir)
if ok then
for item in commonDir do
if item:match("^" .. appName .. ".-%.pid$") then
self:stopInstance(string.format("%s/%s", self.commonDir, item))
success = false
if item:match(self.pidFilePattern) then
if self:stopInstance(string.format("%s/%s", self.commonDir, item)) then
nopids = false
end
end
if success then
end
if nopids then
break
end
unistd.sleep(1)
time.nanosleep({ tv_sec = 0, tv_nsec = 10000000 })
else
break
end
@@ -531,11 +574,10 @@ function InternetDetector:stop()
end
function InternetDetector:setSIGUSR()
local appName = self.appName:gsub("-", "%%-")
local ok, commonDir = pcall(dirent.files, self.commonDir)
if ok then
for item in commonDir do
if item:match("^" .. appName .. ".-%.pid$") then
if item:match(self.pidFilePattern) then
pidValue = self:readValueFromFile(string.format("%s/%s", self.commonDir, item))
if pidValue then
signal.kill(tonumber(pidValue), signal.SIGUSR1)
@@ -559,18 +601,25 @@ function InternetDetector:preRun()
os.exit(1)
end
end
if stat.stat(self.pidFile) then
io.stderr:write(
string.format('PID file "%s" exists. Is the %s already running?\n',
self.pidFile, self.appName))
return false
local ok, commonDir = pcall(dirent.files, self.commonDir)
if ok then
local instancePattern = "^" .. self.appNamePattern .. "%." .. self.serviceConfig.instance .. "%.[%d]+%.pid$"
for item in commonDir do
if item:match(instancePattern) then
self:stopInstance(string.format("%s/%s", self.commonDir, item))
end
end
end
return true
end
function InternetDetector:run()
local pidValue = unistd.getpid()
self.pidFile = string.format(
"%s/%s.%s.%s.pid", self.commonDir, self.appName, self.serviceConfig.instance, pidValue)
self.statusFile = string.format(
"%s/%s.%s.status", self.commonDir, self.appName, self.serviceConfig.instance)
self:writeValueToFile(self.pidFile, pidValue)
if self.loggingLevel > 0 then
syslog.openlog(self.appName, syslog.LOG_PID, syslog.LOG_DAEMON)
end
@@ -613,29 +662,16 @@ function InternetDetector:run()
self.statusFile, self:statusJson(-1, self.serviceConfig.instance))
self:mainLoop()
for _, e in ipairs(self.modules) do
e:onExit()
end
self:removeProcessFiles()
if self.loggingLevel > 0 then
self:writeLogMessage("info", "stoped")
syslog.closelog()
end
self:exit()
end
function InternetDetector:noDaemon()
if not self:preRun() then
return
end
self:preRun()
self:run()
end
function InternetDetector:daemon()
if not self:preRun() then
return
end
self:preRun()
-- UNIX double fork
if unistd.fork() == 0 then
unistd.setpid("s")

View File

@@ -25,6 +25,7 @@ local Module = {
_enabled = false,
_leds = {},
_counter = 0,
_exit = false,
}
function Module:setLedAttrs(t)
@@ -114,6 +115,7 @@ function Module:init(t)
self.syslog("err", string.format(
"%s: module disabled. LED '%s' is not available", self.name, l.ledName))
end
self._exit = false
end
end
@@ -303,6 +305,9 @@ function Module:run(currentStatus, lastStatus, timeDiff, timeNow, inetChecked)
end
if self._counter == 0 or self._counter >= self.runInterval or currentStatus ~= lastStatus then
for _, t in ipairs(self._leds) do
if self._exit then
break
end
if t.enabled then
self:ledRunFunc(t, currentStatus)
end
@@ -313,6 +318,7 @@ function Module:run(currentStatus, lastStatus, timeDiff, timeNow, inetChecked)
end
function Module:onExit()
self._exit = true
for _, l in ipairs(self._leds) do
if l.ledPrevState then
if l.ledPrevState.brightness then

View File

@@ -362,12 +362,14 @@ function Module:httpRequest(url)
if fh then
data = fh:read("*a")
fh:close()
if data ~= nil then
local s, e = data:find("[0-9]+\n?$")
retCode = tonumber(data:sub(s))
data = data:sub(0, s - 2)
if not data or data == "" then
data = nil
end
end
else
retCode = 1
end

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-internet-detector
PKG_VERSION:=1.6.4
PKG_VERSION:=1.6.5
PKG_RELEASE:=1
LUCI_TITLE:=LuCI support for internet-detector
LUCI_DEPENDS:=+internet-detector

View File

@@ -844,8 +844,6 @@ return view.extend({
o.value(1);
o.value(2);
o.value(3);
o.value(4);
o.value(5);
o.default = '2';
// connection_timeout
@@ -859,11 +857,6 @@ return view.extend({
o.value(3, '3 ' + _('sec'));
o.value(4, '4 ' + _('sec'));
o.value(5, '5 ' + _('sec'));
o.value(6, '6 ' + _('sec'));
o.value(7, '7 ' + _('sec'));
o.value(8, '8 ' + _('sec'));
o.value(9, '9 ' + _('sec'));
o.value(10, '10 ' + _('sec'));
o.default = '2';
// enabled
@@ -1569,7 +1562,7 @@ return view.extend({
// enabled
o = s.taboption('telegram', form.Flag,
'mod_telegram_enabled',
_('Enable'));
_('Enabled'));
o.rmempty = false;
o.modalonly = true;