add luci-app-watchcat-plus

This commit is contained in:
SirPdboy 2023-04-18 01:53:47 +08:00 committed by GitHub
parent b6985660fb
commit 2b43f20571
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1116 additions and 0 deletions

View File

@ -0,0 +1,21 @@
#
# Copyright (C) 2008-2014 The LuCI gngpp <gngppz@gmail.com>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-watchcat-plus
PKG_VERSION:=1.3
PKG_RELEASE:=202303012
PKG_MAINTAINER:=gngpp <gngppz@gmail.com>
LUCI_TITLE:=LuCI Support for Watchcat
LUCI_DEPENDS:=+watchcat
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,28 @@
module("luci.controller.watchcat-plus", package.seeall)
function index()
if not nixio.fs.access("/etc/config/watchcat") then
return
end
local page
page = entry({"admin", "control", "watchcat-plus"}, alias("admin", "control", "watchcat-plus", "periodic_reboot"),
_("Watchcat Plus"), 10) -- 首页
page.dependent = true
page.acl_depends = { "luci-app-watchcat-plus" }
entry({"admin", "control", "watchcat-plus", "periodic_reboot"}, cbi("watchcat-plus/periodic_reboot"), translate("Periodic Reboot"), 10).leaf = true -- "定时重启模式页面"
entry({"admin", "control", "watchcat-plus", "ping_reboot"}, cbi("watchcat-plus/ping_reboot"), translate("Ping Reboot"), 20).leaf = true -- "Ping重启模式页面"
entry({"admin", "control", "watchcat-plus", "restart_iface"}, cbi("watchcat-plus/restart_iface"), translate("Restart Interface"), 30).leaf = true -- "重启接口模式页面"
entry({"admin", "control", "watchcat-plus", "run_script"}, cbi("watchcat-plus/run_script"), translate("Run Script"), 40).leaf = true -- "运行脚本模式界面"
entry({"admin", "control", "watchcat-plus", "log"}, form("watchcat-plus/log"), _("Log"), 50).leaf = true -- 日志页面
entry({"admin", "control", "watchcat-plus", "logread"}, call("action_logread"), nil).dependent = false -- 日志采集
end
function action_logread()
local e = luci.sys.exec("logread | grep watchcat")
if e == nil then
e = ""
end
luci.http.prepare_content("application/json")
luci.http.write_json(e);
end

View File

@ -0,0 +1,9 @@
log = SimpleForm("logview")
log.submit = false
log.reset = false
t = log:field(DummyValue, '', '')
t.rawhtml = true
t.template = 'watchcat-plus/watchcat-plus_log'
return log

View File

@ -0,0 +1,46 @@
m = Map("watchcat",
"",
translate("Here you can set up several checks and actions to take in the event that a host becomes unreachable. \
Click the <b>Add</b> button at the bottom to set up more than one action."
))
m.on_after_commit = function(self)
luci.sys.exec("service watchcat reload")
end
s = m:section(TypedSection, "watchcat")
s.anonymous = true
s.addremove = true
function s.filter(self, section)
return self.map:get(section, "mode") == "periodic_reboot"
end
-- 定时重启模式
mode = s:option(ListValue, "mode",
translate("Mode"),
translate("Periodic Reboot: Reboot this device after a specified interval of time."))
mode:value("periodic_reboot", translate("Periodic Reboot"))
mode.default = "periodic_reboot"
-- 周期
period = s:option(Value, "period",
translate("Period"),
translate("In Periodic Reboot mode, it defines how often to reboot. <br /> \
In Ping Reboot mode, it defines the longest period of \
time without a reply from the Host To Check before a reboot is engaged. <br /> \
In Network Restart or Run Script mode, it defines the longest period of \
time without a reply from the Host to Check before the interface is restarted or the script is run. \
<br /><br />The default unit is seconds, without a suffix, but you can use the \
suffix <b>m</b> for minutes, <b>h</b> for hours or <b>d</b> \
for days. <br /><br />Examples:<ul><li>10 seconds would be: <b>10</b> or <b>10s</b></li><li>5 minutes would be: <b>5m</b></li><li> \
1 hour would be: <b>1h</b></li><li>1 week would be: <b>7d</b></li><ul>"))
period.default = '6h'
-- 强制重启延时
forcedelay = s:option(Value, "forcedelay",
translate("Force Reboot Delay"),
translate("Applies to Ping Reboot and Periodic Reboot modes</i> <br /> When rebooting the router, the service will trigger a soft reboot. \
Entering a non-zero value here will trigger a delayed hard reboot if the soft reboot were to fail. \
Enter the number of seconds to wait for the soft reboot to fail or use 0 to disable the forced reboot delay."))
forcedelay.default = "1m"
return m

View File

@ -0,0 +1,93 @@
m = Map("watchcat",
"",
translate("Here you can set up several checks and actions to take in the event that a host becomes unreachable. \
Click the <b>Add</b> button at the bottom to set up more than one action."
))
m.on_after_commit = function(self)
luci.sys.exec("service watchcat reload")
end
s = m:section(TypedSection, "watchcat")
s.anonymous = true
s.addremove = true
function s.filter(self, section)
return self.map:get(section, "mode") == "ping_reboot"
end
-- Ping重启模式
mode = s:option(ListValue, "mode",
translate("Mode"),
translate("Ping Reboot: Reboot this device if a ping to a specified host fails for a specified duration of time."))
mode:value("ping_reboot", translate("Ping Reboot"))
mode.default = "ping_reboot"
-- 周期
period = s:option(Value, "period",
translate("Period"),
translate("In Periodic Reboot mode, it defines how often to reboot. <br /> \
In Ping Reboot mode, it defines the longest period of \
time without a reply from the Host To Check before a reboot is engaged. <br /> \
In Network Restart or Run Script mode, it defines the longest period of \
time without a reply from the Host to Check before the interface is restarted or the script is run. \
<br /><br />The default unit is seconds, without a suffix, but you can use the \
suffix <b>m</b> for minutes, <b>h</b> for hours or <b>d</b> \
for days. <br /><br />Examples:<ul><li>10 seconds would be: <b>10</b> or <b>10s</b></li><li>5 minutes would be: <b>5m</b></li><li> \
1 hour would be: <b>1h</b></li><li>1 week would be: <b>7d</b></li><ul>"))
period.default = '6h'
-- ping 主机
pinghosts = s:option(Value, "pinghosts",
translate("Host To Check"),
translate("IP address or hostname to ping."))
pinghosts.datatype = "host(1)"
pinghosts.default = "8.8.8.8"
-- ping 地址簇
addressfamily = s:option(ListValue, 'addressfamily',
translate('Address family for pinging the host'))
addressfamily:value("any", "any");
addressfamily:value("ipv4", "ipv4");
addressfamily:value("ipv6", "ipv6");
addressfamily.default = "any";
-- ping周期
pingperiod = s:option(Value, "pingperiod",
translate("Check Interval"),
translate("How often to ping the host specified above. \
<br /><br />The default unit is seconds, without a suffix, but you can use the suffix <b>m</b> for minutes, <b>h</b> for hours or <b>d</b> for days. <br /><br /> \
Examples:<ul><li>10 seconds would be: <b>10</b> or <b>10s</b></li><li>5 minutes would be: <b>5m</b></li><li>1 hour would be: <b>1h</b></li><li>1 week would be: <b>7d</b></li><ul>"))
pingperiod.default = "30s"
-- ping 包大小
pingsize = s:option(ListValue, 'pingsize', translate('Ping Packet Size'));
pingsize:value('small', translate('Small: 1 byte'));
pingsize:value('windows', translate('Windows: 32 bytes'));
pingsize:value('standard', translate('Standard: 56 bytes'));
pingsize:value('big', translate('Big: 248 bytes'));
pingsize:value('huge', translate('Huge: 1492 bytes'));
pingsize:value('jumbo', translate('Jumbo: 9000 bytes'));
pingsize.default = 'standard';
-- 强制重启延时
forcedelay = s:option(Value, "forcedelay",
translate("Force Reboot Delay"),
translate("Applies to Ping Reboot and Periodic Reboot modes</i> <br /> When rebooting the router, the service will trigger a soft reboot. \
Entering a non-zero value here will trigger a delayed hard reboot if the soft reboot were to fail. \
Enter the number of seconds to wait for the soft reboot to fail or use 0 to disable the forced reboot delay."))
forcedelay.default = "1m"
-- 接口
interface = s:option(Value, "interface",
translate('Restart Interface'),
translate("Interface to monitor and/or restart.<br/><br/><i>Applies to Ping Reboot, Restart Interface, and Run Script modes</i> <br /> Specify the interface to monitor and react if a ping over it fails.")
);
device_table = luci.sys.net.devices();
if device_table ~= nil then
for k, v in ipairs(device_table) do
if v ~= "lo" then
interface:value(v, v)
end
end
end
return m

View File

@ -0,0 +1,107 @@
require("luci.tools.webadmin")
m = Map("watchcat",
"",
translate("Here you can set up several checks and actions to take in the event that a host becomes unreachable. \
Click the <b>Add</b> button at the bottom to set up more than one action."
))
m.on_after_commit = function(self)
luci.sys.exec("service watchcat reload")
end
s = m:section(TypedSection, "watchcat")
s.anonymous = true
s.addremove = true
function s.filter(self, section)
return self.map:get(section, "mode") == "restart_iface"
end
-- 重启接口模式
mode = s:option(ListValue, "mode",
translate("Mode"),
translate("Restart Interface: Restart a network interface if a ping to a specified host fails for a specified duration of time."))
mode:value("restart_iface", translate("Restart Interface"))
mode.default = "restart_iface"
-- 周期
period = s:option(Value, "period",
translate("Period"),
translate("In Periodic Reboot mode, it defines how often to reboot. <br /> \
In Ping Reboot mode, it defines the longest period of \
time without a reply from the Host To Check before a reboot is engaged. <br /> \
In Network Restart or Run Script mode, it defines the longest period of \
time without a reply from the Host to Check before the interface is restarted or the script is run. \
<br /><br />The default unit is seconds, without a suffix, but you can use the \
suffix <b>m</b> for minutes, <b>h</b> for hours or <b>d</b> \
for days. <br /><br />Examples:<ul><li>10 seconds would be: <b>10</b> or <b>10s</b></li><li>5 minutes would be: <b>5m</b></li><li> \
1 hour would be: <b>1h</b></li><li>1 week would be: <b>7d</b></li><ul>"))
period.default = '6h'
-- ping 主机
pinghosts = s:option(Value, "pinghosts",
translate("Host To Check"),
translate("IP address or hostname to ping."))
pinghosts.datatype = "host(1)"
pinghosts.default = "8.8.8.8"
-- ping 地址簇
addressfamily = s:option(ListValue, 'addressfamily',
translate('Address family for pinging the host'))
addressfamily:value("any", "any");
addressfamily:value("ipv4", "ipv4");
addressfamily:value("ipv6", "ipv6");
addressfamily.default = "any";
-- ping周期
pingperiod = s:option(Value, "pingperiod",
translate("Check Interval"),
translate("How often to ping the host specified above. \
<br /><br />The default unit is seconds, without a suffix, but you can use the suffix <b>m</b> for minutes, <b>h</b> for hours or <b>d</b> for days. <br /><br /> \
Examples:<ul><li>10 seconds would be: <b>10</b> or <b>10s</b></li><li>5 minutes would be: <b>5m</b></li><li>1 hour would be: <b>1h</b></li><li>1 week would be: <b>7d</b></li><ul>"))
pingperiod.default = "30s"
-- ping 包大小
pingsize = s:option(ListValue, 'pingsize', translate('Ping Packet Size'));
pingsize:value('small', translate('Small: 1 byte'));
pingsize:value('windows', translate('Windows: 32 bytes'));
pingsize:value('standard', translate('Standard: 56 bytes'));
pingsize:value('big', translate('Big: 248 bytes'));
pingsize:value('huge', translate('Huge: 1492 bytes'));
pingsize:value('jumbo', translate('Jumbo: 9000 bytes'));
pingsize.default = 'standard';
-- 接口
interface = s:option(Value, "interface",
translate('Restart Interface'),
translate("Interface to monitor and/or restart.<br/><br/><i>Applies to Ping Reboot, Restart Interface, and Run Script modes</i> <br /> Specify the interface to monitor and react if a ping over it fails.")
);
device_table = luci.sys.net.devices();
if device_table ~= nil then
for k, v in ipairs(device_table) do
if v ~= "lo" then
interface:value(v, v)
end
end
end
mmifacename = s:option(Value, 'mmifacename',
translate('Name of ModemManager Interface'),
translate("Applies to Ping Reboot and Restart Interface modes</i> <br /> If using ModemManager, \
you can have Watchcat restart your ModemManger interface by specifying its name."));
mmifacename.rmempty = true;
mmifacename.optional = true;
device_info = luci.sys.net.devices();
if device_info ~= nil then
for k, v in ipairs(device_info) do
if v ~= "lo" then
mmifacename:value(k, v)
end
end
end
luci.tools.webadmin.cbi_add_networks(mmifacename)
unlockbands = s:option(Value, 'unlockbands',
translate('Unlock Modem Bands'),
translate('If using ModemManager, then before restarting the interface, set the modem to be allowed to use any band.'));
unlockbands.default = '0';
return m

View File

@ -0,0 +1,92 @@
m = Map("watchcat",
"",
translate("Here you can set up several checks and actions to take in the event that a host becomes unreachable. \
Click the <b>Add</b> button at the bottom to set up more than one action."
))
m.on_after_commit = function(self)
luci.sys.exec("service watchcat reload")
end
s = m:section(TypedSection, "watchcat")
s.anonymous = true
s.addremove = true
function s.filter(self, section)
return self.map:get(section, "mode") == "run_script"
end
-- 运行脚本模式
mode = s:option(ListValue, "mode",
translate("Mode"),
translate("Run Script: Run a script if a ping to a specified host fails for a specified duration of time."))
mode:value("run_script", translate("Run Script"))
mode.default = "run_script"
-- 运行脚本
script = s:option(Value, "script", translate("Script to run"))
script.datatype = "file"
script.default = "/etc/watchcat.user.sh"
script.description = translate("Script to run when the host has not responded for the specified duration of " ..
"time. The script is passed the interface name as $1")
-- 周期
period = s:option(Value, "period",
translate("Period"),
translate("In Periodic Reboot mode, it defines how often to reboot. <br /> \
In Ping Reboot mode, it defines the longest period of \
time without a reply from the Host To Check before a reboot is engaged. <br /> \
In Network Restart or Run Script mode, it defines the longest period of \
time without a reply from the Host to Check before the interface is restarted or the script is run. \
<br /><br />The default unit is seconds, without a suffix, but you can use the \
suffix <b>m</b> for minutes, <b>h</b> for hours or <b>d</b> \
for days. <br /><br />Examples:<ul><li>10 seconds would be: <b>10</b> or <b>10s</b></li><li>5 minutes would be: <b>5m</b></li><li> \
1 hour would be: <b>1h</b></li><li>1 week would be: <b>7d</b></li><ul>"))
period.default = '6h'
-- ping 主机
pinghosts = s:option(Value, "pinghosts",
translate("Host To Check"),
translate("IP address or hostname to ping."))
pinghosts.datatype = "host(1)"
pinghosts.default = "8.8.8.8"
-- ping 地址簇
addressfamily = s:option(ListValue, 'addressfamily',
translate('Address family for pinging the host'))
addressfamily:value("any", "any");
addressfamily:value("ipv4", "ipv4");
addressfamily:value("ipv6", "ipv6");
addressfamily.default = "any";
-- ping周期
pingperiod = s:option(Value, "pingperiod",
translate("Check Interval"),
translate("How often to ping the host specified above. \
<br /><br />The default unit is seconds, without a suffix, but you can use the suffix <b>m</b> for minutes, <b>h</b> for hours or <b>d</b> for days. <br /><br /> \
Examples:<ul><li>10 seconds would be: <b>10</b> or <b>10s</b></li><li>5 minutes would be: <b>5m</b></li><li>1 hour would be: <b>1h</b></li><li>1 week would be: <b>7d</b></li><ul>"))
pingperiod.default = "30s"
-- ping 包大小
pingsize = s:option(ListValue, 'pingsize', translate('Ping Packet Size'));
pingsize:value('small', translate('Small: 1 byte'));
pingsize:value('windows', translate('Windows: 32 bytes'));
pingsize:value('standard', translate('Standard: 56 bytes'));
pingsize:value('big', translate('Big: 248 bytes'));
pingsize:value('huge', translate('Huge: 1492 bytes'));
pingsize:value('jumbo', translate('Jumbo: 9000 bytes'));
pingsize.default = 'standard';
-- 接口
interface = s:option(Value, "interface",
translate('Restart Interface'),
translate("Interface to monitor and/or restart.<br/><br/><i>Applies to Ping Reboot, Restart Interface, and Run Script modes</i> <br /> Specify the interface to monitor and react if a ping over it fails.")
);
device_table = luci.sys.net.devices();
if device_table ~= nil then
for k, v in ipairs(device_table) do
if v ~= "lo" then
interface:value(v, v)
end
end
end
return m

View File

@ -0,0 +1,12 @@
<%+cbi/valueheader%>
<textarea id="logview" class="cbi-input-textarea" style="width: 100%" rows="30" readonly="readonly"></textarea>
<script type="text/javascript">
const LOG_URL = '<%=luci.dispatcher.build_url("admin", "control", "watchcat-plus", "logread")%>';
XHR.get(LOG_URL, null, (x, data) => {
let logview = document.getElementById("logview");
logview.value = data
logview.scrollTop = logview.scrollHeight;
});
</script>
<%+cbi/valuefooter%>

View File

@ -0,0 +1,200 @@
#
# gngpp <gngppz@gmail.com>, 2023.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Weblate 4.6-dev\n"
msgid "Watchcat"
msgstr "Watchcat"
msgid "Periodic Reboot"
msgstr "定时重启"
msgid "Ping Reboot"
msgstr "Ping 重启"
msgid "Restart Interface"
msgstr "重启接口"
msgid "Run Script"
msgstr "执行脚本"
msgid ""
"Here you can set up several checks and actions to take in the event that a "
"host becomes unreachable. Click the <b>Add</b> button at the bottom to set "
"up more than one action."
msgstr "你可以在此处设置数个检查以及在特定主机变得不可访问时要采取的操作。点击底部的<"
"b>添加</b>按钮可以设置多条规则。"
msgid "Enabled"
msgstr "启用"
msgid "Mode"
msgstr "模式"
msgid "Periodic Reboot: Reboot this device after a specified interval of time."
msgstr "定时重启:在指定的时间间隔后重新启动本设备。"
msgid "Ping Reboot: Reboot this device if a ping to a specified host fails for a specified duration of time."
msgstr "Ping 重启如果在指定的时间内ping 指定主机始终失败,则重新启动本设备。"
msgid "Restart Interface: Restart a network interface if a ping to a specified host fails for a specified duration of time."
msgstr "重启接口如果在指定的时间内ping 指定主机始终失败,则重新启动特定网络接口。"
msgid "Run Script: Run a script if a ping to a specified host fails for a specified duration of time."
msgstr "执行脚本如果在指定的时间内ping 指定主机始终失败,则执行特定脚本。"
msgid "Script to run"
msgstr "要执行的脚本"
msgid ""
"Script to run when the host has not responded for the specified duration of "
"time. The script is passed the interface name as $1"
msgstr "当特定主机在指定的时间内未回复时要执行的脚本。脚本将接口名称作为 $1 传递"
msgid "Period"
msgstr "周期"
msgid ""
"In Periodic Reboot mode, it defines how often to reboot. <br /> In Ping "
"Reboot mode, it defines the longest period of time without a reply from the "
"Host To Check before a reboot is engaged. <br /> In Network Restart or Run "
"Script mode, it defines the longest period of time without a reply from the "
"Host to Check before the interface is restarted or the script is run. <br /"
"><br />The default unit is seconds, without a suffix, but you can use the "
"suffix <b>m</b> for minutes, <b>h</b> for hours or <b>d</b> for days. <br /"
"><br />Examples:<ul><li>10 seconds would be: <b>10</b> or <b>10s</b></"
"li><li>5 minutes would be: <b>5m</b></li><li> 1 hour would be: <b>1h</b></"
"li><li>1 week would be: <b>7d</b></li><ul>"
msgstr ""
"对于 定时重启 模式,它定义了重启的频率。<br />对于 Ping 重启 "
"模式,它定义了在重启前未收到来自要检查的主机的回复的最长时间。<br />对于 "
"重启接口 或 执行脚本 "
"模式,它定义了在重启接口或执行脚本前未收到要检查的主机的回复的最长时间。<br /"
"><br />默认单位是秒,不带后缀,但你可以使用后缀 <b>m</b> 代表分钟, <b>h</b> "
"代表小时或 <b>d</b> 代表天。<br /><br />示例:<ul><li>10秒是<b>10</b> 或 "
"<b>10s</b></li><li>5 分钟是:<b>5m</b></li><li>1 小时是:<b>1h</b></li><li>1 "
"周是:<b>7d</b></li><ul>"
msgid "Forced reboot delay"
msgstr "强制重启延时"
msgid "Host address to ping"
msgstr "要 ping 的主机地址"
msgid ""
"How often to check internet connection. Default unit is seconds, you can you "
"use the suffix 'm' for minutes, 'h' for hours or 'd' for days"
msgstr ""
"检测网络连接的频率。默认单位为秒您可以使用“m”作为后缀表示分钟“h”表示小"
"时“d”表示天"
msgid ""
"In periodic mode, it defines the reboot period. In internet mode, it defines "
"the longest period of time without internet access before a reboot is "
"engaged.Default unit is seconds, you can use the suffix 'm' for minutes, 'h' "
"for hours or 'd' for days"
msgstr ""
"在周期模式下,此处定义了重启的周期。在联网模式下,这个表示没有网络连接情况下"
"到执行重启的最长时间间隔。默认单位为秒您可以使用“m”作为后缀表示分钟“h”表"
"示小时“d”表示天"
msgid "Host To Check"
msgstr "要检查的主机"
msgid "IP address or hostname to ping."
msgstr "要 ping 的 IP 地址或主机名。"
msgid "Check Interval"
msgstr "检查间隔"
msgid ""
"How often to ping the host specified above. <br /><br />The default unit is "
"seconds, without a suffix, but you can use the suffix <b>m</b> for minutes, "
"<b>h</b> for hours or <b>d</b> for days. <br /><br /> Examples:<ul><li>10 "
"seconds would be: <b>10</b> or <b>10s</b></li><li>5 minutes would be: <b>5m</"
"b></li><li>1 hour would be: <b>1h</b></li><li>1 week would be: <b>7d</b></"
"li><ul>"
msgstr ""
"多长时间 ping 一次上面指定的主机。<br /><br />默认单位是秒,不带后缀,但你可"
"以使用后缀<b>m</b>代表分钟, <b>h</b>代表小时或<b>d</b>代表天数。<br /><br />"
"示例:<ul><li>10秒是<b>10</b> 或 <b>10s</b></li><li>5 分钟是:<b>5m</b></"
"li><li>1 小时是:<b>1h</b></li><li>1 周是:<b>7d</b></li><ul>"
msgid "Address family for pinging the host"
msgstr "Ping 主机的地址簇"
msgid "Ping Packet Size"
msgstr "Ping 包大小"
msgid "Small: 1 byte"
msgstr "小1 字节"
msgid "Standard: 56 bytes"
msgstr "标准56 字节"
msgid "Windows: 32 bytes"
msgstr "Windows32 字节"
msgid "Big: 248 bytes"
msgstr "大248 字节"
msgid "Huge: 1492 bytes"
msgstr "巨大1492 字节"
msgid "Jumbo: 9000 bytes"
msgstr "巨无霸9000 字节"
msgid "Forced reboot delay"
msgstr "强制重启延时"
msgid "Interface"
msgstr "接口"
msgid "Restart Interface"
msgstr "重启接口"
msgid "Force Reboot Delay"
msgstr "强制重启延迟"
msgid ""
"Applies to Ping Reboot and Periodic Reboot modes</i> <br /> When rebooting "
"the router, the service will trigger a soft reboot. Entering a non-zero "
"value here will trigger a delayed hard reboot if the soft reboot were to "
"fail. Enter the number of seconds to wait for the soft reboot to fail or use "
"0 to disable the forced reboot delay."
msgstr ""
"应用于 Ping 重启 和 定时重启 模式</i> <br />当重新启动路由器时,该服务将触发"
"软重启。如果软重启失败,在这里输入非零值将触发延迟的硬重启。输入等待软重启失"
"败的秒数或使用 0 来禁用强制重启延迟。"
msgid ""
"Interface to monitor and/or restart.<br/><br/><i>Applies to Ping Reboot, Restart Interface, and Run Script modes</i> <br /"
"> Specify the interface to monitor and react if a ping over it fails."
msgstr "要监视和/或重启的接口。<br/><br/><i>应用于 Ping重启、重启接口 和 执行脚本 模式</i> <br />指定要监视的接口并在 "
"ping 失败时做出反应。"
msgid "Name of ModemManager Interface"
msgstr "ModemManager 接口的名称"
msgid ""
"Applies to Ping Reboot and Restart Interface modes</i> <br /> If using "
"ModemManager, you can have Watchcat restart your ModemManger interface by "
"specifying its name."
msgstr ""
"应用于 Ping 重启 和 重启接口 模式</i> <br />如果使用 ModemManager你可以通过"
"指定名称让 Watchcat 重新启动你的 ModemManager 接口。"
msgid "Unlock Modem Bands"
msgstr "解锁调制解调器频段"
msgid ""
"If using ModemManager, then before restarting the interface, set the modem "
"to be allowed to use any band."
msgstr ""
"如果使用 ModemManager则在重新启动接口之前将调制解调器设置为允许使用任何频"
"段。"

View File

@ -0,0 +1,12 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@watchcat[-1]
add ucitrack watchcat
set ucitrack.@watchcat[-1].init=watchcat
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
rm -rf /tmp/luci-modulecache
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-watchcat-plus": {
"description": "Grant UCI access for luci-app-watchcat-plus",
"read": {
"uci": [ "watchcat-plus" ]
},
"write": {
"uci": [ "watchcat-plus" ]
}
}
}

48
watchcat/Makefile Normal file
View File

@ -0,0 +1,48 @@
#
# Copyright (C) 2010 segal.di.ubi.pt
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=watchcat
PKG_VERSION:=1
PKG_RELEASE:=17
PKG_MAINTAINER:=Roger D <rogerdammit@gmail.com>
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define Package/watchcat
SECTION:=utils
CATEGORY:=Utilities
TITLE:=Enable the configuration of programmed reboots or network interface restarts
PKGARCH:=all
endef
define Package/watchcat/description
Restart network interfaces or reboot if pings to hosts fail, or set up periodic reboots. Configured via UCI /etc/config/watchcat
endef
define Package/watchcat/conffiles
/etc/config/watchcat
endef
define Build/Compile
endef
define Package/watchcat/install
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/watchcat.init $(1)/etc/init.d/watchcat
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) ./files/watchcat.sh $(1)/usr/bin/watchcat.sh
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_DATA) ./files/watchcat.config $(1)/etc/config/watchcat
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_BIN) ./files/migrate-watchcat $(1)/etc/uci-defaults/migrate-watchcat
endef
$(eval $(call BuildPackage,watchcat))

View File

@ -0,0 +1,27 @@
#!/bin/sh
. /lib/functions.sh
upgrade_watchcat() {
local cfg="$1"
config_get period "$cfg" period
config_get mode "$cfg" mode
config_get pinghosts "$cfg" pinghosts
config_get forcedelay "$cfg" forcedelay
[ -f "/etc/config/watchcat" ] || touch /etc/config/watchcat
uci_add watchcat watchcat
uci_set watchcat @watchcat[-1] period "$period"
uci_set watchcat @watchcat[-1] mode "$mode"
uci_set watchcat @watchcat[-1] pinghosts "$pinghosts"
uci_set watchcat @watchcat[-1] forcedelay "$forcedelay"
uci_remove system "$cfg"
}
config_load system
config_foreach upgrade_watchcat watchcat
uci_commit watchcat
uci commit system

View File

@ -0,0 +1,5 @@
config watchcat
option period '6h'
option mode 'ping_reboot'
option pinghosts '8.8.8.8'
option forcedelay '30'

View File

@ -0,0 +1,136 @@
#!/bin/sh /etc/rc.common
USE_PROCD=1
START=97
STOP=01
append_string() {
varname="$1"
add="$2"
separator="${3:- }"
local actual
eval "actual=\$$varname"
new="${actual:+$actual$separator}$add"
eval "$varname=\$new"
}
time_to_seconds() {
time=$1
{ [ "$time" -ge 1 ] 2> /dev/null && seconds="$time"; } ||
{ [ "${time%s}" -ge 1 ] 2> /dev/null && seconds="${time%s}"; } ||
{ [ "${time%m}" -ge 1 ] 2> /dev/null && seconds=$((${time%m} * 60)); } ||
{ [ "${time%h}" -ge 1 ] 2> /dev/null && seconds=$((${time%h} * 3600)); } ||
{ [ "${time%d}" -ge 1 ] 2> /dev/null && seconds=$((${time%d} * 86400)); }
echo $seconds
unset seconds
unset time
}
config_watchcat() {
# Read config
config_get period "$1" period "120"
config_get mode "$1" mode "ping_reboot"
config_get pinghosts "$1" pinghosts "8.8.8.8"
config_get pingperiod "$1" pingperiod "60"
config_get forcedelay "$1" forcedelay "60"
config_get pingsize "$1" pingsize "standard"
config_get interface "$1" interface
config_get mmifacename "$1" mmifacename
config_get_bool unlockbands "$1" unlockbands "0"
config_get addressfamily "$1" addressfamily "any"
config_get script "$1" script
# Fix potential typo in mode and provide backward compatibility.
[ "$mode" = "allways" ] && mode="periodic_reboot"
[ "$mode" = "always" ] && mode="periodic_reboot"
[ "$mode" = "ping" ] && mode="ping_reboot"
# Checks for settings common to all operation modes
if [ "$mode" != "periodic_reboot" ] && [ "$mode" != "ping_reboot" ] && [ "$mode" != "restart_iface" ] && [ "$mode" != "run_script" ]; then
append_string "error" "mode must be 'periodic_reboot' or 'ping_reboot' or 'restart_iface' or 'run_script'" "; "
fi
period="$(time_to_seconds "$period")"
[ "$period" -ge 1 ] ||
append_string "error" "period has invalid format. Use time value(ex: '30'; '4m'; '6h'; '2d')" "; "
# ping_reboot mode and restart_iface mode specific checks
if [ "$mode" = "ping_reboot" ] || [ "$mode" = "restart_iface" ] || [ "$mode" = "run_script" ]; then
if [ -z "$error" ]; then
pingperiod_default="$((period / 5))"
pingperiod="$(time_to_seconds "$pingperiod")"
if [ "$pingperiod" -ge 0 ] && [ "$pingperiod" -ge "$period" ]; then
pingperiod="$(time_to_seconds "$pingperiod_default")"
append_string "warn" "pingperiod cannot be greater than $period. Defaulted to $pingperiod_default seconds (1/5 of period)" "; "
fi
if [ "$pingperiod" -lt 0 ]; then
append_string "warn" "pingperiod cannot be a negative value." "; "
fi
if [ "$mmifacename" != "" ] && [ "$period" -lt 30 ]; then
append_string "error" "Check interval is less than 30s. For robust operation with ModemManager modem interfaces it is recommended to set the period to at least 30s."
fi
fi
fi
if [ "$mode" = "run_script" ] && [ -z "$script" ]; then
append_string "error" "run_script mode requires a script"
fi
# ping_reboot mode and periodic_reboot mode specific checks
if [ "$mode" = "ping_reboot" ] || [ "$mode" = "periodic_reboot" ]; then
forcedelay="$(time_to_seconds "$forcedelay")"
fi
[ -n "$warn" ] && logger -p user.warn -t "watchcat" "$1: $warn"
[ -n "$error" ] && {
logger -p user.err -t "watchcat" "reboot program $1 not started - $error"
return
}
# Need to conditionally run mode functions because they have different signatures
case "$mode" in
periodic_reboot)
procd_open_instance "watchcat_${1}"
procd_set_param command /usr/bin/watchcat.sh "periodic_reboot" "$period" "$forcedelay"
procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}"
procd_close_instance
;;
ping_reboot)
procd_open_instance "watchcat_${1}"
procd_set_param command /usr/bin/watchcat.sh "ping_reboot" "$period" "$forcedelay" "$pinghosts" "$pingperiod" "$pingsize" "$addressfamily"
procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}"
procd_close_instance
;;
restart_iface)
procd_open_instance "watchcat_${1}"
procd_set_param command /usr/bin/watchcat.sh "restart_iface" "$period" "$pinghosts" "$pingperiod" "$pingsize" "$interface" "$mmifacename" "$unlockbands" "$addressfamily"
procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}"
procd_close_instance
;;
run_script)
procd_open_instance "watchcat_${1}"
procd_set_param command /usr/bin/watchcat.sh "run_script" "$period" "$pinghosts" "$pingperiod" "$pingsize" "$interface" "$addressfamily" "$script"
procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}"
procd_close_instance
;;
*)
echo "Error starting Watchcat service. Invalid mode selection: $mode"
;;
esac
}
start_service() {
config_load watchcat
config_foreach config_watchcat watchcat
}
service_triggers() {
procd_add_reload_trigger "watchcat"
}

269
watchcat/files/watchcat.sh Normal file
View File

@ -0,0 +1,269 @@
#!/bin/sh
#
# Copyright (C) 2010 segal.di.ubi.pt
# Copyright (C) 2020 nbembedded.com
#
# This is free software, licensed under the GNU General Public License v2.
#
get_ping_size() {
ps=$1
case "$ps" in
small)
ps="1"
;;
windows)
ps="32"
;;
standard)
ps="56"
;;
big)
ps="248"
;;
huge)
ps="1492"
;;
jumbo)
ps="9000"
;;
*)
echo "Error: invalid ping_size. ping_size should be either: small, windows, standard, big, huge or jumbo" 1>&2
echo "Corresponding ping packet sizes (bytes): small=1, windows=32, standard=56, big=248, huge=1492, jumbo=9000" 1>&2
;;
esac
echo $ps
}
get_ping_family_flag() {
family=$1
case "$family" in
any)
family=""
;;
ipv4)
family="-4"
;;
ipv6)
family="-6"
;;
*)
echo "Error: invalid address_family \"$family\". address_family should be one of: any, ipv4, ipv6" 1>&2
;;
esac
echo $family
}
reboot_now() {
reboot &
[ "$1" -ge 1 ] && {
sleep "$1"
echo 1 > /proc/sys/kernel/sysrq
echo b > /proc/sysrq-trigger # Will immediately reboot the system without syncing or unmounting your disks.
}
}
watchcat_periodic() {
failure_period="$1"
force_reboot_delay="$2"
sleep "$failure_period" && reboot_now "$force_reboot_delay"
}
watchcat_restart_modemmanager_iface() {
[ "$2" -gt 0 ] && {
logger -p daemon.info -t "watchcat[$$]" "Resetting current-bands to 'any' on modem: \"$1\" now."
/usr/bin/mmcli -m any --set-current-bands=any
}
logger -p daemon.info -t "watchcat[$$]" "Reconnecting modem: \"$1\" now."
/etc/init.d/modemmanager restart
ifup "$1"
}
watchcat_restart_network_iface() {
logger -p daemon.info -t "watchcat[$$]" "Restarting network interface: \"$1\"."
ip link set "$1" down
ip link set "$1" up
}
watchcat_run_script() {
logger -p daemon.info -t "watchcat[$$]" "Running script \"$1\" for network interface: \"$2\"."
"$1" "$2"
}
watchcat_restart_all_network() {
logger -p daemon.info -t "watchcat[$$]" "Restarting networking now by running: /etc/init.d/network restart"
/etc/init.d/network restart
}
watchcat_monitor_network() {
failure_period="$1"
ping_hosts="$2"
ping_frequency_interval="$3"
ping_size="$4"
iface="$5"
mm_iface_name="$6"
mm_iface_unlock_bands="$7"
address_family="$8"
script="$9"
time_now="$(cat /proc/uptime)"
time_now="${time_now%%.*}"
[ "$time_now" -lt "$failure_period" ] && sleep "$((failure_period - time_now))"
time_now="$(cat /proc/uptime)"
time_now="${time_now%%.*}"
time_lastcheck="$time_now"
time_lastcheck_withinternet="$time_now"
ping_size="$(get_ping_size "$ping_size")"
ping_family="$(get_ping_family_flag "$address_family")"
while true; do
# account for the time ping took to return. With a ping time of 5s, ping might take more than that, so it is important to avoid even more delay.
time_now="$(cat /proc/uptime)"
time_now="${time_now%%.*}"
time_diff="$((time_now - time_lastcheck))"
[ "$time_diff" -lt "$ping_frequency_interval" ] && sleep "$((ping_frequency_interval - time_diff))"
time_now="$(cat /proc/uptime)"
time_now="${time_now%%.*}"
time_lastcheck="$time_now"
for host in $ping_hosts; do
if [ "$iface" != "" ]; then
ping_result="$(
ping $ping_family -I "$iface" -s "$ping_size" -c 1 "$host" &> /dev/null
echo $?
)"
else
ping_result="$(
ping $ping_family -s "$ping_size" -c 1 "$host" &> /dev/null
echo $?
)"
fi
if [ "$ping_result" -eq 0 ]; then
time_lastcheck_withinternet="$time_now"
else
if [ "$script" != "" ]; then
logger -p daemon.info -t "watchcat[$$]" "Could not reach $host via \"$iface\" for \"$((time_now - time_lastcheck_withinternet))\" seconds. Running script after reaching \"$failure_period\" seconds"
elif [ "$iface" != "" ]; then
logger -p daemon.info -t "watchcat[$$]" "Could not reach $host via \"$iface\" for \"$((time_now - time_lastcheck_withinternet))\" seconds. Restarting \"$iface\" after reaching \"$failure_period\" seconds"
else
logger -p daemon.info -t "watchcat[$$]" "Could not reach $host for \"$((time_now - time_lastcheck_withinternet))\" seconds. Restarting networking after reaching \"$failure_period\" seconds"
fi
fi
done
[ "$((time_now - time_lastcheck_withinternet))" -ge "$failure_period" ] && {
if [ "$script" != "" ]; then
watchcat_run_script "$script" "$iface"
else
if [ "$mm_iface_name" != "" ]; then
watchcat_restart_modemmanager_iface "$mm_iface_name" "$mm_iface_unlock_bands"
fi
if [ "$iface" != "" ]; then
watchcat_restart_network_iface "$iface"
else
watchcat_restart_all_network
fi
fi
/etc/init.d/watchcat start
# Restart timer cycle.
time_lastcheck_withinternet="$time_now"
}
done
}
watchcat_ping() {
failure_period="$1"
force_reboot_delay="$2"
ping_hosts="$3"
ping_frequency_interval="$4"
ping_size="$5"
address_family="$6"
time_now="$(cat /proc/uptime)"
time_now="${time_now%%.*}"
[ "$time_now" -lt "$failure_period" ] && sleep "$((failure_period - time_now))"
time_now="$(cat /proc/uptime)"
time_now="${time_now%%.*}"
time_lastcheck="$time_now"
time_lastcheck_withinternet="$time_now"
ping_size="$(get_ping_size "$ping_size")"
ping_family="$(get_ping_family_flag "$address_family")"
while true; do
# account for the time ping took to return. With a ping time of 5s, ping might take more than that, so it is important to avoid even more delay.
time_now="$(cat /proc/uptime)"
time_now="${time_now%%.*}"
time_diff="$((time_now - time_lastcheck))"
[ "$time_diff" -lt "$ping_frequency_interval" ] && sleep "$((ping_frequency_interval - time_diff))"
time_now="$(cat /proc/uptime)"
time_now="${time_now%%.*}"
time_lastcheck="$time_now"
for host in $ping_hosts; do
if [ "$iface" != "" ]; then
ping_result="$(
ping $ping_family -I "$iface" -s "$ping_size" -c 1 "$host" &> /dev/null
echo $?
)"
else
ping_result="$(
ping $ping_family -s "$ping_size" -c 1 "$host" &> /dev/null
echo $?
)"
fi
if [ "$ping_result" -eq 0 ]; then
time_lastcheck_withinternet="$time_now"
else
logger -p daemon.info -t "watchcat[$$]" "Could not reach $host for $((time_now - time_lastcheck_withinternet)). Rebooting after reaching $failure_period"
fi
done
[ "$((time_now - time_lastcheck_withinternet))" -ge "$failure_period" ] && reboot_now "$force_reboot_delay"
done
}
mode="$1"
# Fix potential typo in mode and provide backward compatibility.
[ "$mode" = "allways" ] && mode="periodic_reboot"
[ "$mode" = "always" ] && mode="periodic_reboot"
[ "$mode" = "ping" ] && mode="ping_reboot"
case "$mode" in
periodic_reboot)
# args from init script: period forcedelay
watchcat_periodic "$2" "$3"
;;
ping_reboot)
# args from init script: period forcedelay pinghosts pingperiod pingsize addressfamily
watchcat_ping "$2" "$3" "$4" "$5" "$6" "$7"
;;
restart_iface)
# args from init script: period pinghosts pingperiod pingsize interface mmifacename unlockbands addressfamily
watchcat_monitor_network "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" ""
;;
run_script)
# args from init script: period pinghosts pingperiod pingsize interface addressfamily script
watchcat_monitor_network "$2" "$3" "$4" "$5" "$6" "" "" "$7" "$8"
;;
*)
echo "Error: invalid mode selected: $mode"
;;
esac