diff --git a/luci-app-serverchan/Makefile b/luci-app-serverchan/Makefile index 9d81d36e..993edaee 100644 --- a/luci-app-serverchan/Makefile +++ b/luci-app-serverchan/Makefile @@ -1,23 +1,23 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-serverchan -PKG_VERSION:=2.02.1 -PKG_RELEASE:=10 - -PKG_MAINTAINER:=tty228 - -LUCI_TITLE:=LuCI support for serverchan -LUCI_PKGARCH:=all -LUCI_DEPENDS:=+iputils-arping +curl +jq - -define Package/$(PKG_NAME)/conffiles -/etc/config/serverchan -/usr/share/serverchan/api/diy.json -/usr/share/serverchan/api/logo.jpg -/usr/share/serverchan/api/ipv4.list -/usr/share/serverchan/api/ipv6.list -endef - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-serverchan +PKG_VERSION:=2.02.0 +PKG_RELEASE:=9 + +PKG_MAINTAINER:=tty228 + +LUCI_TITLE:=LuCI support for serverchan +LUCI_PKGARCH:=all +LUCI_DEPENDS:=+iputils-arping +curl +jq + +define Package/$(PKG_NAME)/conffiles +/etc/config/serverchan +/usr/bin/serverchan/api/diy.json +/usr/bin/serverchan/api/logo.jpg +/usr/bin/serverchan/api/ipv4.list +/usr/bin/serverchan/api/ipv6.list +endef + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-serverchan/README.md b/luci-app-serverchan/README.md index 18d6bbe6..1f043aa6 100644 --- a/luci-app-serverchan/README.md +++ b/luci-app-serverchan/README.md @@ -1,49 +1,49 @@ -# 简介 -- 用于 OpenWRT/LEDE 路由器上进行 微信/Telegram 推送的插件 -- 支持列表: -- 微信推送/Server酱 https://sct.ftqq.com/ -- 企业微信/应用推送 https://work.weixin.qq.com/api/doc/90000/90135/90248 -- 微信推送/WxPusher https://wxpusher.zjiecode.com/docs -- 微信推送/推送加 http://www.pushplus.plus/ -- Telegram/BotFather https://t.me/BotFather -- 精力有限,如需要钉钉推送、飞书推送、Bark推送等请尝试 https://github.com/zzsj0928/luci-app-pushbot -- **基于 x86 OpenWrt 19.07.8 制作,不同系统不同设备,请自行修改部分代码,无测试条件无法重现的 bug 不考虑修复** -- 依赖 iputils-arping + curl + jq 命令,安装前请 `opkg update`,小内存路由谨慎安装 -- 使用主动探测设备连接的方式检测设备在线状态,以避免 Wi-Fi 休眠机制,主动探测较为耗时,**如遇设备休眠频繁,请自行调整超时设置** -- 流量统计功能依赖 wrtbwmon ,自行选装或编译,该插件与 Routing/NAT 、Flow Offloading 冲突,开启无法获取流量,自行选择 - -#### 主要功能 -- 路由 IP/IPv6 变动推送 -- 设备别名 -- 设备上线推送 -- 设备离线推送及流量使用情况 -- CPU 负载、温度监视 -- 定时推送设备运行状态 -- MAC 白名单、黑名单、按接口检测设备 -- 免打扰 -- 无人值守任务 - -#### 已知问题 -- 直接关闭接口时,该接口的离线设备会忽略检测 -- 部分设备无法读取到设备名,脚本使用 `cat /tmp/dhcp.leases` 命令读取设备名,如果 DHCP 中不存在设备名,则无法读取设备名(如二级路由设备、静态IP设备),请使用设备名备注. -- 基于X86 OpenWrt 19.07.8 制作,不同系统不同设备,可能会遇到各种问题 -- 潘多拉系统、或不支持 sh 的系统,请将脚本开头 `#!/bin/sh` 改为 `#!/bin/bash`,或手动安装 `sh` - -# Download -- [luci-app-serverchan](https://github.com/tty228/luci-app-serverchan/releases) -- [wrtbwmon](https://github.com/brvphoenix/wrtbwmon) -- [luci-app-wrtbwmon](https://github.com/brvphoenix/luci-app-wrtbwmon) -- **L大版本直接编译 luci-app-wrtbwmon ,非原版 LuCI 如使用以上 wrtbwmon,请注意安装版本号** - -#### PS -- 新功能看情况开发,忙得头晕眼花 -- 欢迎各种代码提交 -- 提交bug时请尽量带上设备信息,日志与描述 -(如执行 `/usr/share/serverchan/serverchan` 后的提示、日志信息、/tmp/serverchan/ipAddress 文件信息、或尝试使用 sh -x /usr/share/serverchan/serverchan 查看详细运行信息 ) -- 三言两句恕我无能为力 - -# Donate -如果你觉得此项目对你有帮助,请捐助我们,以使项目能持续发展,更加完善。 - -![image](https://github.com/tty228/Python-100-Days/blob/master/res/WX.jpg) - +# 简介 +- 用于 OpenWRT/LEDE 路由器上进行 微信/Telegram 推送的插件 +- 支持列表: +- 微信推送/Server酱 https://sct.ftqq.com/ +- 企业微信/应用推送 https://work.weixin.qq.com/api/doc/90000/90135/90248 +- 微信推送/WxPusher https://wxpusher.zjiecode.com/docs +- 微信推送/推送加 http://www.pushplus.plus/ +- Telegram/BotFather https://t.me/BotFather +- 精力有限,如需要钉钉推送、飞书推送、Bark推送等请尝试 https://github.com/zzsj0928/luci-app-pushbot +- **基于 x86 OpenWrt 19.07.8 制作,不同系统不同设备,请自行修改部分代码,无测试条件无法重现的 bug 不考虑修复** +- 依赖 iputils-arping + curl + jq 命令,安装前请 `opkg update`,小内存路由谨慎安装 +- 使用主动探测设备连接的方式检测设备在线状态,以避免 Wi-Fi 休眠机制,主动探测较为耗时,**如遇设备休眠频繁,请自行调整超时设置** +- 流量统计功能依赖 wrtbwmon ,自行选装或编译,该插件与 Routing/NAT 、Flow Offloading 冲突,开启无法获取流量,自行选择 + +#### 主要功能 +- 路由 IP/IPv6 变动推送 +- 设备别名 +- 设备上线推送 +- 设备离线推送及流量使用情况 +- CPU 负载、温度监视 +- 定时推送设备运行状态 +- MAC 白名单、黑名单、按接口检测设备 +- 免打扰 +- 无人值守任务 + +#### 已知问题 +- 直接关闭接口时,该接口的离线设备会忽略检测 +- 部分设备无法读取到设备名,脚本使用 `cat /tmp/dhcp.leases` 命令读取设备名,如果 DHCP 中不存在设备名,则无法读取设备名(如二级路由设备、静态IP设备),请使用设备名备注. +- 基于X86 OpenWrt 19.07.8 制作,不同系统不同设备,可能会遇到各种问题 +- 潘多拉系统、或不支持 sh 的系统,请将脚本开头 `#!/bin/sh` 改为 `#!/bin/bash`,或手动安装 `sh` + +# Download +- [luci-app-serverchan](https://github.com/tty228/luci-app-serverchan/releases) +- [wrtbwmon](https://github.com/brvphoenix/wrtbwmon) +- [luci-app-wrtbwmon](https://github.com/brvphoenix/luci-app-wrtbwmon) +- **L大版本直接编译 luci-app-wrtbwmon ,非原版 LuCI 如使用以上 wrtbwmon,请注意安装版本号** + +#### PS +- 新功能看情况开发,忙得头晕眼花 +- 欢迎各种代码提交 +- 提交bug时请尽量带上设备信息,日志与描述 +(如执行 `/usr/bin/serverchan/serverchan` 后的提示、日志信息、/tmp/serverchan/ipAddress 文件信息、或尝试使用 sh -x /usr/bin/serverchan/serverchan 查看详细运行信息 ) +- 三言两句恕我无能为力 + +# Donate +如果你觉得此项目对你有帮助,请捐助我们,以使项目能持续发展,更加完善。 + +![image](https://github.com/tty228/Python-100-Days/blob/master/res/WX.jpg) + diff --git a/luci-app-serverchan/luasrc/controller/serverchan.lua b/luci-app-serverchan/luasrc/controller/serverchan.lua index 8e522c8a..aa612c88 100644 --- a/luci-app-serverchan/luasrc/controller/serverchan.lua +++ b/luci-app-serverchan/luasrc/controller/serverchan.lua @@ -1,34 +1,34 @@ -module("luci.controller.serverchan", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/serverchan") then - return - end - - local page = entry({"admin", "services", "serverchan"}, alias("admin", "services", "serverchan", "setting"), _("微信推送"), 30) - page.dependent = true - page.acl_depends = { "luci-app-serverchan" } - - entry({"admin", "services", "serverchan", "setting"}, cbi("serverchan/setting"), _("配置"), 40).leaf = true - entry({"admin", "services", "serverchan", "advanced"}, cbi("serverchan/advanced"), _("高级设置"), 50).leaf = true - entry({"admin", "services", "serverchan", "client"}, form("serverchan/client"), _("在线设备"), 80) - entry({"admin", "services", "serverchan", "log"}, form("serverchan/log"), _("日志"), 99).leaf = true - entry({"admin", "services", "serverchan", "get_log"}, call("get_log")).leaf = true - entry({"admin", "services", "serverchan", "clear_log"}, call("clear_log")).leaf = true - entry({"admin", "services", "serverchan", "status"}, call("act_status")).leaf = true -end - -function act_status() - local e = {} - e.running = luci.sys.call("busybox ps|grep -v grep|grep -c serverchan >/dev/null") == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end - -function get_log() - luci.http.write(luci.sys.exec("[ -f '/tmp/serverchan/serverchan.log' ] && cat /tmp/serverchan/serverchan.log")) -end - -function clear_log() - luci.sys.call("echo '' > /tmp/serverchan/serverchan.log") -end +module("luci.controller.serverchan", package.seeall) + +function index() + if not nixio.fs.access("/etc/config/serverchan") then + return + end + + local page = entry({"admin", "services", "serverchan"}, alias("admin", "services", "serverchan", "setting"), _("微信推送"), 30) + page.dependent = true + page.acl_depends = { "luci-app-serverchan" } + + entry({"admin", "services", "serverchan", "setting"}, cbi("serverchan/setting"), _("配置"), 40).leaf = true + entry({"admin", "services", "serverchan", "advanced"}, cbi("serverchan/advanced"), _("高级设置"), 50).leaf = true + entry({"admin", "services", "serverchan", "client"}, form("serverchan/client"), _("在线设备"), 80) + entry({"admin", "services", "serverchan", "log"}, form("serverchan/log"), _("日志"), 99).leaf = true + entry({"admin", "services", "serverchan", "get_log"}, call("get_log")).leaf = true + entry({"admin", "services", "serverchan", "clear_log"}, call("clear_log")).leaf = true + entry({"admin", "services", "serverchan", "status"}, call("act_status")).leaf = true +end + +function act_status() + local e = {} + e.running = luci.sys.call("busybox ps|grep -v grep|grep -c serverchan >/dev/null") == 0 + luci.http.prepare_content("application/json") + luci.http.write_json(e) +end + +function get_log() + luci.http.write(luci.sys.exec("[ -f '/tmp/serverchan/serverchan.log' ] && cat /tmp/serverchan/serverchan.log")) +end + +function clear_log() + luci.sys.call("echo '' > /tmp/serverchan/serverchan.log") +end diff --git a/luci-app-serverchan/luasrc/model/cbi/serverchan/advanced.lua b/luci-app-serverchan/luasrc/model/cbi/serverchan/advanced.lua index f6a28570..15753649 100644 --- a/luci-app-serverchan/luasrc/model/cbi/serverchan/advanced.lua +++ b/luci-app-serverchan/luasrc/model/cbi/serverchan/advanced.lua @@ -1,166 +1,166 @@ -local nt = require "luci.sys".net -local fs = require "nixio.fs" - -m = Map("serverchan", translate("提示:")) -m.description = translate("如果你不了解这些选项的含义,请不要修改这些选项") - -s = m:section(TypedSection, "serverchan", "高级设置") -s.anonymous = true -s.addremove = false - -a = s:option(Value, "up_timeout", translate('设备上线检测超时(s)')) -a.default = "2" -a.optional = false -a.datatype = "uinteger" - -a = s:option(Value, "down_timeout", translate('设备离线检测超时(s)')) -a.default = "20" -a.optional = false -a.datatype = "uinteger" - -a = s:option(Value, "timeout_retry_count", translate('离线检测次数')) -a.default = "2" -a.optional = false -a.datatype = "uinteger" -a.description = translate("若无二级路由设备,信号强度良好,可以减少以上数值
因夜间 wifi 休眠较为玄学,遇到设备频繁推送断开,烦请自行调整参数
..╮(╯_╰)╭..") - -a = s:option(Value, "thread_num", translate('最大并发进程数')) -a.default = "3" -a.datatype = "uinteger" - -a = s:option(Value, "soc_code", "自定义温度读取命令") -a.rmempty = true -a:value("", translate("默认")) -a:value("pve", translate("PVE 虚拟机")) -a.description = translate("自定义命令如需使用特殊符号,如引号、$、!等,则需要自行转义,并在保存后查看 /etc/config/serverchan 文件 soc_code 设置项是否保存正确
可以使用 eval `echo $(uci get serverchan.serverchan.soc_code)` 命令查看命令输出及错误信息
执行结果需为纯数字(可带小数),用于温度对比") - -a = s:option(Value, "server_host", translate("宿主机地址")) -a.rmempty = true -a.default = "10.0.0.2" -a.description = translate("") -a:depends({soc_code = "pve"}) - -a = s:option(Value, "server_port", translate("宿主机 SSH 端口")) -a.rmempty = true -a.default = "22" -a.description = translate("SSH 端口默认为 22,如有自定义,请填写自定义 SSH 端口
请确认已经设置好密钥登陆,否则会引起脚本无法运行等错误!
PVE 安装 sensors 命令自行百度
密钥登陆例(自行修改地址与端口号):
opkg update #更新列表
opkg install openssh-client openssh-keygen #安装openssh客户端
echo -e \"\\n\" | ssh-keygen -t rsa # 生成密钥文件(空密码)
pve_host=`uci get serverchan.serverchan.server_host` || pve_host=\"10.0.0.3\" # 读取配置文件中的 pve 主机地址,如果不存在请自行填写
pve_port=`uci get serverchan.serverchan.server_port` || pve_host=\"22\" # 读取配置文件中的 pve 主机 ssh 端口号,,如果不存在请自行填写
ssh root@${pve_host} -p ${pve_port} \"tee -a ~/.ssh/id_rsa.pub\" < ~/.ssh/id_rsa.pub # 传送公钥到 PVE
ssh root@${pve_host} -p ${pve_port} \"cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys\" # 写入公钥到 PVE
ssh -i /root/.ssh/id_rsa root@${pve_host} -p ${pve_port} sensors # 使用私钥连接 PVE 测试温度命令
刷机党自行将 /root/.ssh/ 加入备份列表,避免重复操作") -a:depends({soc_code = "pve"}) - -a = s:option(Button, "soc", translate("测试温度命令")) -a.inputtitle = translate("输出信息") -a.write = function() - luci.sys.call("/usr/share/serverchan/serverchan soc") - luci.http.redirect(luci.dispatcher.build_url("admin", "services", "serverchan", "advanced")) -end - -if nixio.fs.access("/tmp/serverchan/soc_tmp") then -e = s:option(TextValue,"soc_tmp") -e.rows = 2 -e.readonly = true -e.cfgvalue = function() - return luci.sys.exec("cat /tmp/serverchan/soc_tmp && rm -f /tmp/serverchan/soc_tmp") -end -end - -a = s:option(Flag, "gateway_info_enable", translate("从光猫获取主机名等信息")) -a.default = 0 -a.rmempty = true -a.description = translate("适用于 OpenWrt 作为透明网关,无法获取设备主机名及完整的局域网设备列表时
仅测试通过 HG5143F 天翼网关,不保证通用性") - -a = s:option(Value, "gateway_host_url", translate('光猫登录地址 URL')) -a.rmempty = true -a.default = "http://192.168.1.1/cgi-bin/luci" -a:depends({gateway_info_enable = "1"}) - -a = s:option(Value, "gateway_info_url", translate('设备列表 JSON URL')) -a.rmempty = true -a.default = "http://192.168.1.1/cgi-bin/luci/admin/allInfo" -a:depends({gateway_info_enable = "1"}) - -a = s:option(Value, "gateway_logout_url", translate('光猫注销登录 URL')) -a.rmempty = true -a.default = "http://192.168.1.1/cgi-bin/luci/admin/logout" -a.description = translate("使用 F12 控制台自行抓取") -a:depends({gateway_info_enable = "1"}) - -a = s:option(Value, "gateway_username_id", translate('登录页面帐号输入框 ID')) -a.rmempty = true -a.default = "username" -a:depends({gateway_info_enable = "1"}) - -a = s:option(Value, "gateway_password_id", translate('登录页面密码输入框 ID')) -a.rmempty = true -a.default = "psd" -a.description = translate("浏览器右键-检查元素") -a:depends({gateway_info_enable = "1"}) - -a = s:option(Value, "gateway_username", translate('光猫登录帐号')) -a.rmempty = true -a.default = "useradmin" -a:depends({gateway_info_enable = "1"}) - -a = s:option(Value, "gateway_password", translate('光猫登录密码')) -a.rmempty = true -a.description = translate("使用普通账号即可,不需要超密") -a:depends({gateway_info_enable = "1"}) - -a = s:option(Flag, "err_enable", translate("无人值守任务")) -a.default = 0 -a.rmempty = true -a.description = translate("请确认脚本可以正常运行,否则可能造成频繁重启等错误!") - -a = s:option(Flag, "err_sheep_enable", translate("仅在免打扰时段重拨")) -a.default = 0 -a.rmempty = true -a.description = translate("避免白天重拨 DDNS 域名等待解析,此功能不影响断网检测
因夜间跑流量问题,该功能可能不稳定") -a:depends({err_enable = "1"}) - -a = s:option(DynamicList, "err_device_aliases", translate("关注列表")) -a.rmempty = true -a.description = translate("只会在列表中设备都不在线时才会执行
免打扰时段一小时后,关注设备五分钟低流量(约100kb/m)将视为离线") -nt.mac_hints(function(mac, name) a :value(mac, "%s (%s)" %{ mac, name }) end) -a:depends({err_enable = "1"}) - -a = s:option(ListValue, "network_err_event", translate("网络断开时")) -a.default = "" -a:depends({err_enable = "1"}) -a:value("", translate("无操作")) -a:value("1", translate("重启路由器")) -a:value("2", translate("重新拨号")) -a:value("3", translate("修改相关设置项,尝试自动修复网络")) -a.description = translate("选项 1 选项 2 不会修改设置,并最多尝试 2 次。
选项 3 会将设置项备份于 /usr/share/serverchan/configbak 目录,并在失败后还原。
【!!无法保证兼容性!!】不熟悉系统设置项,不会救砖请勿使用") - -a = s:option(ListValue, "system_time_event", translate("定时重启")) -a.default = "" -a:depends({err_enable = "1"}) -a:value("", translate("无操作")) -a:value("1", translate("重启路由器")) -a:value("2", translate("重新拨号")) - -a = s:option(Value, "autoreboot_time", "系统运行时间大于") -a.rmempty = true -a.default = "24" -a.datatype = "uinteger" -a:depends({system_time_event = "1"}) -a.description = translate("单位为小时") - -a = s:option(Value, "network_restart_time", "网络在线时间大于") -a.rmempty = true -a.default = "24" -a.datatype = "uinteger" -a:depends({system_time_event = "2"}) -a.description = translate("单位为小时") - -a = s:option(Flag, "public_ip_event", translate("重拨尝试获取公网 IP")) -a.default = 0 -a.rmempty = true -a:depends({err_enable = "1"}) -a.description = translate("重拨时不会推送 IP 变动通知,并会导致你的域名无法及时更新 IP 地址
请确认你可以通过重拨获取公网 IP,否则这不仅徒劳无功还会引起频繁断网
移动等大内网你就别挣扎了!!") - -a = s:option(Value, "public_ip_retry_count", "当天最大重试次数") -a.rmempty = true -a.default = "10" -a.datatype = "uinteger" -a:depends({public_ip_event = "1"}) - -return m +local nt = require "luci.sys".net +local fs = require "nixio.fs" + +m = Map("serverchan", translate("提示:")) +m.description = translate("如果你不了解这些选项的含义,请不要修改这些选项") + +s = m:section(TypedSection, "serverchan", "高级设置") +s.anonymous = true +s.addremove = false + +a = s:option(Value, "up_timeout", translate('设备上线检测超时(s)')) +a.default = "2" +a.optional = false +a.datatype = "uinteger" + +a = s:option(Value, "down_timeout", translate('设备离线检测超时(s)')) +a.default = "20" +a.optional = false +a.datatype = "uinteger" + +a = s:option(Value, "timeout_retry_count", translate('离线检测次数')) +a.default = "2" +a.optional = false +a.datatype = "uinteger" +a.description = translate("若无二级路由设备,信号强度良好,可以减少以上数值
因夜间 wifi 休眠较为玄学,遇到设备频繁推送断开,烦请自行调整参数
..╮(╯_╰)╭..") + +a = s:option(Value, "thread_num", translate('最大并发进程数')) +a.default = "3" +a.datatype = "uinteger" + +a = s:option(Value, "soc_code", "自定义温度读取命令") +a.rmempty = true +a:value("", translate("默认")) +a:value("pve", translate("PVE 虚拟机")) +a.description = translate("自定义命令如需使用特殊符号,如引号、$、!等,则需要自行转义,并在保存后查看 /etc/config/serverchan 文件 soc_code 设置项是否保存正确
可以使用 eval `echo $(uci get serverchan.serverchan.soc_code)` 命令查看命令输出及错误信息
执行结果需为纯数字(可带小数),用于温度对比") + +a = s:option(Value, "server_host", translate("宿主机地址")) +a.rmempty = true +a.default = "10.0.0.2" +a.description = translate("") +a:depends({soc_code = "pve"}) + +a = s:option(Value, "server_port", translate("宿主机 SSH 端口")) +a.rmempty = true +a.default = "22" +a.description = translate("SSH 端口默认为 22,如有自定义,请填写自定义 SSH 端口
请确认已经设置好密钥登陆,否则会引起脚本无法运行等错误!
PVE 安装 sensors 命令自行百度
密钥登陆例(自行修改地址与端口号):
opkg update #更新列表
opkg install openssh-client openssh-keygen #安装openssh客户端
echo -e \"\\n\" | ssh-keygen -t rsa # 生成密钥文件(空密码)
pve_host=`uci get serverchan.serverchan.server_host` || pve_host=\"10.0.0.3\" # 读取配置文件中的 pve 主机地址,如果不存在请自行填写
pve_port=`uci get serverchan.serverchan.server_port` || pve_host=\"22\" # 读取配置文件中的 pve 主机 ssh 端口号,,如果不存在请自行填写
ssh root@${pve_host} -p ${pve_port} \"tee -a ~/.ssh/id_rsa.pub\" < ~/.ssh/id_rsa.pub # 传送公钥到 PVE
ssh root@${pve_host} -p ${pve_port} \"cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys\" # 写入公钥到 PVE
ssh -i /root/.ssh/id_rsa root@${pve_host} -p ${pve_port} sensors # 使用私钥连接 PVE 测试温度命令
刷机党自行将 /root/.ssh/ 加入备份列表,避免重复操作") +a:depends({soc_code = "pve"}) + +a = s:option(Button, "soc", translate("测试温度命令")) +a.inputtitle = translate("输出信息") +a.write = function() + luci.sys.call("/usr/bin/serverchan/serverchan soc") + luci.http.redirect(luci.dispatcher.build_url("admin", "services", "serverchan", "advanced")) +end + +if nixio.fs.access("/tmp/serverchan/soc_tmp") then +e = s:option(TextValue,"soc_tmp") +e.rows = 2 +e.readonly = true +e.cfgvalue = function() + return luci.sys.exec("cat /tmp/serverchan/soc_tmp && rm -f /tmp/serverchan/soc_tmp") +end +end + +a = s:option(Flag, "gateway_info_enable", translate("从光猫获取主机名等信息")) +a.default = 0 +a.rmempty = true +a.description = translate("适用于 OpenWrt 作为透明网关,无法获取设备主机名及完整的局域网设备列表时
仅测试通过 HG5143F 天翼网关,不保证通用性") + +a = s:option(Value, "gateway_host_url", translate('光猫登录地址 URL')) +a.rmempty = true +a.default = "http://192.168.1.1/cgi-bin/luci" +a:depends({gateway_info_enable = "1"}) + +a = s:option(Value, "gateway_info_url", translate('设备列表 JSON URL')) +a.rmempty = true +a.default = "http://192.168.1.1/cgi-bin/luci/admin/allInfo" +a:depends({gateway_info_enable = "1"}) + +a = s:option(Value, "gateway_logout_url", translate('光猫注销登录 URL')) +a.rmempty = true +a.default = "http://192.168.1.1/cgi-bin/luci/admin/logout" +a.description = translate("使用 F12 控制台自行抓取") +a:depends({gateway_info_enable = "1"}) + +a = s:option(Value, "gateway_username_id", translate('登录页面帐号输入框 ID')) +a.rmempty = true +a.default = "username" +a:depends({gateway_info_enable = "1"}) + +a = s:option(Value, "gateway_password_id", translate('登录页面密码输入框 ID')) +a.rmempty = true +a.default = "psd" +a.description = translate("浏览器右键-检查元素") +a:depends({gateway_info_enable = "1"}) + +a = s:option(Value, "gateway_username", translate('光猫登录帐号')) +a.rmempty = true +a.default = "useradmin" +a:depends({gateway_info_enable = "1"}) + +a = s:option(Value, "gateway_password", translate('光猫登录密码')) +a.rmempty = true +a.description = translate("使用普通账号即可,不需要超密") +a:depends({gateway_info_enable = "1"}) + +a = s:option(Flag, "err_enable", translate("无人值守任务")) +a.default = 0 +a.rmempty = true +a.description = translate("请确认脚本可以正常运行,否则可能造成频繁重启等错误!") + +a = s:option(Flag, "err_sheep_enable", translate("仅在免打扰时段重拨")) +a.default = 0 +a.rmempty = true +a.description = translate("避免白天重拨 DDNS 域名等待解析,此功能不影响断网检测
因夜间跑流量问题,该功能可能不稳定") +a:depends({err_enable = "1"}) + +a = s:option(DynamicList, "err_device_aliases", translate("关注列表")) +a.rmempty = true +a.description = translate("只会在列表中设备都不在线时才会执行
免打扰时段一小时后,关注设备五分钟低流量(约100kb/m)将视为离线") +nt.mac_hints(function(mac, name) a :value(mac, "%s (%s)" %{ mac, name }) end) +a:depends({err_enable = "1"}) + +a = s:option(ListValue, "network_err_event", translate("网络断开时")) +a.default = "" +a:depends({err_enable = "1"}) +a:value("", translate("无操作")) +a:value("1", translate("重启路由器")) +a:value("2", translate("重新拨号")) +a:value("3", translate("修改相关设置项,尝试自动修复网络")) +a.description = translate("选项 1 选项 2 不会修改设置,并最多尝试 2 次。
选项 3 会将设置项备份于 /usr/bin/serverchan/configbak 目录,并在失败后还原。
【!!无法保证兼容性!!】不熟悉系统设置项,不会救砖请勿使用") + +a = s:option(ListValue, "system_time_event", translate("定时重启")) +a.default = "" +a:depends({err_enable = "1"}) +a:value("", translate("无操作")) +a:value("1", translate("重启路由器")) +a:value("2", translate("重新拨号")) + +a = s:option(Value, "autoreboot_time", "系统运行时间大于") +a.rmempty = true +a.default = "24" +a.datatype = "uinteger" +a:depends({system_time_event = "1"}) +a.description = translate("单位为小时") + +a = s:option(Value, "network_restart_time", "网络在线时间大于") +a.rmempty = true +a.default = "24" +a.datatype = "uinteger" +a:depends({system_time_event = "2"}) +a.description = translate("单位为小时") + +a = s:option(Flag, "public_ip_event", translate("重拨尝试获取公网 IP")) +a.default = 0 +a.rmempty = true +a:depends({err_enable = "1"}) +a.description = translate("重拨时不会推送 IP 变动通知,并会导致你的域名无法及时更新 IP 地址
请确认你可以通过重拨获取公网 IP,否则这不仅徒劳无功还会引起频繁断网
移动等大内网你就别挣扎了!!") + +a = s:option(Value, "public_ip_retry_count", "当天最大重试次数") +a.rmempty = true +a.default = "10" +a.datatype = "uinteger" +a:depends({public_ip_event = "1"}) + +return m diff --git a/luci-app-serverchan/luasrc/model/cbi/serverchan/client.lua b/luci-app-serverchan/luasrc/model/cbi/serverchan/client.lua index 28cc3e4c..45da6d5e 100644 --- a/luci-app-serverchan/luasrc/model/cbi/serverchan/client.lua +++ b/luci-app-serverchan/luasrc/model/cbi/serverchan/client.lua @@ -1,34 +1,34 @@ -local o = require "luci.dispatcher" -local fs = require "nixio.fs" -local jsonc = require "luci.jsonc" -local sys = require "luci.sys" - -local sessions = {} -local session_path = "/var/serverchan/client" -if fs.access(session_path) then - for filename in fs.dir(session_path) do - local session_file = session_path .. "/" .. filename - local file = io.open(session_file, "r") - local t = jsonc.parse(file:read("*a")) - if t then - t.session_file = session_file - sessions[#sessions + 1] = t - end - file:close() - end -end - -f = SimpleForm("processes", translate("")) -f.reset = false -f.submit = false - -local client_count = sys.exec("cat /tmp/serverchan/ipAddress | wc -l") -t = f:section(Table, sessions, translate("当前共 ".. client_count .. "台设备在线")) -t:option(DummyValue, "name", translate("主机名")) -t:option(DummyValue, "mac", translate("MAC")) -t:option(DummyValue, "ip", translate("IP")) -t:option(DummyValue, "usage", translate("总计流量")) -t:option(DummyValue, "uptime", translate("在线时间")) - - -return f +local o = require "luci.dispatcher" +local fs = require "nixio.fs" +local jsonc = require "luci.jsonc" +local sys = require "luci.sys" + +local sessions = {} +local session_path = "/var/serverchan/client" +if fs.access(session_path) then + for filename in fs.dir(session_path) do + local session_file = session_path .. "/" .. filename + local file = io.open(session_file, "r") + local t = jsonc.parse(file:read("*a")) + if t then + t.session_file = session_file + sessions[#sessions + 1] = t + end + file:close() + end +end + +f = SimpleForm("processes", translate("")) +f.reset = false +f.submit = false + +local client_count = sys.exec("cat /tmp/serverchan/ipAddress | wc -l") +t = f:section(Table, sessions, translate("当前共 ".. client_count .. "台设备在线")) +t:option(DummyValue, "name", translate("主机名")) +t:option(DummyValue, "mac", translate("MAC")) +t:option(DummyValue, "ip", translate("IP")) +t:option(DummyValue, "usage", translate("总计流量")) +t:option(DummyValue, "uptime", translate("在线时间")) + + +return f diff --git a/luci-app-serverchan/luasrc/model/cbi/serverchan/log.lua b/luci-app-serverchan/luasrc/model/cbi/serverchan/log.lua index f0fb6e08..d794f7d7 100644 --- a/luci-app-serverchan/luasrc/model/cbi/serverchan/log.lua +++ b/luci-app-serverchan/luasrc/model/cbi/serverchan/log.lua @@ -1,6 +1,6 @@ -f = SimpleForm("serverchan") -f.reset = false -f.submit = false -f:append(Template("serverchan/serverchan_log")) - -return f +f = SimpleForm("serverchan") +f.reset = false +f.submit = false +f:append(Template("serverchan/serverchan_log")) + +return f diff --git a/luci-app-serverchan/luasrc/model/cbi/serverchan/setting.lua b/luci-app-serverchan/luasrc/model/cbi/serverchan/setting.lua index f923b0e8..cd1c445c 100644 --- a/luci-app-serverchan/luasrc/model/cbi/serverchan/setting.lua +++ b/luci-app-serverchan/luasrc/model/cbi/serverchan/setting.lua @@ -1,509 +1,509 @@ -local nt = require "luci.sys".net -local fs = require "nixio.fs" -local e = luci.model.uci.cursor() -local net = require "luci.model.network".init() -local sys = require "luci.sys" -local ifaces = sys.net:devices() - -m = Map("serverchan", translate("ServerChan"), -translate("「Server酱」,英文名「ServerChan」,是一款从服务器推送报警信息和日志到微信的工具。

如果你在使用中遇到问题,请到这里提交:") -.. [[]] -.. translate("GitHub 项目地址") -.. [[]] -) - -m:section(SimpleSection).template = "serverchan/serverchan_status" - -s = m:section(NamedSection, "serverchan", "serverchan", translate("")) -s:tab("basic", translate("基本设置")) -s:tab("content", translate("推送内容")) -s:tab("crontab", translate("定时推送")) -s:tab("disturb", translate("免打扰")) -s.addremove = false -s.anonymous = true - ---基本设置 -a = s:taboption("basic", Flag, "serverchan_enable", translate("启用")) -a.rmempty = true - -a = s:taboption("basic", MultiValue, "lite_enable", translate("精简模式")) -a:value("device", translate("精简当前设备列表")) -a:value("nowtime", translate("精简当前时间")) -a:value("content", translate("只推送标题")) -a.widget = "checkbox" -a.default = nil -a.optional = true - -a = s:taboption("basic", ListValue, "jsonpath", translate("推送模式")) -a.default = "/usr/share/serverchan/api/serverchan.json" -a.rmempty = true -a:value("/usr/share/serverchan/api/serverchan.json", translate("微信 Server酱")) -a:value("/usr/share/serverchan/api/qywx_mpnews.json", translate("企业微信 图文消息")) -a:value("/usr/share/serverchan/api/qywx_markdown.json", translate("企业微信 markdown版(不支持公众号)")) -a:value("/usr/share/serverchan/api/wxpusher.json", translate("微信 wxpusher")) -a:value("/usr/share/serverchan/api/pushplus.json", translate("微信 pushplus")) -a:value("/usr/share/serverchan/api/telegram.json", translate("Telegram")) -a:value("/usr/share/serverchan/api/diy.json", translate("自定义推送")) - -a = s:taboption("basic", Value, "sckey", translate('微信推送/新旧共用'), translate("").."Server酱 sendkey 点击这里
") -a.rmempty = true -a:depends("jsonpath", "/usr/share/serverchan/api/serverchan.json") - -a = s:taboption("basic", Value, "corpid", translate('企业ID(corpid)'), translate("").."获取说明 点击这里") -a.rmempty = true -a:depends("jsonpath", "/usr/share/serverchan/api/qywx_mpnews.json") -a:depends("jsonpath", "/usr/share/serverchan/api/qywx_markdown.json") - -a = s:taboption("basic", Value, "userid", translate('帐号(userid)')) -a.rmempty = true -a.description = translate("群发到应用请填入 @all ") -a:depends("jsonpath", "/usr/share/serverchan/api/qywx_mpnews.json") -a:depends("jsonpath", "/usr/share/serverchan/api/qywx_markdown.json") - -a = s:taboption("basic", Value, "agentid", translate('应用id(agentid)')) -a.rmempty = true -a:depends("jsonpath", "/usr/share/serverchan/api/qywx_mpnews.json") -a:depends("jsonpath", "/usr/share/serverchan/api/qywx_markdown.json") - -a = s:taboption("basic", Value, "corpsecret", translate('应用密钥(Secret)')) -a.rmempty = true -a:depends("jsonpath", "/usr/share/serverchan/api/qywx_mpnews.json") -a:depends("jsonpath", "/usr/share/serverchan/api/qywx_markdown.json") - -a = s:taboption("basic", Value, "mediapath", translate('图片缩略图文件路径')) -a.rmempty = true -a.default = "/usr/share/serverchan/api/logo.jpg" -a:depends("jsonpath", "/usr/share/serverchan/api/qywx_mpnews.json") -a.description = translate("只支持 2MB 以内 JPG,PNG 格式
900*383 或 2.35:1 为佳 ") - -a = s:taboption("basic", Value, "wxpusher_apptoken", translate('appToken'), translate("").."获取 appToken 点击这里
") -a.rmempty = true -a:depends("jsonpath", "/usr/share/serverchan/api/wxpusher.json") - -a = s:taboption("basic", Value,"wxpusher_uids",translate('uids')) -a.rmempty = true -a:depends("jsonpath", "/usr/share/serverchan/api/wxpusher.json") - -a = s:taboption("basic", Value, "wxpusher_topicIds", translate('topicIds(群发)'), translate("").."接口说明 点击这里
") -a.rmempty = true -a:depends("jsonpath", "/usr/share/serverchan/api/wxpusher.json") - -a = s:taboption("basic", Value, "pushplus_token", translate('pushplus_token'), translate("").."获取pushplus_token 点击这里
") -a.rmempty = true -a:depends("jsonpath", "/usr/share/serverchan/api/pushplus.json") - -a = s:taboption("basic", Value, "tg_token", translate("TG_token"), translate("").."获取机器人点击这里
与创建的机器人发一条消息,开启对话
") -a.rmempty = true -a:depends("jsonpath", "/usr/share/serverchan/api/telegram.json") - -a = s:taboption("basic", Value, "chat_id", translate('TG_chatid'), translate("").."获取 chat_id 点击这里") -a.rmempty = true -a:depends("jsonpath", "/usr/share/serverchan/api/telegram.json") - -a = s:taboption("basic", TextValue, "diy_json", translate("自定义推送")) -a.optional = false -a.rows = 28 -a.wrap = "soft" -a.cfgvalue = function(self, section) - return fs.readfile("/usr/share/serverchan/api/diy.json") -end -a.write = function(self, section, value) - fs.writefile("/usr/share/serverchan/api/diy.json", value:gsub("\r\n", "\n")) -end -a:depends("jsonpath", "/usr/share/serverchan/api/diy.json") - -a = s:taboption("basic", Button, "__add", translate("发送测试")) -a.inputtitle = translate("发送") -a.inputstyle = "apply" -function a.write(self, section) - luci.sys.call("cbi.apply") - luci.sys.call("/usr/share/serverchan/serverchan test &") -end - -a = s:taboption("basic", Value, "device_name", translate('本设备名称')) -a.rmempty = true -a.description = translate("在推送信息标题中会标识本设备名称,用于区分推送信息的来源设备") - -a = s:taboption("basic", Value, "sleeptime", translate('检测时间间隔(s)')) -a.rmempty = true -a.optional = false -a.default = "60" -a.datatype = "and(uinteger,min(10))" -a.description = translate("越短的时间时间响应越及时,但会占用更多的系统资源") - -a = s:taboption("basic", ListValue, "oui_data", translate("MAC设备信息数据库")) -a.rmempty = true -a.default = "" -a:value("", translate("关闭")) -a:value("1", translate("简化版")) -a:value("2", translate("完整版")) -a:value("3", translate("网络查询")) -a.description = translate("需下载 4.36 MB 原始数据,处理后完整版约 1.2 MB,简化版约 250 kB
若无梯子,请勿使用网络查询") - -a = s:taboption("basic", Flag, "oui_dir", translate("下载到内存")) -a.rmempty = true -a:depends("oui_data", "1") -a:depends("oui_data", "2") -a.description = translate("懒得做自动更新了,下载到内存中,重启会重新下载
若无梯子,还是下到机身吧") - -a = s:taboption("basic", Flag, "reset_regularly", translate("每天零点重置流量数据")) -a.rmempty = true - -a = s:taboption("basic", Flag, "debuglevel", translate("开启日志")) -a.rmempty = true - -a = s:taboption("basic", DynamicList, "device_aliases", translate("设备别名")) -a.rmempty = true -a.description = translate("
请输入设备 MAC 和设备别名,用“-”隔开,如:
XX:XX:XX:XX:XX:XX-我的手机") - ---设备状态 -a = s:taboption("content", ListValue, "serverchan_ipv4", translate("IPv4 变动通知")) -a.rmempty = true -a.default = "" -a:value("", translate("关闭")) -a:value("1", translate("通过接口获取")) -a:value("2", translate("通过URL获取")) - -a = s:taboption("content", ListValue, "ipv4_interface", translate("接口名称")) -a.rmempty = true -a:depends({serverchan_ipv4 = "1"}) -for _, iface in ipairs(ifaces) do - if not (iface == "lo" or iface:match("^ifb.*")) then - local nets = net:get_interface(iface) - nets = nets and nets:get_networks() or {} - for k, v in pairs(nets) do - nets[k] = nets[k].sid - end - nets = table.concat(nets, ",") - a:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface)) - end -end -a.description = translate("
一般选择 wan 接口,多拨环境请自行选择") - -a = s:taboption("content", TextValue, "ipv4_list", translate("IPv4 API列表")) -a.optional = false -a.rows = 8 -a.wrap = "soft" -a.cfgvalue = function(self, section) - return fs.readfile("/usr/share/serverchan/api/ipv4.list") -end -a.write = function(self, section, value) - fs.writefile("/usr/share/serverchan/api/ipv4.list", value:gsub("\r\n", "\n")) -end -a.description = translate("
会因服务器稳定性、连接频繁等原因导致获取失败
如接口可以正常获取 IP,不推荐使用
从以上列表中随机地址访问") -a:depends({serverchan_ipv4 = "2"}) - -a = s:taboption("content", ListValue, "serverchan_ipv6", translate("IPv6 变动通知")) -a.rmempty = true -a.default = "disable" -a:value("0", translate("关闭")) -a:value("1", translate("通过接口获取")) -a:value("2", translate("通过URL获取")) - -a = s:taboption("content", ListValue, "ipv6_interface", translate("接口名称")) -a.rmempty = true -a:depends({serverchan_ipv6 = "1"}) -for _, iface in ipairs(ifaces) do - if not (iface == "lo" or iface:match("^ifb.*")) then - local nets = net:get_interface(iface) - nets = nets and nets:get_networks() or {} - for k, v in pairs(nets) do - nets[k] = nets[k].sid - end - nets = table.concat(nets, ",") - a:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface)) - end -end -a.description = translate("
一般选择 wan 接口,多拨环境请自行选择") - -a = s:taboption("content", TextValue, "ipv6_list", translate("IPv6 API列表")) -a.optional = false -a.rows = 8 -a.wrap = "soft" -a.cfgvalue = function(self, section) - return fs.readfile("/usr/share/serverchan/api/ipv6.list") -end -a.write = function(self, section, value) - fs.writefile("/usr/share/serverchan/api/ipv6.list", value:gsub("\r\n", "\n")) -end -a.description = translate("
会因服务器稳定性、连接频繁等原因导致获取失败
如接口可以正常获取 IP,不推荐使用
从以上列表中随机地址访问") -a:depends({serverchan_ipv6 = "2"}) - -a = s:taboption("content", Flag, "serverchan_up", translate("设备上线通知")) -a.default = 1 -a.rmempty = true - -a = s:taboption("content", Flag, "serverchan_down", translate("设备下线通知")) -a.default = 1 -a.rmempty = true - -a = s:taboption("content", Flag, "cpuload_enable", translate("CPU 负载报警")) -a.default = 1 -a.rmempty = true - -a = s:taboption("content", Value, "cpuload", "负载报警阈值") -a.default = 2 -a.rmempty = true -a:depends({cpuload_enable = "1"}) - -a = s:taboption("content", Flag, "temperature_enable", translate("CPU 温度报警")) -a.default = 1 -a.rmempty = true -a.description = translate("请确认设备可以获取温度,如需修改命令,请移步高级设置") - -a = s:taboption("content", Value, "temperature", "温度报警阈值") -a.rmempty = true -a.default = "80" -a.datatype = "and(uinteger,min(1))" -a:depends({temperature_enable = "1"}) -a.description = translate("
设备报警只会在连续五分钟超过设定值时才会推送
而且一个小时内不会再提醒第二次") - -a = s:taboption("content", Flag, "client_usage", translate("设备异常流量")) -a.default = 0 -a.rmempty = true - -a = s:taboption("content", Value, "client_usage_max", "每分钟流量限制") -a.default = "10M" -a.rmempty = true -a:depends({client_usage = "1"}) -a.description = translate("设备异常流量警报(byte),你可以追加 K 或者 M") - -a = s:taboption("content", Flag, "client_usage_disturb", translate("异常流量免打扰")) -a.default = 1 -a.rmempty = true -a:depends({client_usage = "1"}) - -a = s:taboption("content", DynamicList, "client_usage_whitelist", translate("异常流量关注列表")) -nt.mac_hints(function(mac, name) a:value(mac, "%s (%s)" %{ mac, name }) end) -a.rmempty = true -a:depends({client_usage_disturb = "1"}) -a.description = translate("请输入设备 MAC") - -a = s:taboption("content", Flag, "web_logged", translate("web 登录提醒")) -a.default = 0 -a.rmempty = true - -a = s:taboption("content", Flag, "ssh_logged", translate("ssh 登录提醒")) -a.default = 0 -a.rmempty = true - -a = s:taboption("content", Flag, "web_login_failed", translate("web 错误尝试提醒")) -a.default = 0 -a.rmempty = true - -a = s:taboption("content", Flag, "ssh_login_failed", translate("ssh 错误尝试提醒")) -a.default = 0 -a.rmempty = true - -a = s:taboption("content", Value, "login_max_num", "错误尝试次数") -a.default = "3" -a.datatype = "and(uinteger,min(1))" -a:depends("web_login_failed", "1") -a:depends("ssh_login_failed", "1") -a.description = translate("超过次数后推送提醒") - -a = s:taboption("content", Flag, "web_login_black", translate("自动拉黑")) -a.default = 0 -a.rmempty = true -a:depends("web_login_failed", "1") -a:depends("ssh_login_failed", "1") -a.description = translate("直到重启前都不会重置次数,请先添加白名单") - -a = s:taboption("content", Value, "ip_black_timeout", "拉黑时间(秒)") -a.default = "86400" -a.datatype = "and(uinteger,min(0))" -a:depends("web_login_black", "1") -a.description = translate("0 为永久拉黑,慎用
如不幸误操作,请更改设备 IP 进入 LUCI 界面清空规则") - -a = s:taboption("content", DynamicList, "ip_white_list", translate("白名单 IP 列表")) -a.datatype = "ipaddr" -a.rmempty = true -luci.ip.neighbors({family = 4}, function(entry) - if entry.reachable then - a:value(entry.dest:string()) - end -end) -a:depends("web_logged", "1") -a:depends("ssh_logged", "1") -a:depends("web_login_failed", "1") -a:depends("ssh_login_failed", "1") -a.description = translate("忽略白名单登陆提醒和拉黑操作,暂不支持掩码位表示") - -a = s:taboption("content", TextValue, "ip_black_list", translate("IP 黑名单列表")) -a.optional = false -a.rows = 8 -a.wrap = "soft" -a.cfgvalue = function(self, section) - return fs.readfile("/usr/share/serverchan/api/ip_blacklist") -end -a.write = function(self, section, value) - fs.writefile("/usr/share/serverchan/api/ip_blacklist", value:gsub("\r\n", "\n")) -end -a:depends("web_login_black", "1") - ---定时推送 -a = s:taboption("crontab", ListValue, "crontab", translate("定时任务设定")) -a.rmempty = true -a.default = "" -a:value("", translate("关闭")) -a:value("1", translate("定时发送")) -a:value("2", translate("间隔发送")) - -a = s:taboption("crontab", ListValue, "regular_time", translate("发送时间")) -a.rmempty = true -for t = 0, 23 do -a:value(t, translate("每天"..t.."点")) -end -a.default = 8 -a.datatype = uinteger -a:depends("crontab", "1") - -a = s:taboption("crontab", ListValue, "regular_time_2", translate("发送时间")) -a.rmempty = true -a:value("", translate("关闭")) -for t = 0, 23 do -a:value(t, translate("每天"..t.."点")) -end -a.default = "关闭" -a.datatype = uinteger -a:depends("crontab", "1") - -a = s:taboption("crontab", ListValue, "regular_time_3", translate("发送时间")) -a.rmempty = true - -a:value("", translate("关闭")) -for t = 0, 23 do -a:value(t, translate("每天"..t.."点")) -end -a.default = "关闭" -a.datatype = uinteger -a:depends("crontab", "1") - -a = s:taboption("crontab", ListValue, "interval_time", translate("发送间隔")) -a.rmempty = true -for t = 1, 23 do -a:value(t, translate(t.."小时")) -end -a.default = 6 -a.datatype = uinteger -a:depends("crontab", "2") -a.description = translate("
从 00:00 开始,每 * 小时发送一次") - -a = s:taboption("crontab", Value, "send_title", translate("微信推送标题")) -a:depends("crontab", "1") -a:depends("crontab", "2") -a.placeholder = "OpenWrt By tty228 路由状态:" -a.description = translate("
使用特殊符号可能会造成发送失败") - -a = s:taboption("crontab", Flag, "router_status", translate("系统运行情况")) -a.default = 1 -a:depends("crontab", "1") -a:depends("crontab", "2") - -a = s:taboption("crontab", Flag, "router_temp", translate("设备温度")) -a.default = 1 -a:depends("crontab", "1") -a:depends("crontab", "2") - -a = s:taboption("crontab", Flag, "router_wan", translate("WAN信息")) -a.default = 1 -a:depends("crontab", "1") -a:depends("crontab", "2") - -a = s:taboption("crontab", Flag, "client_list", translate("客户端列表")) -a.default = 1 -a:depends("crontab", "1") -a:depends("crontab", "2") - -e = s:taboption("crontab", Button, "_add", translate("手动发送")) -e.inputtitle = translate("发送") -e:depends("crontab", "1") -e:depends("crontab", "2") -e.inputstyle = "apply" -function e.write(self, section) -luci.sys.call("cbi.apply") - luci.sys.call("/usr/share/serverchan/serverchan send &") -end - ---免打扰 -a = s:taboption("disturb", ListValue, "serverchan_sheep", translate("免打扰时段设置"), translate("在指定整点时间段内,暂停推送消息
免打扰时间中,定时推送也会被阻止。")) -a.rmempty = true -a:value("", translate("关闭")) -a:value("1", translate("模式一:脚本挂起")) -a:value("2", translate("模式二:静默模式")) -a.description = translate("模式一停止一切检测,包括无人值守。") - -a = s:taboption("disturb", ListValue, "starttime", translate("免打扰开始时间")) -a.rmempty = true - -for t = 0, 23 do -a:value(t, translate("每天"..t.."点")) -end -a.default = 0 -a.datatype = uinteger -a:depends({serverchan_sheep = "1"}) -a:depends({serverchan_sheep = "2"}) - -a = s:taboption("disturb", ListValue, "endtime", translate("免打扰结束时间")) -a.rmempty = true - -for t = 0, 23 do -a:value(t, translate("每天"..t.."点")) -end -a.default = 8 -a.datatype = uinteger -a:depends({serverchan_sheep = "1"}) -a:depends({serverchan_sheep = "2"}) - -a = s:taboption("disturb", ListValue, "macmechanism", translate("MAC过滤")) -a:value("", translate("disable")) -a:value("allow", translate("忽略列表内设备")) -a:value("block", translate("仅通知列表内设备")) -a:value("interface", translate("仅通知此接口设备")) -a.rmempty = true - -a = s:taboption("disturb", DynamicList, "serverchan_whitelist", translate("忽略列表")) -nt.mac_hints(function(mac, name) a :value(mac, "%s (%s)" %{ mac, name }) end) -a.rmempty = true -a:depends({macmechanism = "allow"}) -a.description = translate("AA:AA:AA:AA:AA:AA\\|BB:BB:BB:BB:BB:B 可以将多个 MAC 视为同一用户
任一设备在线后不再推送,设备全部离线时才会推送,避免双 wifi 频繁推送") - -a = s:taboption("disturb", DynamicList, "serverchan_blacklist", translate("关注列表")) -nt.mac_hints(function(mac, name) a:value(mac, "%s (%s)" %{ mac, name }) end) -a.rmempty = true -a:depends({macmechanism = "block"}) -a.description = translate("AA:AA:AA:AA:AA:AA\\|BB:BB:BB:BB:BB:B 可以将多个 MAC 视为同一用户
任一设备在线后不再推送,设备全部离线时才会推送,避免双 wifi 频繁推送") - -a = s:taboption("disturb", ListValue, "serverchan_interface", translate("接口名称")) -a:depends({macmechanism = "interface"}) -a.rmempty = true - -for _, iface in ipairs(ifaces) do - if not (iface == "lo" or iface:match("^ifb.*")) then - local nets = net:get_interface(iface) - nets = nets and nets:get_networks() or {} - for k, v in pairs(nets) do - nets[k] = nets[k].sid - end - nets = table.concat(nets, ",") - a:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface)) - end -end - -a = s:taboption("disturb", ListValue, "macmechanism2", translate("MAC过滤2")) -a:value("", translate("disable")) -a:value("MAC_online", translate("列表内任意设备在线时免打扰")) -a:value("MAC_offline", translate("列表内设备都离线后免打扰")) -a.rmempty = true - -a = s:taboption("disturb", DynamicList, "MAC_online_list", translate("在线免打扰列表")) -nt.mac_hints(function(mac, name) a:value(mac, "%s (%s)" %{ mac, name }) end) -a.rmempty = true -a:depends({macmechanism2 = "MAC_online"}) - -a = s:taboption("disturb", DynamicList, "MAC_offline_list", translate("任意离线免打扰列表")) -nt.mac_hints(function(mac, name) a:value(mac, "%s (%s)" %{ mac, name }) end) -a.rmempty = true -a:depends({macmechanism2 = "MAC_offline"}) - -return m +local nt = require "luci.sys".net +local fs = require "nixio.fs" +local e = luci.model.uci.cursor() +local net = require "luci.model.network".init() +local sys = require "luci.sys" +local ifaces = sys.net:devices() + +m = Map("serverchan", translate("ServerChan"), +translate("「Server酱」,英文名「ServerChan」,是一款从服务器推送报警信息和日志到微信的工具。

如果你在使用中遇到问题,请到这里提交:") +.. [[]] +.. translate("GitHub 项目地址") +.. [[]] +) + +m:section(SimpleSection).template = "serverchan/serverchan_status" + +s = m:section(NamedSection, "serverchan", "serverchan", translate("")) +s:tab("basic", translate("基本设置")) +s:tab("content", translate("推送内容")) +s:tab("crontab", translate("定时推送")) +s:tab("disturb", translate("免打扰")) +s.addremove = false +s.anonymous = true + +--基本设置 +a = s:taboption("basic", Flag, "serverchan_enable", translate("启用")) +a.rmempty = true + +a = s:taboption("basic", MultiValue, "lite_enable", translate("精简模式")) +a:value("device", translate("精简当前设备列表")) +a:value("nowtime", translate("精简当前时间")) +a:value("content", translate("只推送标题")) +a.widget = "checkbox" +a.default = nil +a.optional = true + +a = s:taboption("basic", ListValue, "jsonpath", translate("推送模式")) +a.default = "/usr/bin/serverchan/api/serverchan.json" +a.rmempty = true +a:value("/usr/bin/serverchan/api/serverchan.json", translate("微信 Server酱")) +a:value("/usr/bin/serverchan/api/qywx_mpnews.json", translate("企业微信 图文消息")) +a:value("/usr/bin/serverchan/api/qywx_markdown.json", translate("企业微信 markdown版(不支持公众号)")) +a:value("/usr/bin/serverchan/api/wxpusher.json", translate("微信 wxpusher")) +a:value("/usr/bin/serverchan/api/pushplus.json", translate("微信 pushplus")) +a:value("/usr/bin/serverchan/api/telegram.json", translate("Telegram")) +a:value("/usr/bin/serverchan/api/diy.json", translate("自定义推送")) + +a = s:taboption("basic", Value, "sckey", translate('微信推送/新旧共用'), translate("").."Server酱 sendkey 点击这里
") +a.rmempty = true +a:depends("jsonpath", "/usr/bin/serverchan/api/serverchan.json") + +a = s:taboption("basic", Value, "corpid", translate('企业ID(corpid)'), translate("").."获取说明 点击这里") +a.rmempty = true +a:depends("jsonpath", "/usr/bin/serverchan/api/qywx_mpnews.json") +a:depends("jsonpath", "/usr/bin/serverchan/api/qywx_markdown.json") + +a = s:taboption("basic", Value, "userid", translate('帐号(userid)')) +a.rmempty = true +a.description = translate("群发到应用请填入 @all ") +a:depends("jsonpath", "/usr/bin/serverchan/api/qywx_mpnews.json") +a:depends("jsonpath", "/usr/bin/serverchan/api/qywx_markdown.json") + +a = s:taboption("basic", Value, "agentid", translate('应用id(agentid)')) +a.rmempty = true +a:depends("jsonpath", "/usr/bin/serverchan/api/qywx_mpnews.json") +a:depends("jsonpath", "/usr/bin/serverchan/api/qywx_markdown.json") + +a = s:taboption("basic", Value, "corpsecret", translate('应用密钥(Secret)')) +a.rmempty = true +a:depends("jsonpath", "/usr/bin/serverchan/api/qywx_mpnews.json") +a:depends("jsonpath", "/usr/bin/serverchan/api/qywx_markdown.json") + +a = s:taboption("basic", Value, "mediapath", translate('图片缩略图文件路径')) +a.rmempty = true +a.default = "/usr/bin/serverchan/api/logo.jpg" +a:depends("jsonpath", "/usr/bin/serverchan/api/qywx_mpnews.json") +a.description = translate("只支持 2MB 以内 JPG,PNG 格式
900*383 或 2.35:1 为佳 ") + +a = s:taboption("basic", Value, "wxpusher_apptoken", translate('appToken'), translate("").."获取 appToken 点击这里
") +a.rmempty = true +a:depends("jsonpath", "/usr/bin/serverchan/api/wxpusher.json") + +a = s:taboption("basic", Value,"wxpusher_uids",translate('uids')) +a.rmempty = true +a:depends("jsonpath", "/usr/bin/serverchan/api/wxpusher.json") + +a = s:taboption("basic", Value, "wxpusher_topicIds", translate('topicIds(群发)'), translate("").."接口说明 点击这里
") +a.rmempty = true +a:depends("jsonpath", "/usr/bin/serverchan/api/wxpusher.json") + +a = s:taboption("basic", Value, "pushplus_token", translate('pushplus_token'), translate("").."获取pushplus_token 点击这里
") +a.rmempty = true +a:depends("jsonpath", "/usr/bin/serverchan/api/pushplus.json") + +a = s:taboption("basic", Value, "tg_token", translate("TG_token"), translate("").."获取机器人点击这里
与创建的机器人发一条消息,开启对话
") +a.rmempty = true +a:depends("jsonpath", "/usr/bin/serverchan/api/telegram.json") + +a = s:taboption("basic", Value, "chat_id", translate('TG_chatid'), translate("").."获取 chat_id 点击这里") +a.rmempty = true +a:depends("jsonpath", "/usr/bin/serverchan/api/telegram.json") + +a = s:taboption("basic", TextValue, "diy_json", translate("自定义推送")) +a.optional = false +a.rows = 28 +a.wrap = "soft" +a.cfgvalue = function(self, section) + return fs.readfile("/usr/bin/serverchan/api/diy.json") +end +a.write = function(self, section, value) + fs.writefile("/usr/bin/serverchan/api/diy.json", value:gsub("\r\n", "\n")) +end +a:depends("jsonpath", "/usr/bin/serverchan/api/diy.json") + +a = s:taboption("basic", Button, "__add", translate("发送测试")) +a.inputtitle = translate("发送") +a.inputstyle = "apply" +function a.write(self, section) + luci.sys.call("cbi.apply") + luci.sys.call("/usr/bin/serverchan/serverchan test &") +end + +a = s:taboption("basic", Value, "device_name", translate('本设备名称')) +a.rmempty = true +a.description = translate("在推送信息标题中会标识本设备名称,用于区分推送信息的来源设备") + +a = s:taboption("basic", Value, "sleeptime", translate('检测时间间隔(s)')) +a.rmempty = true +a.optional = false +a.default = "60" +a.datatype = "and(uinteger,min(10))" +a.description = translate("越短的时间时间响应越及时,但会占用更多的系统资源") + +a = s:taboption("basic", ListValue, "oui_data", translate("MAC设备信息数据库")) +a.rmempty = true +a.default = "" +a:value("", translate("关闭")) +a:value("1", translate("简化版")) +a:value("2", translate("完整版")) +a:value("3", translate("网络查询")) +a.description = translate("需下载 4.36 MB 原始数据,处理后完整版约 1.2 MB,简化版约 250 kB
若无梯子,请勿使用网络查询") + +a = s:taboption("basic", Flag, "oui_dir", translate("下载到内存")) +a.rmempty = true +a:depends("oui_data", "1") +a:depends("oui_data", "2") +a.description = translate("懒得做自动更新了,下载到内存中,重启会重新下载
若无梯子,还是下到机身吧") + +a = s:taboption("basic", Flag, "reset_regularly", translate("每天零点重置流量数据")) +a.rmempty = true + +a = s:taboption("basic", Flag, "debuglevel", translate("开启日志")) +a.rmempty = true + +a = s:taboption("basic", DynamicList, "device_aliases", translate("设备别名")) +a.rmempty = true +a.description = translate("
请输入设备 MAC 和设备别名,用“-”隔开,如:
XX:XX:XX:XX:XX:XX-我的手机") + +--设备状态 +a = s:taboption("content", ListValue, "serverchan_ipv4", translate("IPv4 变动通知")) +a.rmempty = true +a.default = "" +a:value("", translate("关闭")) +a:value("1", translate("通过接口获取")) +a:value("2", translate("通过URL获取")) + +a = s:taboption("content", ListValue, "ipv4_interface", translate("接口名称")) +a.rmempty = true +a:depends({serverchan_ipv4 = "1"}) +for _, iface in ipairs(ifaces) do + if not (iface == "lo" or iface:match("^ifb.*")) then + local nets = net:get_interface(iface) + nets = nets and nets:get_networks() or {} + for k, v in pairs(nets) do + nets[k] = nets[k].sid + end + nets = table.concat(nets, ",") + a:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface)) + end +end +a.description = translate("
一般选择 wan 接口,多拨环境请自行选择") + +a = s:taboption("content", TextValue, "ipv4_list", translate("IPv4 API列表")) +a.optional = false +a.rows = 8 +a.wrap = "soft" +a.cfgvalue = function(self, section) + return fs.readfile("/usr/bin/serverchan/api/ipv4.list") +end +a.write = function(self, section, value) + fs.writefile("/usr/bin/serverchan/api/ipv4.list", value:gsub("\r\n", "\n")) +end +a.description = translate("
会因服务器稳定性、连接频繁等原因导致获取失败
如接口可以正常获取 IP,不推荐使用
从以上列表中随机地址访问") +a:depends({serverchan_ipv4 = "2"}) + +a = s:taboption("content", ListValue, "serverchan_ipv6", translate("IPv6 变动通知")) +a.rmempty = true +a.default = "disable" +a:value("0", translate("关闭")) +a:value("1", translate("通过接口获取")) +a:value("2", translate("通过URL获取")) + +a = s:taboption("content", ListValue, "ipv6_interface", translate("接口名称")) +a.rmempty = true +a:depends({serverchan_ipv6 = "1"}) +for _, iface in ipairs(ifaces) do + if not (iface == "lo" or iface:match("^ifb.*")) then + local nets = net:get_interface(iface) + nets = nets and nets:get_networks() or {} + for k, v in pairs(nets) do + nets[k] = nets[k].sid + end + nets = table.concat(nets, ",") + a:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface)) + end +end +a.description = translate("
一般选择 wan 接口,多拨环境请自行选择") + +a = s:taboption("content", TextValue, "ipv6_list", translate("IPv6 API列表")) +a.optional = false +a.rows = 8 +a.wrap = "soft" +a.cfgvalue = function(self, section) + return fs.readfile("/usr/bin/serverchan/api/ipv6.list") +end +a.write = function(self, section, value) + fs.writefile("/usr/bin/serverchan/api/ipv6.list", value:gsub("\r\n", "\n")) +end +a.description = translate("
会因服务器稳定性、连接频繁等原因导致获取失败
如接口可以正常获取 IP,不推荐使用
从以上列表中随机地址访问") +a:depends({serverchan_ipv6 = "2"}) + +a = s:taboption("content", Flag, "serverchan_up", translate("设备上线通知")) +a.default = 1 +a.rmempty = true + +a = s:taboption("content", Flag, "serverchan_down", translate("设备下线通知")) +a.default = 1 +a.rmempty = true + +a = s:taboption("content", Flag, "cpuload_enable", translate("CPU 负载报警")) +a.default = 1 +a.rmempty = true + +a = s:taboption("content", Value, "cpuload", "负载报警阈值") +a.default = 2 +a.rmempty = true +a:depends({cpuload_enable = "1"}) + +a = s:taboption("content", Flag, "temperature_enable", translate("CPU 温度报警")) +a.default = 1 +a.rmempty = true +a.description = translate("请确认设备可以获取温度,如需修改命令,请移步高级设置") + +a = s:taboption("content", Value, "temperature", "温度报警阈值") +a.rmempty = true +a.default = "80" +a.datatype = "and(uinteger,min(1))" +a:depends({temperature_enable = "1"}) +a.description = translate("
设备报警只会在连续五分钟超过设定值时才会推送
而且一个小时内不会再提醒第二次") + +a = s:taboption("content", Flag, "client_usage", translate("设备异常流量")) +a.default = 0 +a.rmempty = true + +a = s:taboption("content", Value, "client_usage_max", "每分钟流量限制") +a.default = "10M" +a.rmempty = true +a:depends({client_usage = "1"}) +a.description = translate("设备异常流量警报(byte),你可以追加 K 或者 M") + +a = s:taboption("content", Flag, "client_usage_disturb", translate("异常流量免打扰")) +a.default = 1 +a.rmempty = true +a:depends({client_usage = "1"}) + +a = s:taboption("content", DynamicList, "client_usage_whitelist", translate("异常流量关注列表")) +nt.mac_hints(function(mac, name) a:value(mac, "%s (%s)" %{ mac, name }) end) +a.rmempty = true +a:depends({client_usage_disturb = "1"}) +a.description = translate("请输入设备 MAC") + +a = s:taboption("content", Flag, "web_logged", translate("web 登录提醒")) +a.default = 0 +a.rmempty = true + +a = s:taboption("content", Flag, "ssh_logged", translate("ssh 登录提醒")) +a.default = 0 +a.rmempty = true + +a = s:taboption("content", Flag, "web_login_failed", translate("web 错误尝试提醒")) +a.default = 0 +a.rmempty = true + +a = s:taboption("content", Flag, "ssh_login_failed", translate("ssh 错误尝试提醒")) +a.default = 0 +a.rmempty = true + +a = s:taboption("content", Value, "login_max_num", "错误尝试次数") +a.default = "3" +a.datatype = "and(uinteger,min(1))" +a:depends("web_login_failed", "1") +a:depends("ssh_login_failed", "1") +a.description = translate("超过次数后推送提醒") + +a = s:taboption("content", Flag, "web_login_black", translate("自动拉黑")) +a.default = 0 +a.rmempty = true +a:depends("web_login_failed", "1") +a:depends("ssh_login_failed", "1") +a.description = translate("直到重启前都不会重置次数,请先添加白名单") + +a = s:taboption("content", Value, "ip_black_timeout", "拉黑时间(秒)") +a.default = "86400" +a.datatype = "and(uinteger,min(0))" +a:depends("web_login_black", "1") +a.description = translate("0 为永久拉黑,慎用
如不幸误操作,请更改设备 IP 进入 LUCI 界面清空规则") + +a = s:taboption("content", DynamicList, "ip_white_list", translate("白名单 IP 列表")) +a.datatype = "ipaddr" +a.rmempty = true +luci.ip.neighbors({family = 4}, function(entry) + if entry.reachable then + a:value(entry.dest:string()) + end +end) +a:depends("web_logged", "1") +a:depends("ssh_logged", "1") +a:depends("web_login_failed", "1") +a:depends("ssh_login_failed", "1") +a.description = translate("忽略白名单登陆提醒和拉黑操作,暂不支持掩码位表示") + +a = s:taboption("content", TextValue, "ip_black_list", translate("IP 黑名单列表")) +a.optional = false +a.rows = 8 +a.wrap = "soft" +a.cfgvalue = function(self, section) + return fs.readfile("/usr/bin/serverchan/api/ip_blacklist") +end +a.write = function(self, section, value) + fs.writefile("/usr/bin/serverchan/api/ip_blacklist", value:gsub("\r\n", "\n")) +end +a:depends("web_login_black", "1") + +--定时推送 +a = s:taboption("crontab", ListValue, "crontab", translate("定时任务设定")) +a.rmempty = true +a.default = "" +a:value("", translate("关闭")) +a:value("1", translate("定时发送")) +a:value("2", translate("间隔发送")) + +a = s:taboption("crontab", ListValue, "regular_time", translate("发送时间")) +a.rmempty = true +for t = 0, 23 do +a:value(t, translate("每天"..t.."点")) +end +a.default = 8 +a.datatype = uinteger +a:depends("crontab", "1") + +a = s:taboption("crontab", ListValue, "regular_time_2", translate("发送时间")) +a.rmempty = true +a:value("", translate("关闭")) +for t = 0, 23 do +a:value(t, translate("每天"..t.."点")) +end +a.default = "关闭" +a.datatype = uinteger +a:depends("crontab", "1") + +a = s:taboption("crontab", ListValue, "regular_time_3", translate("发送时间")) +a.rmempty = true + +a:value("", translate("关闭")) +for t = 0, 23 do +a:value(t, translate("每天"..t.."点")) +end +a.default = "关闭" +a.datatype = uinteger +a:depends("crontab", "1") + +a = s:taboption("crontab", ListValue, "interval_time", translate("发送间隔")) +a.rmempty = true +for t = 1, 23 do +a:value(t, translate(t.."小时")) +end +a.default = 6 +a.datatype = uinteger +a:depends("crontab", "2") +a.description = translate("
从 00:00 开始,每 * 小时发送一次") + +a = s:taboption("crontab", Value, "send_title", translate("微信推送标题")) +a:depends("crontab", "1") +a:depends("crontab", "2") +a.placeholder = "OpenWrt By tty228 路由状态:" +a.description = translate("
使用特殊符号可能会造成发送失败") + +a = s:taboption("crontab", Flag, "router_status", translate("系统运行情况")) +a.default = 1 +a:depends("crontab", "1") +a:depends("crontab", "2") + +a = s:taboption("crontab", Flag, "router_temp", translate("设备温度")) +a.default = 1 +a:depends("crontab", "1") +a:depends("crontab", "2") + +a = s:taboption("crontab", Flag, "router_wan", translate("WAN信息")) +a.default = 1 +a:depends("crontab", "1") +a:depends("crontab", "2") + +a = s:taboption("crontab", Flag, "client_list", translate("客户端列表")) +a.default = 1 +a:depends("crontab", "1") +a:depends("crontab", "2") + +e = s:taboption("crontab", Button, "_add", translate("手动发送")) +e.inputtitle = translate("发送") +e:depends("crontab", "1") +e:depends("crontab", "2") +e.inputstyle = "apply" +function e.write(self, section) +luci.sys.call("cbi.apply") + luci.sys.call("/usr/bin/serverchan/serverchan send &") +end + +--免打扰 +a = s:taboption("disturb", ListValue, "serverchan_sheep", translate("免打扰时段设置"), translate("在指定整点时间段内,暂停推送消息
免打扰时间中,定时推送也会被阻止。")) +a.rmempty = true +a:value("", translate("关闭")) +a:value("1", translate("模式一:脚本挂起")) +a:value("2", translate("模式二:静默模式")) +a.description = translate("模式一停止一切检测,包括无人值守。") + +a = s:taboption("disturb", ListValue, "starttime", translate("免打扰开始时间")) +a.rmempty = true + +for t = 0, 23 do +a:value(t, translate("每天"..t.."点")) +end +a.default = 0 +a.datatype = uinteger +a:depends({serverchan_sheep = "1"}) +a:depends({serverchan_sheep = "2"}) + +a = s:taboption("disturb", ListValue, "endtime", translate("免打扰结束时间")) +a.rmempty = true + +for t = 0, 23 do +a:value(t, translate("每天"..t.."点")) +end +a.default = 8 +a.datatype = uinteger +a:depends({serverchan_sheep = "1"}) +a:depends({serverchan_sheep = "2"}) + +a = s:taboption("disturb", ListValue, "macmechanism", translate("MAC过滤")) +a:value("", translate("disable")) +a:value("allow", translate("忽略列表内设备")) +a:value("block", translate("仅通知列表内设备")) +a:value("interface", translate("仅通知此接口设备")) +a.rmempty = true + +a = s:taboption("disturb", DynamicList, "serverchan_whitelist", translate("忽略列表")) +nt.mac_hints(function(mac, name) a :value(mac, "%s (%s)" %{ mac, name }) end) +a.rmempty = true +a:depends({macmechanism = "allow"}) +a.description = translate("AA:AA:AA:AA:AA:AA\\|BB:BB:BB:BB:BB:B 可以将多个 MAC 视为同一用户
任一设备在线后不再推送,设备全部离线时才会推送,避免双 wifi 频繁推送") + +a = s:taboption("disturb", DynamicList, "serverchan_blacklist", translate("关注列表")) +nt.mac_hints(function(mac, name) a:value(mac, "%s (%s)" %{ mac, name }) end) +a.rmempty = true +a:depends({macmechanism = "block"}) +a.description = translate("AA:AA:AA:AA:AA:AA\\|BB:BB:BB:BB:BB:B 可以将多个 MAC 视为同一用户
任一设备在线后不再推送,设备全部离线时才会推送,避免双 wifi 频繁推送") + +a = s:taboption("disturb", ListValue, "serverchan_interface", translate("接口名称")) +a:depends({macmechanism = "interface"}) +a.rmempty = true + +for _, iface in ipairs(ifaces) do + if not (iface == "lo" or iface:match("^ifb.*")) then + local nets = net:get_interface(iface) + nets = nets and nets:get_networks() or {} + for k, v in pairs(nets) do + nets[k] = nets[k].sid + end + nets = table.concat(nets, ",") + a:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface)) + end +end + +a = s:taboption("disturb", ListValue, "macmechanism2", translate("MAC过滤2")) +a:value("", translate("disable")) +a:value("MAC_online", translate("列表内任意设备在线时免打扰")) +a:value("MAC_offline", translate("列表内设备都离线后免打扰")) +a.rmempty = true + +a = s:taboption("disturb", DynamicList, "MAC_online_list", translate("在线免打扰列表")) +nt.mac_hints(function(mac, name) a:value(mac, "%s (%s)" %{ mac, name }) end) +a.rmempty = true +a:depends({macmechanism2 = "MAC_online"}) + +a = s:taboption("disturb", DynamicList, "MAC_offline_list", translate("任意离线免打扰列表")) +nt.mac_hints(function(mac, name) a:value(mac, "%s (%s)" %{ mac, name }) end) +a.rmempty = true +a:depends({macmechanism2 = "MAC_offline"}) + +return m diff --git a/luci-app-serverchan/luasrc/view/serverchan/serverchan_log.htm b/luci-app-serverchan/luasrc/view/serverchan/serverchan_log.htm index 9cb029ca..56fe70d6 100644 --- a/luci-app-serverchan/luasrc/view/serverchan/serverchan_log.htm +++ b/luci-app-serverchan/luasrc/view/serverchan/serverchan_log.htm @@ -1,33 +1,33 @@ -<% -local dsp = require "luci.dispatcher" --%> - - -
- <%:自动刷新%> - - -
+<% +local dsp = require "luci.dispatcher" +-%> + + +
+ <%:自动刷新%> + + +
diff --git a/luci-app-serverchan/luasrc/view/serverchan/serverchan_status.htm b/luci-app-serverchan/luasrc/view/serverchan/serverchan_status.htm index df28ade3..e36561dd 100644 --- a/luci-app-serverchan/luasrc/view/serverchan/serverchan_status.htm +++ b/luci-app-serverchan/luasrc/view/serverchan/serverchan_status.htm @@ -1,22 +1,22 @@ - - -
-

- <%:Collecting data...%> -

-
+ + +
+

+ <%:Collecting data...%> +

+
diff --git a/luci-app-serverchan/root/etc/config/serverchan b/luci-app-serverchan/root/etc/config/serverchan index 82001daa..a9a53d9b 100644 --- a/luci-app-serverchan/root/etc/config/serverchan +++ b/luci-app-serverchan/root/etc/config/serverchan @@ -1,11 +1,11 @@ - -config serverchan 'serverchan' - option serverchan_enable '0' - option sleeptime '60' - option serverchan_ipv6 '0' - option serverchan_up '1' - option serverchan_down '1' - option cpuload_enable '1' - option cpuload '2' - option temperature_enable '0' - + +config serverchan 'serverchan' + option serverchan_enable '0' + option sleeptime '60' + option serverchan_ipv6 '0' + option serverchan_up '1' + option serverchan_down '1' + option cpuload_enable '1' + option cpuload '2' + option temperature_enable '0' + diff --git a/luci-app-serverchan/root/etc/init.d/serverchan b/luci-app-serverchan/root/etc/init.d/serverchan index 3dbed79a..2631e4f6 100755 --- a/luci-app-serverchan/root/etc/init.d/serverchan +++ b/luci-app-serverchan/root/etc/init.d/serverchan @@ -1,26 +1,26 @@ -#!/bin/sh /etc/rc.common - -START=99 -STOP=10 - -start() { - state=`pgrep -f "/usr/share/serverchan/serverchan"` - if [ ! -z "$state" ]; then - restart - else - /usr/share/serverchan/serverchan & - fi - echo "serverchan is starting now ..." -} - -stop() { - kill -9 `pgrep -f "/usr/share/serverchan/serverchan"` 2>/dev/null - echo "serverchan exit ..." -} - -restart(){ - stop - sleep 1 - start - echo "restarted." -} +#!/bin/sh /etc/rc.common + +START=99 +STOP=10 + +start() { + state=`pgrep -f "/usr/bin/serverchan/serverchan"` + if [ ! -z "$state" ]; then + restart + else + /usr/bin/serverchan/serverchan & + fi + echo "serverchan is starting now ..." +} + +stop() { + kill -9 `pgrep -f "/usr/bin/serverchan/serverchan"` 2>/dev/null + echo "serverchan exit ..." +} + +restart(){ + stop + sleep 1 + start + echo "restarted." +} diff --git a/luci-app-serverchan/root/etc/uci-defaults/luci-serverchan b/luci-app-serverchan/root/etc/uci-defaults/luci-serverchan index 1abfa341..72ce46dd 100755 --- a/luci-app-serverchan/root/etc/uci-defaults/luci-serverchan +++ b/luci-app-serverchan/root/etc/uci-defaults/luci-serverchan @@ -1,11 +1,11 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@serverchan[-1] - add ucitrack serverchan - set ucitrack.@serverchan[-1].init=serverchan - commit ucitrack -EOF - -rm -rf /tmp/luci-* -exit 0 +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@serverchan[-1] + add ucitrack serverchan + set ucitrack.@serverchan[-1].init=serverchan + commit ucitrack +EOF + +rm -rf /tmp/luci-* +exit 0 diff --git a/luci-app-serverchan/root/usr/share/serverchan/api/diy.json b/luci-app-serverchan/root/usr/bin/serverchan/api/diy.json similarity index 97% rename from luci-app-serverchan/root/usr/share/serverchan/api/diy.json rename to luci-app-serverchan/root/usr/bin/serverchan/api/diy.json index 9fd51f28..04339ef5 100644 --- a/luci-app-serverchan/root/usr/share/serverchan/api/diy.json +++ b/luci-app-serverchan/root/usr/bin/serverchan/api/diy.json @@ -1,40 +1,40 @@ -{ - "_//": "-------------------------------------------------------------------------------", - "_readme": "这是 自定义 api 文件,这里以 telegram 为例", - "_readme": "特殊符号请使用斜杠转义,变量使用 ${var} 表示", - "_//": "-------------------------------------------------------------------------------", - "_api": "【DIY 推送】", - "_url": "api 地址", - "_data": "生成的 json 文件路径,一般不需要改,如 api 不支持 json,请参考 serverchan 推送接口", - "_content_type": "post 内容类型,这里为 json", - "_//": "-------------------------------------------------------------------------------", - "_str_title_start": "标题粗体字开始符号", - "_str_title_end": "标题粗体字结束符号", - "_str_linefeed": "换行符号", - "_str_splitline": "换行+分隔符", - "_str_space": "空格", - "_str_tab": "TAB(用在行首,生成文字区块)", - "_//": "-------------------------------------------------------------------------------", - "_type": - { - "_readme": "type 对象因为需要转义变量,前后必须使用 斜杠+双引号 转义", - "_readme": "参照上文说明,填写下文相关参数" - }, - "_//": "-------------------------------------------------------------------------------", - - "url": "https://api.telegram.org/bot${tg_token}/sendMessage", - "data": "@${tempjsonpath}", - "content_type": "Content-Type: application/json", - "str_title_start": "", - "str_title_end": "", - "str_linefeed": "\\n", - "str_splitline": "\\n----\\n", - "str_space": " ", - "str_tab": " ", - "type": - { - "text":"\"${str_title_start}${1}${str_title_end}${str_splitline}${nowtime}${2}\"", - "chat_id":"\"${chat_id}\"", - "parse_mode":"\"HTML\"" - } -} +{ + "_//": "-------------------------------------------------------------------------------", + "_readme": "这是 自定义 api 文件,这里以 telegram 为例", + "_readme": "特殊符号请使用斜杠转义,变量使用 ${var} 表示", + "_//": "-------------------------------------------------------------------------------", + "_api": "【DIY 推送】", + "_url": "api 地址", + "_data": "生成的 json 文件路径,一般不需要改,如 api 不支持 json,请参考 serverchan 推送接口", + "_content_type": "post 内容类型,这里为 json", + "_//": "-------------------------------------------------------------------------------", + "_str_title_start": "标题粗体字开始符号", + "_str_title_end": "标题粗体字结束符号", + "_str_linefeed": "换行符号", + "_str_splitline": "换行+分隔符", + "_str_space": "空格", + "_str_tab": "TAB(用在行首,生成文字区块)", + "_//": "-------------------------------------------------------------------------------", + "_type": + { + "_readme": "type 对象因为需要转义变量,前后必须使用 斜杠+双引号 转义", + "_readme": "参照上文说明,填写下文相关参数" + }, + "_//": "-------------------------------------------------------------------------------", + + "url": "https://api.telegram.org/bot${tg_token}/sendMessage", + "data": "@${tempjsonpath}", + "content_type": "Content-Type: application/json", + "str_title_start": "", + "str_title_end": "", + "str_linefeed": "\\n", + "str_splitline": "\\n----\\n", + "str_space": " ", + "str_tab": " ", + "type": + { + "text":"\"${str_title_start}${1}${str_title_end}${str_splitline}${nowtime}${2}\"", + "chat_id":"\"${chat_id}\"", + "parse_mode":"\"HTML\"" + } +} diff --git a/luci-app-serverchan/root/usr/share/serverchan/api/ip_blacklist b/luci-app-serverchan/root/usr/bin/serverchan/api/ip_blacklist similarity index 50% rename from luci-app-serverchan/root/usr/share/serverchan/api/ip_blacklist rename to luci-app-serverchan/root/usr/bin/serverchan/api/ip_blacklist index d3f5a12f..8b137891 100644 --- a/luci-app-serverchan/root/usr/share/serverchan/api/ip_blacklist +++ b/luci-app-serverchan/root/usr/bin/serverchan/api/ip_blacklist @@ -1 +1 @@ - + diff --git a/luci-app-serverchan/root/usr/share/serverchan/api/ipv4.list b/luci-app-serverchan/root/usr/bin/serverchan/api/ipv4.list similarity index 94% rename from luci-app-serverchan/root/usr/share/serverchan/api/ipv4.list rename to luci-app-serverchan/root/usr/bin/serverchan/api/ipv4.list index 20b7d887..0a3d793d 100644 --- a/luci-app-serverchan/root/usr/share/serverchan/api/ipv4.list +++ b/luci-app-serverchan/root/usr/bin/serverchan/api/ipv4.list @@ -1,9 +1,9 @@ -www.cip.cc -ifcfg.cn -ddns.oray.com/checkip -www.net.cn/static/customercare/yourip.asp -myip.ipip.net/s -speed.neu.edu.cn/getIP.php -www.uc.cn/ip -ifcfg.cn -ip.3322.net +www.cip.cc +ifcfg.cn +ddns.oray.com/checkip +www.net.cn/static/customercare/yourip.asp +myip.ipip.net/s +speed.neu.edu.cn/getIP.php +www.uc.cn/ip +ifcfg.cn +ip.3322.net diff --git a/luci-app-serverchan/root/usr/share/serverchan/api/ipv6.list b/luci-app-serverchan/root/usr/bin/serverchan/api/ipv6.list similarity index 94% rename from luci-app-serverchan/root/usr/share/serverchan/api/ipv6.list rename to luci-app-serverchan/root/usr/bin/serverchan/api/ipv6.list index e8b6d6b1..5f1ca230 100644 --- a/luci-app-serverchan/root/usr/share/serverchan/api/ipv6.list +++ b/luci-app-serverchan/root/usr/bin/serverchan/api/ipv6.list @@ -1,5 +1,5 @@ -ip.sb -ipv6.ddnspod.com -api-ipv6.ip.sb/ip -speed.neu6.edu.cn/getIP.php -v6.myip.la/json +ip.sb +ipv6.ddnspod.com +api-ipv6.ip.sb/ip +speed.neu6.edu.cn/getIP.php +v6.myip.la/json diff --git a/luci-app-serverchan/root/usr/share/serverchan/api/logo.jpg b/luci-app-serverchan/root/usr/bin/serverchan/api/logo.jpg similarity index 100% rename from luci-app-serverchan/root/usr/share/serverchan/api/logo.jpg rename to luci-app-serverchan/root/usr/bin/serverchan/api/logo.jpg diff --git a/luci-app-serverchan/root/usr/share/serverchan/api/pushplus.json b/luci-app-serverchan/root/usr/bin/serverchan/api/pushplus.json similarity index 96% rename from luci-app-serverchan/root/usr/share/serverchan/api/pushplus.json rename to luci-app-serverchan/root/usr/bin/serverchan/api/pushplus.json index 965d2581..5fea8cba 100644 --- a/luci-app-serverchan/root/usr/share/serverchan/api/pushplus.json +++ b/luci-app-serverchan/root/usr/bin/serverchan/api/pushplus.json @@ -1,21 +1,21 @@ -{ - "_api": "这是 pushplus api 文件", - "_api": "【pushplus】", - - "url": "http://www.pushplus.plus/send", - "data": "@${tempjsonpath}", - "content_type": "Content-Type: application/json", - "str_title_start": "##### ", - "str_title_end": "", - "str_linefeed": "\\n", - "str_splitline": "\\n----\\n", - "str_space": " ", - "str_tab": " ", - "type": - { - "title": "\"${1}\"", - "content": "\"${2}\"", - "token": "\"${pushplus_token}\"", - "template":"\"markdown\"" - } -} +{ + "_api": "这是 pushplus api 文件", + "_api": "【pushplus】", + + "url": "http://www.pushplus.plus/send", + "data": "@${tempjsonpath}", + "content_type": "Content-Type: application/json", + "str_title_start": "##### ", + "str_title_end": "", + "str_linefeed": "\\n", + "str_splitline": "\\n----\\n", + "str_space": " ", + "str_tab": " ", + "type": + { + "title": "\"${1}\"", + "content": "\"${2}\"", + "token": "\"${pushplus_token}\"", + "template":"\"markdown\"" + } +} diff --git a/luci-app-serverchan/root/usr/share/serverchan/api/qywx_markdown.json b/luci-app-serverchan/root/usr/bin/serverchan/api/qywx_markdown.json similarity index 87% rename from luci-app-serverchan/root/usr/share/serverchan/api/qywx_markdown.json rename to luci-app-serverchan/root/usr/bin/serverchan/api/qywx_markdown.json index 35c53b7d..52511617 100644 --- a/luci-app-serverchan/root/usr/share/serverchan/api/qywx_markdown.json +++ b/luci-app-serverchan/root/usr/bin/serverchan/api/qywx_markdown.json @@ -1,23 +1,23 @@ -{ - "_api": "这是企业微信 markdown 模板信息 api 文件", - "_api": "【企业微信】", - - "url": "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$(curl -s \"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${corpid}&corpsecret=${corpsecret}\"|jq '.access_token' | sed 's/\"//g')", - "data": "@${tempjsonpath}", - "content_type": "Content-Type: application/json", - "str_title_start": "#### ", - "str_title_end": "", - "str_linefeed": "\\n", - "str_splitline": "\\n\\n", - "str_space": " ", - "str_tab": "> ", - "type": - { - "touser": "\"${userid}\"", - "msgtype": "\"markdown\"", - "agentid": "\"${agentid}\"", - "markdown": { - "content": "\"${1}${str_linefeed}${nowtime}${2}\"" - } - } -} +{ + "_api": "这是企业微信 markdown 模板信息 api 文件", + "_api": "【企业微信】", + + "url": "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$(curl -s \"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${corpid}&corpsecret=${corpsecret}\"|/usr/bin/jq '.access_token' | sed 's/\"//g')", + "data": "@${tempjsonpath}", + "content_type": "Content-Type: application/json", + "str_title_start": "#### ", + "str_title_end": "", + "str_linefeed": "\\n", + "str_splitline": "\\n\\n", + "str_space": " ", + "str_tab": "> ", + "type": + { + "touser": "\"${userid}\"", + "msgtype": "\"markdown\"", + "agentid": "\"${agentid}\"", + "markdown": { + "content": "\"${1}${str_linefeed}${nowtime}${2}\"" + } + } +} diff --git a/luci-app-serverchan/root/usr/share/serverchan/api/qywx_mpnews.json b/luci-app-serverchan/root/usr/bin/serverchan/api/qywx_mpnews.json similarity index 82% rename from luci-app-serverchan/root/usr/share/serverchan/api/qywx_mpnews.json rename to luci-app-serverchan/root/usr/bin/serverchan/api/qywx_mpnews.json index 258b7db7..4d452a4c 100644 --- a/luci-app-serverchan/root/usr/share/serverchan/api/qywx_mpnews.json +++ b/luci-app-serverchan/root/usr/bin/serverchan/api/qywx_mpnews.json @@ -1,33 +1,33 @@ -{ - "_api": "这是企业微信图文信息 api 文件", - "_api": "【企业微信】", - - "url": "\"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$(curl -s \"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${corpid}&corpsecret=${corpsecret}\"|jq '.access_token'|sed 's/\"//g')\"", - "data": "@${tempjsonpath}", - "content_type": "Content-Type: application/json", - "str_title_start": "

", - "str_title_end": "

", - "str_linefeed": "\\n", - "str_splitline": "
", - "str_space": " ", - "str_tab": "
  • ", - "type": - { - "touser": "\"${userid}\"", - "msgtype": "\"mpnews\"", - "agentid": "\"${agentid}\"", - "mpnews":{ - "articles":[ - { - "title": "\"${nowtime}${str_linefeed}${1}\"", - "thumb_media_id": "\"`curl \"https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=$(curl -s \"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${corpid}&corpsecret=${corpsecret}\"|jq '.access_token'|sed 's/\"//g')&type=image\" -F \"file=@${mediapath}\"|jq '.media_id'|sed 's/\"//g'`\"", - "author": "\"\"", - "content_source_url": "\"\"", - "content": "\"${2}\"", - "digest": "\"\"" - } - ] - }, - "safe":0 - } -} +{ + "_api": "这是企业微信图文信息 api 文件", + "_api": "【企业微信】", + + "url": "\"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$(curl -s \"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${corpid}&corpsecret=${corpsecret}\"|/usr/bin/jq '.access_token'|sed 's/\"//g')\"", + "data": "@${tempjsonpath}", + "content_type": "Content-Type: application/json", + "str_title_start": "

    ", + "str_title_end": "

    ", + "str_linefeed": "\\n", + "str_splitline": "
    ", + "str_space": " ", + "str_tab": "
  • ", + "type": + { + "touser": "\"${userid}\"", + "msgtype": "\"mpnews\"", + "agentid": "\"${agentid}\"", + "mpnews":{ + "articles":[ + { + "title": "\"${nowtime}${str_linefeed}${1}\"", + "thumb_media_id": "\"`curl \"https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=$(curl -s \"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${corpid}&corpsecret=${corpsecret}\"|/usr/bin/jq '.access_token'|sed 's/\"//g')&type=image\" -F \"file=@${mediapath}\"|/usr/bin/jq '.media_id'|sed 's/\"//g'`\"", + "author": "\"\"", + "content_source_url": "\"\"", + "content": "\"${2}\"", + "digest": "\"\"" + } + ] + }, + "safe":0 + } +} diff --git a/luci-app-serverchan/root/usr/share/serverchan/api/serverchan.json b/luci-app-serverchan/root/usr/bin/serverchan/api/serverchan.json similarity index 96% rename from luci-app-serverchan/root/usr/share/serverchan/api/serverchan.json rename to luci-app-serverchan/root/usr/bin/serverchan/api/serverchan.json index a0a8245e..116e3f20 100644 --- a/luci-app-serverchan/root/usr/share/serverchan/api/serverchan.json +++ b/luci-app-serverchan/root/usr/bin/serverchan/api/serverchan.json @@ -1,17 +1,17 @@ -{ - "_api": "这是 serverchan api 文件", - "_api": "【serverchan】", - - "url": "\"https://sctapi.ftqq.com/${sckey}.send\"", - "data": "\"text=${1}&desp=${nowtime}${str_linefeed}${2}\"", - "content_type": "Content-Type:application/x-www-form-urlencoded", - "str_title_start": "#### ", - "str_title_end": "", - "str_linefeed": "%0D%0A%0D%0A", - "str_splitline": "%0D%0A%0D%0A----%0D%0A%0D%0A", - "str_space": " ", - "str_tab": " ", - "type": - { - } -} +{ + "_api": "这是 serverchan api 文件", + "_api": "【serverchan】", + + "url": "\"https://sctapi.ftqq.com/${sckey}.send\"", + "data": "\"text=${1}&desp=${nowtime}${str_linefeed}${2}\"", + "content_type": "Content-Type:application/x-www-form-urlencoded", + "str_title_start": "#### ", + "str_title_end": "", + "str_linefeed": "%0D%0A%0D%0A", + "str_splitline": "%0D%0A%0D%0A----%0D%0A%0D%0A", + "str_space": " ", + "str_tab": " ", + "type": + { + } +} diff --git a/luci-app-serverchan/root/usr/share/serverchan/api/telegram.json b/luci-app-serverchan/root/usr/bin/serverchan/api/telegram.json similarity index 96% rename from luci-app-serverchan/root/usr/share/serverchan/api/telegram.json rename to luci-app-serverchan/root/usr/bin/serverchan/api/telegram.json index 3638365c..a8c57b04 100644 --- a/luci-app-serverchan/root/usr/share/serverchan/api/telegram.json +++ b/luci-app-serverchan/root/usr/bin/serverchan/api/telegram.json @@ -1,20 +1,20 @@ -{ - "_api": "这是 telegram api 文件", - "_api": "【telegram】", - - "url": "https://api.telegram.org/bot${tg_token}/sendMessage", - "data": "@${tempjsonpath}", - "content_type": "Content-Type: application/json", - "str_title_start": "", - "str_title_end": "", - "str_linefeed": "\\n", - "str_splitline": "\\n----\\n", - "str_space": " ", - "str_tab": " ", - "type": - { - "text":"\"${str_title_start}${1}${str_title_end}${str_splitline}${nowtime}${2}\"", - "chat_id":"\"${chat_id}\"", - "parse_mode":"\"HTML\"" - } -} +{ + "_api": "这是 telegram api 文件", + "_api": "【telegram】", + + "url": "https://api.telegram.org/bot${tg_token}/sendMessage", + "data": "@${tempjsonpath}", + "content_type": "Content-Type: application/json", + "str_title_start": "", + "str_title_end": "", + "str_linefeed": "\\n", + "str_splitline": "\\n----\\n", + "str_space": " ", + "str_tab": " ", + "type": + { + "text":"\"${str_title_start}${1}${str_title_end}${str_splitline}${nowtime}${2}\"", + "chat_id":"\"${chat_id}\"", + "parse_mode":"\"HTML\"" + } +} diff --git a/luci-app-serverchan/root/usr/share/serverchan/api/wxpusher.json b/luci-app-serverchan/root/usr/bin/serverchan/api/wxpusher.json similarity index 96% rename from luci-app-serverchan/root/usr/share/serverchan/api/wxpusher.json rename to luci-app-serverchan/root/usr/bin/serverchan/api/wxpusher.json index 20443462..83e1a78e 100644 --- a/luci-app-serverchan/root/usr/share/serverchan/api/wxpusher.json +++ b/luci-app-serverchan/root/usr/bin/serverchan/api/wxpusher.json @@ -1,23 +1,23 @@ -{ - "_api": "这是 wxpusher api 文件", - "_api": "【wxpusher】", - - "url": "http://wxpusher.zjiecode.com/api/send/message", - "data": "@${tempjsonpath}", - "content_type": "Content-Type: application/json", - "str_title_start": "#### ", - "str_title_end": "", - "str_linefeed": "\\n", - "str_splitline": "\\n----\\n", - "str_space": " ", - "str_tab": " ", - "type": - { - "summary":"\"${1}\"", - "content":"\"${2}\"", - "appToken":"\"${wxpusher_apptoken}\"", - "topicIds":"[\"${wxpusher_topicIds}\"]", - "uids":"[\"${wxpusher_uids}\"]", - "contentType":3 - } -} +{ + "_api": "这是 wxpusher api 文件", + "_api": "【wxpusher】", + + "url": "http://wxpusher.zjiecode.com/api/send/message", + "data": "@${tempjsonpath}", + "content_type": "Content-Type: application/json", + "str_title_start": "#### ", + "str_title_end": "", + "str_linefeed": "\\n", + "str_splitline": "\\n----\\n", + "str_space": " ", + "str_tab": " ", + "type": + { + "summary":"\"${1}\"", + "content":"\"${2}\"", + "appToken":"\"${wxpusher_apptoken}\"", + "topicIds":"[\"${wxpusher_topicIds}\"]", + "uids":"[\"${wxpusher_uids}\"]", + "contentType":3 + } +} diff --git a/luci-app-serverchan/root/usr/share/serverchan/serverchan b/luci-app-serverchan/root/usr/bin/serverchan/serverchan similarity index 93% rename from luci-app-serverchan/root/usr/share/serverchan/serverchan rename to luci-app-serverchan/root/usr/bin/serverchan/serverchan index 801f7988..c32737a0 100755 --- a/luci-app-serverchan/root/usr/share/serverchan/serverchan +++ b/luci-app-serverchan/root/usr/bin/serverchan/serverchan @@ -1,1259 +1,1259 @@ -#!/bin/sh - -# 读取设置文件 -function get_config(){ - while [[ "$*" != "" ]]; do - eval ${1}='`uci get serverchan.serverchan.$1`' 2>/dev/null - shift - done -} - -# 初始化设置信息 -function read_config(){ - get_config "serverchan_enable" "lite_enable" "device_name" "sleeptime" "oui_data" "oui_dir" "reset_regularly" "debuglevel" "device_aliases" \ - "serverchan_ipv4" "ipv4_interface" "serverchan_ipv6" "ipv6_interface" "serverchan_up" "serverchan_down" "cpuload_enable" "cpuload" "temperature_enable" "temperature" "client_usage" "client_usage_max" "client_usage_disturb" "client_usage_whitelist" "web_logged" "ssh_logged" "web_login_failed" "ssh_login_failed" "login_max_num" "web_login_black" "ip_white_list" "ip_black_timeout"\ - "regular_time" "regular_time_2" "regular_time_3" "interval_time" \ - "serverchan_sheep" "starttime" "endtime" "serverchan_whitelist" "serverchan_blacklist" "serverchan_interface" "MAC_online_list" "MAC_offline_list" \ - "up_timeout" "down_timeout" "timeout_retry_count" "thread_num" "soc_code" "server_host" "server_port" "err_enable" "err_sheep_enable" "err_device_aliases" "network_err_event" "system_time_event" "autoreboot_time" "network_restart_time" "public_ip_event" "public_ip_retry_count" \ - "jsonpath" "sckey" "corpid" "userid" "agentid" "corpsecret" "mediapath" "wxpusher_apptoken" "wxpusher_uids" "wxpusher_topicIds" "pushplus_token" "tg_token" "chat_id" \ - "gateway_info_enable" "gateway_host_url" "gateway_info_url" "gateway_logout_url" "gateway_username_id" "gateway_password_id" "gateway_username" "gateway_password" - - for str_version in "wrtbwmon" "iputils-arping" "curl" "iw"; do - eval `echo ${str_version:0:2}"_version"`=`opkg list-installed|grep -w ^${str_version}|awk '{print $3}'` 2>/dev/null - done - dir="/tmp/serverchan/" && mkdir -p ${dir} && mkdir -p ${dir}/client - tempjsonpath="/tmp/serverchan/temp.json" - ip_blacklist_path="/usr/share/serverchan/api/ip_blacklist" - [ ! -z "$oui_dir" ] && [ "$oui_dir" -eq "1" ] && oui_base="${dir}oui_base.txt" || oui_base="/usr/share/serverchan/oui_base.txt" - debuglevel=`echo "$debuglevel"` && [ -z "$debuglevel" ] && logfile="/dev/null" || logfile="${dir}serverchan.log" - serverchan_blacklist=`echo "$serverchan_blacklist"|sed 's/ /\n/g'` 2>/dev/null - serverchan_whitelist=`echo "$serverchan_whitelist"|sed 's/ /\n/g'` 2>/dev/null - device_aliases=`echo "$device_aliases"|sed 's/ /\n/g'|sed 's/-/ /'` 2>/dev/null - err_device_aliases=`echo "$err_device_aliases"|sed 's/ /\n/g'` 2>/dev/null - client_usage_whitelist=`echo "$client_usage_whitelist"|sed 's/ /\n/g'` 2>/dev/null - ip_white_list=`echo "$ip_white_list"|sed 's/ /\n/g'` 2>/dev/null - mark_mac_list="${MAC_online_list} ${MAC_offline_list}" - mark_mac_list=`echo "$mark_mac_list"|sed 's/ /\n/g'|sed 's/-/ /'` 2>/dev/null - ipv4_urllist=`cat /usr/share/serverchan/api/ipv4.list` 2>/dev/null - ipv6_urllist=`cat /usr/share/serverchan/api/ipv6.list` 2>/dev/null - [ -z "$serverchan_ipv4" ] && serverchan_ipv4=0 - [ -z "$serverchan_ipv6" ] && serverchan_ipv6=0 - [ "$iw_version" ] && wlan_interface=`iw dev|grep Interface|awk '{print $2}'` >/dev/null 2>&1 - [ -z "$up_timeout" ] || [ "$up_timeout" -eq "0" ] && up_timeout="2" - [ -z "$down_timeout" ] || [ "$down_timeout" -eq "0" ] && down_timeout="20";down_timeout=`expr ${down_timeout} / 2 + 1` - [ -z "$timeout_retry_count" ] && timeout_retry_count="2";[ "$timeout_retry_count" -eq "0" ] && timeout_retry_count="1" - [ -z "$server_port" ] && server_port="22" - str_title_start=`jq -r '.str_title_start' ${jsonpath}` - str_title_end=`jq -r '.str_title_end' ${jsonpath}` - str_linefeed=`jq -r '.str_linefeed' ${jsonpath}` - str_splitline=`jq -r '.str_splitline' ${jsonpath}` - str_space=`jq -r '.str_space' ${jsonpath}` - str_tab=`jq -r '.str_tab' ${jsonpath}` - ( echo "$lite_enable"|grep -q "content" ) && str_title_start="" && str_title_end="" && str_splitline="" && str_linefeed="" && str_tab="" -} - -# 初始化 -function serverchan_init(){ - enable_detection - if [ -f "/usr/share/serverchan/errlog" ]; then - cat /usr/share/serverchan/errlog > ${logfile} - echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】载入上次重启前日志" >> ${logfile} - echo "--------------------------------------------------------" >> ${logfile} - fi - down_oui & - get_syslog - add_ip_black - - rm -f ${dir}fd1 ${dir}sheep_usage ${dir}old_sheep_usage ${dir}client_usage_aliases ${dir}old_client_usage_aliases /usr/share/serverchan/errlog >/dev/null 2>&1 - [ ! -f "/usr/sbin/wrtbwmon" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】未安装 wrtbwmon ,流量统计不可用" >> ${logfile} - [ -z "$ip_version" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】无法获取依赖项 iputils-arping 版本号,请确认插件是否正常运行" >> ${logfile} - [ -z "$cu_version" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】无法获取依赖项 curl 版本号,请确认插件是否正常运行" >> ${logfile} - [ -z "${sckey}${tg_token}${pushplus_token}${corpid}${wxpusher_apptoken}${wxpusher_uids}${wxpusher_topicIds}" -a "${jsonpath}" != "/usr/share/serverchan/api/diy.json" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】请填写正确的 key " >> ${logfile} && return 1 - local interfacelist=`getinterfacelist` && [ -z "$interfacelist" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】无法获取接口在线时间等信息,可能存在多个接口或配置错误,请确认插件是否正常运行" >> ${logfile} - return 0 -} - -# 推送 -function diy_send(){ - ( ! echo "$lite_enable"|grep -q "content" ) && ( ! echo "$lite_enable"|grep -q "nowtime" ) && local nowtime=`date "+%Y-%m-%d %H:%M:%S"` - local diyurl=`jq -r .url ${3}` && local diyurl=`eval echo ${diyurl}` - local type=`jq -r '.type' ${3}` && local type=`eval echo ${type}` - local data=`jq -r '.data' ${3}` && local data=`eval echo ${data}` - local content_type=`jq -r '.content_type' ${3}` - jq ".type + $type" ${jsonpath} > ${tempjsonpath} - - jq -r '.[]' ${tempjsonpath}|grep -w "null" && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】参数值错误,请检查设置项 `jq -r '.' ${tempjsonpath}|grep "null"`" >> ${logfile} && return 1 - [ -f ${tempjsonpath} ] && local logrow=$(grep -c "" ${tempjsonpath}) || local logrow="0" - [ $logrow -eq "0" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】json 文件生成失败,请检查文件格式" >> ${logfile} && return 1 - jq -r '.[]' ${tempjsonpath}|grep "null" && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】参数变量生成失败,请检查设置项 `jq -r '.' ${tempjsonpath}|grep "null"`" >> ${logfile} - - curl -X POST -H "$content_type" -d "${data}" "${diyurl}" -} - -# 下载设备MAC厂商信息 -function down_oui(){ - [ -f ${oui_base} ] && local logrow=$(grep -c "" ${oui_base}) || local logrow="0" - [ $logrow -lt "10" ] && rm -f ${oui_base} >/dev/null 2>&1 - if [ ! -z "$oui_data" ] && [ "$oui_data" -ne "3" ] && [ ! -f ${oui_base} ]; then - echo "`date "+%Y-%m-%d %H:%M:%S"` 【初始化】设备MAC厂商信息不存在,重新下载" >> ${logfile} - wget --no-check-certificate -t 3 -T 15 -O ${dir}oui.txt https://standards-oui.ieee.org/oui/oui.txt >/dev/null 2>&1 - if [ -f ${dir}oui.txt ] && [ "$oui_data" -eq "1" ]; then - cat ${dir}oui.txt|grep "base 16"|grep -i "apple\|aruba\|asus\|autelan\|belkin\|bhu\|buffalo\|cctf\|cisco\|comba\|datang\|dell\|dlink\|dowell\|ericsson\|fast\|feixun\|\ -fiberhome\|fujitsu\|grentech\|h3c\|hisense\|hiwifi\|honghai\|honghao\|hp\|htc\|huawei\|intel\|jinli\|jse\|lenovo\|lg\|liteon\|malata\|meizu\|mercury\|meru\|moto\|netcore\|\ -netgear\|nokia\|omron\|oneplus\|oppo\|philips\|router_unkown\|samsung\|shanzhai\|sony\|start_net\|sunyuanda\|tcl\|tenda\|texas\|tianyu\|tp-link\|ubq\|undefine\|VMware\|\ -utstarcom\|volans\|xerox\|xiaomi\|zdc\|zhongxing\|smartisan" > ${oui_base} && echo "`date "+%Y-%m-%d %H:%M:%S"` 【初始化】设备MAC厂商信息下载成功" >> ${logfile} || echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】设备MAC厂商信息下载失败" >> ${logfile} - fi - if [ -f ${dir}oui.txt ] && [ "$oui_data" -eq "2" ]; then - cat ${dir}oui.txt|grep "base 16" > ${oui_base} && echo "`date "+%Y-%m-%d %H:%M:%S"` 【初始化】设备MAC厂商信息下载成功" >> ${logfile} || echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】设备MAC厂商信息下载失败" >> ${logfile} - fi - rm -f ${dir}oui.txt >/dev/null 2>&1 - fi -} - -# 清理临时文件 -function deltemp(){ - unset title content ipAddress_logrow online_list online_mac mac_online_status gatewayinfo gateway_iplist - rm -f ${dir}title ${dir}content ${dir}tmp_downlist ${dir}send_enable.lock ${tempjsonpath} ${dir}cookies.txt >/dev/null 2>&1 - [ ! -f ${dir}ipAddress ] && rm -f ${dir}client/* >/dev/null 2>&1 - LockFile unlock - [ -f ${logfile} ] && local logrow=$(grep -c "" ${logfile}) || local logrow="0" - [ $logrow -gt 500 ] && sed -i '1,100d' ${logfile} && echo "`date "+%Y-%m-%d %H:%M:%S"` 【清理】日志超出上限,删除前 100 条" >> ${logfile} -} - -# 检测程序开关 -function enable_detection(){ - [ ! "$1" ] && local time_n=1 - for i in `seq 1 $time_n`; do - get_config serverchan_enable;[ -z "$serverchan_enable" ] || [ "$serverchan_enable" -eq "0" ] && `/etc/init.d/serverchan stop` || sleep 1 - done -} - -# 获取 ip -function getip(){ - [ ! "$1" ] && return - if [ $1 == "wanipv4" ] ;then - [ ! -z "$ipv4_interface" ] && local wanIP=$(/sbin/ifconfig ${ipv4_interface}|awk '/inet addr/ {print $2}'|awk -F: '{print $2}'|grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') - [ -z "$ipv4_interface" ] && local wanIP=$(getinterfacelist|grep '\"address\"'|grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') - echo "$wanIP" - elif [ $1 == "hostipv4" ] ;then - function get_hostipv4() - { - local url_number=`echo "$ipv4_urllist"|wc -l` - local ipv4_URL=`echo "$ipv4_urllist"| sed -n "$(rand 1 $url_number)p"|sed -e 's/\r//g'` - [ ! -z "$ipv4_interface" ] && local hostIP=$(curl -k -s -4 --interface ${ipv4_interface} -m 5 ${ipv4_URL}) || local hostIP=$(curl -k -s -4 -m 5 ${ipv4_URL}) - echo $hostIP|grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'|head -n1 - } - local hostIP=`get_hostipv4` - [ -z "$hostIP" ] && sleep 1 && local hostIP=`get_hostipv4` - [ -z "$hostIP" ] && sleep 1 && local hostIP=`get_hostipv4` - echo $hostIP # 重试,偷懒,有空再优化 - elif [ $1 == "wanipv6" ] ;then - [ ! -z "$ipv6_interface" ] && local wanIPv6=$(ip addr show ${ipv6_interface}|grep -v deprecated|grep -A1 'inet6 [^f:]'|sed -nr ':a;N;s#^ +inet6 ([a-f0-9:]+)/.+? scope global .*? valid_lft ([0-9]+sec) .*#\2 \1#p;ta'|sort -nr|head -n1|awk '{print $2}') - [ -z "$ipv6_interface" ] && local wanIPv6=$(ip addr show|grep -v deprecated|grep -A1 'inet6 [^f:]'|sed -nr ':a;N;s#^ +inet6 ([a-f0-9:]+)/.+? scope global .*? valid_lft ([0-9]+sec) .*#\2 \1#p;ta'|sort -nr|head -n1|awk '{print $2}') - echo "$wanIPv6" - elif [ $1 == "hostipv6" ] ;then - function get_hostipv6() - { - local urlv6_number=`echo "$ipv6_urllist"|wc -l` - local ipv6_URL=`echo "$ipv6_urllist"| sed -n "$(rand 1 $urlv6_number)p"|sed -e 's/\r//g'` - [ ! -z "$ipv6_interface" ] && local hostIPv6=$(curl -k -s -6 --interface ${ipv6_interface} -m 5 ${ipv6_URL}) || local hostIPv6=$(curl -k -s -6 -m 5 ${ipv6_URL}) - echo $hostIPv6|grep -oE '([\da-fA-F0-9]{1,4}(:{1,2})){1,15}[\da-fA-F0-9]{1,4}'|head -n1 - } - local hostIPv6=`get_hostipv6` - [ -z "$hostIPv6" ] && sleep 1 && local hostIPv6=`get_hostipv6` - [ -z "$hostIPv6" ] && sleep 1 && local hostIPv6=`get_hostipv6` - echo $hostIPv6 # 重试,偷懒,有空再优化 - fi -} - -# 获取接口信息 -function getinterfacelist(){ - [ `ubus list|grep -w -i "network.interface.wan"|wc -l` -ge "1" ] && ubus call network.interface.wan status && return - local ubuslist=`ubus list|grep -i "network.interface."|grep -v "loopback"|grep -v -i "wan6"|grep -v -i "lan6"|grep -v -i "ipsec_server"` - [ `echo "${ubuslist}" |wc -l` -eq "1" ] && ubus call ${ubuslist} status && return -} - -# 获取接口在线时间 -function getinterfaceuptime(){ - getinterfacelist|grep \"uptime\"|sed $'s/\"uptime": //g'|sed $'s/\,//g' -} - -# 查询 MAC 地址 -function getmac(){ - [ -f "${dir}ipAddress" ] && local tmp_mac=`cat ${dir}ipAddress|grep -w ${1}|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` - ( echo "$tmp_mac"|grep -q "unknown" ) && unset tmp_mac # 为unknown时重新读取 - [ -f "${dir}tmp_downlist" ] && [ -z "$tmp_mac" ] && local tmp_mac=`cat ${dir}tmp_downlist|grep -w ${1}|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` - ( echo "$tmp_mac"|grep -q "unknown" ) && unset tmp_mac # 为unknown时重新读取 - [ -f "/tmp/dhcp.leases" ] && [ -z "$tmp_mac" ] && local tmp_mac=`cat /tmp/dhcp.leases|grep -w ${1}|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` - [ -z "$tmp_mac" ] && local tmp_mac=`cat /proc/net/arp|grep "0x2\|0x6"|grep -w ${1}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` - [ -z "$tmp_mac" ] && local tmp_mac="unknown" - echo $tmp_mac |tr -d '\n\r' -} - -# 查询主机名 -function getname(){ - local tmp_name=`echo "$device_aliases"|grep -i $2|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` - [ -f "${dir}ipAddress" ] && [ -z "$tmp_name" ] && local tmp_name=`cat ${dir}ipAddress|grep -w ${1}|awk '{print $3}'|grep -v "^$"|sort -u|head -n1` - ( ! echo "$tmp_name"|grep -q -w "unknown\|*" ) && [ ! -z "$tmp_name" ] && echo "$tmp_name" && return || unset tmp_name # 为unknown时重新读取 - [ -f "${dir}tmp_downlist" ] && [ -z "$tmp_name" ] && local tmp_name=`cat ${dir}tmp_downlist|grep -w ${1}|awk '{print $3}'|grep -v "^$"|sort -u|head -n1` - ( ! echo "$tmp_name"|grep -q -w "unknown\|*" ) && [ ! -z "$tmp_name" ] && echo "$tmp_name" && return || unset tmp_name # 为unknown时重新读取 - [ -f "/tmp/dhcp.leases" ] && [ -z "$tmp_name" ] && local tmp_name=`cat /tmp/dhcp.leases|grep -w ${1}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` - ( ! echo "$tmp_name"|grep -q -w "unknown\|*" ) && [ ! -z "$tmp_name" ] && echo "$tmp_name" && return || unset tmp_name # 为unknown时重新读取 - [ -z "$dhcp_config" ] && dhcp_config=`uci show dhcp|grep "ip\|mac\|name"` - for dhcp_config_str in "host" "domain"; do - local dhcp_ip_n=`echo "$dhcp_config"|grep -w ^dhcp.@${dhcp_config_str}.*ip=.${1}|sed -nr 's#^dhcp.(.*).ip.*#\1#gp'` 2>/dev/null - [ ! -z "$dhcp_ip_n" ] && [ -z "$tmp_name" ] && local tmp_name=`uci get dhcp.${dhcp_ip_n}.name` 2>/dev/null - local dhcp_mac_n=`echo "$dhcp_config"|grep -i ^dhcp.@${dhcp_config_str}.*mac=.${2}|sed -nr 's#^dhcp.(.*).mac.*#\1#gp'` 2>/dev/null - [ ! -z "$dhcp_mac_n" ] && [ -z "$tmp_name" ] && local tmp_name=`uci get dhcp.${dhcp_ip_n}.name` 2>/dev/null - [ ! -z "$tmp_name" ] && break - done - ( ! echo "$tmp_name"|grep -q -w "unknown\|*" ) && [ ! -z "$tmp_name" ] && echo "$tmp_name" && return || unset tmp_name # 为unknown时重新读取 - local tmp_name=`echo "$gatewayinfo"|grep -w ${1}|awk '{print $2}'` - ( ! echo "$tmp_name"|grep -q -w "unknown\|*" ) && [ ! -z "$tmp_name" ] && echo "$tmp_name" && return || unset tmp_name # 为unknown时重新读取 - [ -f "$oui_base" ] && local tmp_name=$(cat $oui_base|grep -i $(echo "$2"|cut -c 1,2,4,5,7,8)|sed -nr 's#^.*16)..(.*)#\1#gp'|sed 's/ /_/g') - [ ! -z "$oui_data" ] && [ "$oui_data" -eq "4" ] && local tmp_name=$(curl -sS "https://standards-oui.ieee.org/oui/oui.txt"|grep -i $(echo "$2"|cut -c 1,2,4,5,7,8)|sed -nr 's#^.*16)..(.*)#\1#gp'|sed 's/ /_/g') - [ -z "$tmp_name" ] && local tmp_name="unknown" - echo $tmp_name |tr -d '\n\r' -} - -# 从光猫处获取设备信息 -function getgateway(){ - local loginfo=`curl -s -L "${gateway_host_url}" -c ${dir}cookies.txt -d "${gateway_username_id}=${gateway_username}&${gateway_password_id}=${gateway_password}"` 2>/dev/null - [ ! -z "$loginfo" ] && local mytoken=$(echo $loginfo |sed 's/{/\n/g' | grep token |awk '/realRestart/{print $2}'| sed $'s/\'//g') - [ ! -z "$mytoken" ] && local get_gateway=`curl -s -b ${dir}cookies.txt "${gateway_info_url}" -d 'token='$mytoken | jq '.[] | iterables| "\(.ip) \(.devName) \(.model)"'|sed 's/unknown//g'|sed 's/ / /g'|sed 's/ /_/g'|sed 's/_/ /'|sed 's/\"//g'` - [ ! -z "$get_gateway" ] && curl -s -b ${dir}cookies.txt "${gateway_logout_url}" -d 'token='$mytoken 2>/dev/null - echo "$get_gateway" -} - -# 查询设备接口 -function getinterface(){ - [ -z "${1}" ] && return - [ "${1}" == "unknown" ] && return - [ -f "${dir}ipAddress" ] && local ip_interface=`cat ${dir}ipAddress|grep -w ${1}|awk '{print $5}'|grep -v "^$"|sort -u|head -n1` - [ -f "${dir}tmp_downlist" ] && [ -z "$ip_interface" ] && local ip_interface=`cat ${dir}tmp_downlist|grep -w ${1}|awk '{print $5}'|grep -v "^$"|sort -u|head -n1` - if [ -z "$ip_interface" ] && [ ! -z "$wlan_interface" ]; then - for interface in $wlan_interface; do - local ip_interface=`iw dev $interface station dump 2>/dev/null|grep Station|grep -i -w ${1}|sed -nr 's#^.*on (.*))#\1#gp'` >/dev/null 2>&1 - [ ! -z "$ip_interface" ] && echo "$ip_interface" && return - done - fi - [ -z "$ip_interface" ] && local ip_interface=`cat /proc/net/arp|grep "0x2\|0x6"|grep -i -w ${1}|awk '{print $6}'|grep -v "^$"|sort -u|head -n1` - echo $ip_interface |tr -d '\n\r' -} - -# ping -function getping(){ - local ip_interface=`getinterface ${2}` - [ "$iw_version" ] && [ "$ip_interface" ] && local wlan_online=`iw dev ${ip_interface} station dump|grep -i -w ${2}|grep Station` >/dev/null 2>&1 - [ "$wlan_online" ] && return 0 - for i in `seq 1 ${4}`; do - ( ! echo "$ip_ms"|grep -q "ms" ) && local interface=`cat /proc/net/arp|grep -w ${1}|awk '{print $6}'|grep -v "^$"|sort -u|head -n1` && [ ! -z "$interface" ] && local ip_ms=`arping -I ${interface} -c 20 -f -w ${3} ${1}` 2>/dev/null - ( ! echo "$ip_ms"|grep -q "ms" ) && local ip_ms=`ping -c 5 -w ${3} ${1}|grep -v '100% packet loss'` 2>/dev/null - ( ! echo "$ip_ms"|grep -q "ms" ) && sleep 1 - done - ( echo "$ip_ms"|grep -q "ms" ) -} - -# CPU 占用率 -function getcpu(){ - local AT=$(cat /proc/stat|grep "^cpu "|awk '{print $2+$3+$4+$5+$6+$7+$8 " " $2+$3+$4+$7+$8}') - sleep 3 - local BT=$(cat /proc/stat|grep "^cpu "|awk '{print $2+$3+$4+$5+$6+$7+$8 " " $2+$3+$4+$7+$8}') - printf "%.01f%%" $(echo ${AT} ${BT}|awk '{print (($4-$2)/($3-$1))*100}') -} - -# 获取SOC温度 (取所有传感器温度最大值) -function soc_temp(){ - [ -z "$soc_code" ] && local soctemp=`sensors 2>/dev/null|grep °C|sed -nr 's#^.*:.*\+(.*)°C .*#\1#gp'|sort -nr|head -n1` - [ -z "$soc_code" ] && [ -z "$soctemp" ] && local soctemp=`cat /sys/class/thermal/thermal_zone*/temp 2>/dev/null|sort -nr|head -n1|cut -c-2` - [ "$soc_code" == "pve" ] && [ ! -z "$server_host" ] && local soctemp=`ssh -i /root/.ssh/id_rsa root@${server_host} -p ${server_port} sensors 2>/dev/null|grep Core|sed -nr 's#^.*:.*\+(.*)°C .*#\1#gp'|sort -nr|head -n1` - [ ! -z "$soctemp" ] && echo "$soctemp" && return - [ ! -z "$soc_code" ] && eval `echo "$soc_code"` 2>/dev/null -} - -# 流量数据 -function usage(){ - [ ! -f "/usr/sbin/wrtbwmon" ] || [ ! "$1" ] && return - if [ $1 == "update" ] ;then - function version_le() { test "$(echo "$@"|tr " " "\n"|sort -n|head -n 1)" == "$1"; } - function version_ge() { test "$(echo "$@"|tr " " "\n"|sort -r|head -n 1)" == "$1"; } - [ ! -z "$wr_version" ] && ( version_ge "${wr_version}" "1.2.0" ) && wrtbwmon -f ${dir}usage.db 2>/dev/null && return - [ ! -z "$wr_version" ] && ( version_le "${wr_version}" "1.0.0" ) || [ -z "$wr_version" ] && wrtbwmon update ${dir}usage.db 2>/dev/null && return - elif [ $1 == "get" ] ;then - [ ! -f "${dir}usage.db" ] && [ ! "$3" ] && echo `bytes_for_humans 0` && return - [ ! -f "${dir}usage.db" ] && [ "$3" ] && echo 0 && return - [ -z "$total_n" ] && total_n=`cat ${dir}usage.db|head -n1|grep "total"|sed 's/,/\n/g'|awk '/total/{print NR}'` 2>/dev/null - [ -z "$total_n" ] && total_n="6" - [ "$2" ] && local tmptotal=`cat ${dir}usage.db|sed 's/,,,/,0,0,/g'|sed 's/,,/,0,/g'|sed 's/,/ /g'|grep -i -w ${2}|awk "{print "'$'$total_n"}"|grep -v "^$"|sort -u|head -n1` 2>/dev/null - [ -z "$tmptotal" ] && local tmptotal="0" - [ ! "$3" ] && echo `bytes_for_humans ${tmptotal}` || echo $tmptotal - elif [ $1 == "down" ] ;then - [ "$2" ] && sed -i "/,${2},/d" ${dir}usage.db 2>/dev/null - fi -} - -# 流量数据单位换算 -function bytes_for_humans { - [ ! "$1" ] && return - [ "$1" -gt 1073741824 ] && echo "`awk 'BEGIN{printf "%.2f\n",'$1'/'1073741824'}'` GB" && return - [ "$1" -gt 1048576 ] && echo "`awk 'BEGIN{printf "%.2f\n",'$1'/'1048576'}'` MB" && return - [ "$1" -gt 1024 ] && echo "`awk 'BEGIN{printf "%.2f\n",'$1'/'1024'}'` KB" && return - echo "${1} bytes" -} - -# 设备异常流量检测 -function get_client_usage(){ - [ -z "$client_usage" ] && return - [ "$client_usage" -ne "1" ] && return - [ -z "$client_usage_max" ] && return - [ -z "$get_client_usage_time" ] && get_client_usage_time=`date +%s` - ( echo $client_usage_max|sed -r 's/.*(.)$/\1/'|grep -q "K\|k" ) && client_usage_max=`expr ${client_usage_max%?} \* 1024` - ( echo $client_usage_max|sed -r 's/.*(.)$/\1/'|grep -q "M\|m" ) && client_usage_max=`expr ${client_usage_max%?} \* 1048576` - ( echo $client_usage_max|sed -r 's/.*(.)$/\1/'|grep -q "G\|g" ) && client_usage_max=`expr ${client_usage_max%?} \* 1073741824` - [ -z "$client_usage_disturb" ] && client_usage_disturb="0" - [ "$client_usage_disturb" -eq "0" ] && [ -f "${dir}ipAddress" ] && local MACLIST=`cat ${dir}ipAddress|awk '{print $2}'|grep -v "^$"|sort -u` - [ "$client_usage_disturb" -eq "1" ] && [ ! -z "$client_usage_whitelist" ] && local MACLIST=`echo "$client_usage_whitelist"` - [ -z "$MACLIST" ] && return - - if [ "$((`date +%s`-$get_client_usage_time))" -ge "60" ]; then - > ${dir}client_usage_aliases - for mac in $MACLIST; do - ( ! cat ${dir}ipAddress|grep -q -i -w $mac|grep -v "^$"|sort -u|head -n1 ) && continue - echo "$mac" `usage get ${mac} bytes` >> ${dir}client_usage_aliases - [ -f "${dir}old_client_usage_aliases" ] && get_client_usage_bytes=`cat ${dir}old_client_usage_aliases|grep -i -w $mac|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` || continue - [ -z "$get_client_usage_bytes" ] && get_client_usage_bytes="0" - if [ "$((`usage get ${mac} bytes`-$get_client_usage_bytes))" -ge "$client_usage_max" ]; then - local ip=`cat ${dir}ipAddress|grep -i -w $mac|awk '{print $1}'|grep -v "^$"|sort -u|head -n1` - local ip_name=`getname ${ip} ${mac}` - local tmp_usage=$(bytes_for_humans $(expr `usage get ${mac} bytes` - ${get_client_usage_bytes})) - local time_up=`cat ${dir}ipAddress|grep -w ${ip}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` - local ip_total=`usage get $mac` && [ ! -z "$ip_total" ] && local ip_total="${str_linefeed}${str_tab}总计流量: ${str_space}${str_space}${str_space}${str_space}${ip_total}" - local time1=`date +%s` - local time1=$(time_for_humans `expr ${time1} - ${time_up}`) - if [ -z "$title" ]; then - title="${ip_name} 流量异常" - content="${content}${str_splitline}${str_title_start} 设备流量异常${str_title_end}${str_linefeed}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${ip}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${mac}$ip_total${str_linefeed}${str_tab}一分钟内流量: ${str_space}${str_space}${tmp_usage}${str_linefeed}${str_tab}在线时间: ${str_space}${str_space}${str_space}${str_space}${time1}" - elif ( echo "$title"|grep -q "流量异常" ); then - title="${ip_name} ${title}" - content="${content}${str_splitline}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${ip}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${mac}$ip_total${str_linefeed}${str_tab}一分钟内流量: ${str_space}${str_space}${str_space}${tmp_usage}${str_linefeed}${str_tab}在线时间: ${str_space}${str_space}${str_space}${str_space}${time1}" - else - title="设备状态变化" - content="${content}${str_splitline}${str_title_start} 设备流量异常${str_title_end}${str_linefeed}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${ip}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${mac}$ip_total${str_linefeed}${str_tab}一分钟内流量: ${str_space}${str_space}${str_space}${tmp_usage}${str_linefeed}${str_tab}在线时间: ${str_space}${str_space}${str_space}${str_space}${time1}" - fi - fi - done - cat ${dir}client_usage_aliases > ${dir}old_client_usage_aliases - get_client_usage_time=`date +%s` - fi -} - -# 时间单位换算 -function time_for_humans { - [ ! "$1" ] && return - if [ "$1" -lt 60 ]; then - echo "${1} 秒" - elif [ "$1" -lt 3600 ]; then - local usetime_min=`expr $1 / 60` - local usetime_sec=`expr $usetime_min \* 60` - local usetime_sec=`expr $1 - $usetime_sec` - echo "${usetime_min} 分 ${usetime_sec} 秒" - elif [ "$1" -lt 86400 ]; then - local usetime_hour=`expr $1 / 3600` - local usetime_min=`expr $usetime_hour \* 3600` - local usetime_min=`expr $1 - $usetime_min` - local usetime_min=`expr $usetime_min / 60` - echo "${usetime_hour} 小时 ${usetime_min} 分" - else - local usetime_day=`expr $1 / 86400` - local usetime_hour=`expr $usetime_day \* 86400` - local usetime_hour=`expr $1 - $usetime_hour` - local usetime_hour=`expr $usetime_hour / 3600` - echo "${usetime_day} 天 ${usetime_hour} 小时" - fi -} - -# 计算字符真实长度 -function length_str { - [ ! "$1" ] && return - local length_zh=`echo "$1"|awk '{print gensub(/[\u4e00-\u9FA5A-Za-z0-9_]/,"","g",$0)}'|awk -F "" '{print NF}'` - local length_en=`echo "$1"|awk '{print gensub(/[^\u4e00-\u9FA5A-Za-z0-9_]/,"","g",$0)}'|awk -F "" '{print NF}'` - echo `expr $length_zh / 3 \* 2 + $length_en` -} - -# 截取字符,避免中文乱码 -function cut_str { - [ ! "$1" ] && return - [ ! "$2" ] && return - [ `length_str $1` -le "$2" ] && echo "$1" && return - local temp_length=$2 - while [ $(length_str `echo "$1"|cut -c -$temp_length`) -lt "$2" ]; do - temp_length=`expr $temp_length + 1` - done - while [ $(printf "%d" \'`echo "$1"|cut -c $temp_length`) -ge "128" ] && [ $(printf "%d" \'`echo "$1"|cut -c $temp_length`) -lt "224" ]; do - temp_length=`expr $temp_length + 1` - done - temp_length=`expr $temp_length - 1` - echo $(echo "$1"|cut -c -$temp_length)"*" -} - -# 随机数 -function rand(){ - local min=$1 - local max=$(($2- $min + 1)) - local num=$(date +%s%N) - echo $(($num % $max + $min)) -} - -# 在线设备列表 -function serverchan_first(){ - gatewayinfo=`getgateway` - [ -f "${dir}ipAddress" ] && local IPLIST=`cat ${dir}ipAddress|awk '{print $1}'|grep -v "^$"|sort -u` - for ip in $IPLIST; do - read -u 5 - { - down $ip - echo "" >&5 - }& - done - wait - unset ip IPLIST - local IPLIST=`cat /proc/net/arp|grep "0x2\|0x6"|awk '{print $1}'|grep -v "^169.254."|grep -v "^$"|sort -u|grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'` - local gateway_iplist=`echo "${gatewayinfo}"|awk '{print $1}'` - [ ! -z "$gateway_iplist" ] && local IPLIST=`echo -e "${IPLIST}\n${gateway_iplist}"|grep -v "^$"|sort -u` - for ip in $IPLIST; do - read -u 5 - { - up $ip - echo "" >&5 - }& - done - wait -} - -# 创建计划任务 -function serverchan_cron(){ - function del_cron(){ - ( echo `crontab -l 2>/dev/null`|grep -q "serverchan" ) && crontab -l > conf && sed -i "/serverchan/d" conf && crontab conf && rm -f conf >/dev/null 2>&1 - } - function re_cron(){ - /etc/init.d/cron stop - /etc/init.d/cron start - } - del_cron - if [ -z "$serverchan_enable" ]; then - re_cron - return - fi - - # 重置流量 - if [ ! -z "$reset_regularly" ] && [ "$reset_regularly" -eq "1" ]; then - crontab -l 2>/dev/null > conf && echo -e "0 0 * * * rm /tmp/serverchan/usage.db >/dev/null 2>&1" >> conf && crontab conf && rm -f conf >/dev/null 2>&1 - crontab -l 2>/dev/null > conf && echo -e "0 0 * * * rm /tmp/serverchan/usage6.db >/dev/null 2>&1" >> conf && crontab conf && rm -f conf >/dev/null 2>&1 - fi - [ ! -z "$regular_time_2" ] && local regular_time_2=",${regular_time_2}" - [ ! -z "$regular_time_3" ] && local regular_time_3=",${regular_time_3}" - # 定时发送 - if [ ! -z "$regular_time" ] || [ ! -z "$regular_time_2" ] || [ ! -z "$regular_time_3" ]; then - crontab -l 2>/dev/null > conf && echo -e "0 $regular_time$regular_time_2$regular_time_3 * * * /usr/share/serverchan/serverchan send &" >> conf && crontab conf && rm -f conf >/dev/null 2>&1 - # 间隔发送 - elif [ ! -z "$interval_time" ]; then - crontab -l 2>/dev/null > conf && echo -e "0 */$interval_time * * * /usr/share/serverchan/serverchan send &" >> conf && crontab conf && rm -f conf >/dev/null 2>&1 - fi - re_cron -} - -# 免打扰检测 -function serverchan_disturb(){ - [ -z "$serverchan_sheep" ] || [ -z "$starttime" ] || [ -z "$endtime" ] && return 0 - if [ `date +%H` -ge $endtime -a $starttime -lt $endtime ] || [ `date +%H` -lt $starttime -a $starttime -lt $endtime ] || [ `date +%H` -lt $starttime -a `date +%H` -ge $endtime -a $starttime -gt $endtime ]; then - unset sheep_starttime - rm -f ${dir}sheep_usage ${dir}old_sheep_usage 2>/dev/null - disturb_text=`jq -r '._api' ${jsonpath}` - return 0 - else - [ -z "$sheep_starttime" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【免打扰】夜深了,该休息了" >> ${logfile} && sheep_starttime=`date +%s` - if [ "$serverchan_sheep" -eq "1" ] ;then - while [ `date +%H` -lt "$endtime" ]; do - enable_detection - sleep $sleeptime - done - elif [ "$serverchan_sheep" -eq "2" ] ;then - disturb_text="【免打扰】" - return 1 - fi - fi -} - -# 文件锁 -function LockFile(){ - if [ $1 = "lock" ] ;then - [ ! -f "${dir}serverchan.lock" ] && > ${dir}serverchan.lock && return - while [ -f "${dir}serverchan.lock" ]; do - enable_detection 1 - done - LockFile lock - fi - [ $1 = "unlock" ] && rm -f ${dir}serverchan.lock >/dev/null 2>&1 - return 0 -} - -# 检测黑白名单 -function blackwhitelist(){ - [ ! "$1" ] && return 1 - [ -z "$serverchan_whitelist" ] && [ -z "$serverchan_blacklist" ] && [ -z "$serverchan_interface" ] && [ -z "$MAC_online_list" ] && [ -z "$MAC_offline_list" ] && return 0 - [ ! -z "$serverchan_whitelist" ] && ( echo "$serverchan_whitelist"|grep -q -i -w $1 ) && return 1 - [ ! -z "$serverchan_blacklist" ] && ( ! echo "$serverchan_blacklist"|grep -q -i -w $1 ) && return 1 - [ ! -z "$serverchan_interface" ] && ( ! echo `getinterface ${1}`|grep -q -i -w $serverchan_interface ) && return 1 - [ ! -z "$MAC_online_list" ] && [ ! -z "$mac_online_status" ] && return 1 - [ ! -z "$MAC_online_list" ] && ( echo "$MAC_online_list"|grep -q -i -w $1 ) && return 1 - [ ! -z "$MAC_offline_list" ] && [ -z "$mac_online_status" ] && return 1 - return 0 -} - -# 重启网络服务 -function network_restart(){ -cat>${dir}network_restart</dev/null 2>&1 & -/etc/init.d/firewall restart >/dev/null 2>&1 & -/etc/init.d/dnsmasq restart >/dev/null 2>&1 & -EOF - chmod 0755 ${dir}network_restart && ${dir}network_restart - rm -f ${dir}network_restart >/dev/null 2>&1 -} - -# 查看无人值守任务设备是否在线 -function geterrdevicealiases(){ - [ -z "$err_device_aliases" ] && return - [ -f ${dir}ipAddress ] && local logrow=$(grep -c "" ${dir}ipAddress) || local logrow="0";[ $logrow -eq "0" ] && return - local MACLIST=`cat ${dir}ipAddress|awk '{print $2}'|grep -v "^$"|sort -u` - for mac in $MACLIST; do - [ -z "$err_mac" ] && [ ! -z "$mac" ] && local err_mac=`echo "$err_device_aliases"|grep -i $mac|grep -v "^$"|sort -u|head -n1` - done - # 进入免打扰时间已经超过一小时 - if [ ! -z "$sheep_starttime" ] && [ "$((`date +%s`-$sheep_starttime))" -ge "3600" ]; then - > ${dir}sheep_usage - local MACLIST=`echo "$err_device_aliases"|grep -v "^$"|sort -u` - for mac in $MACLIST; do - [ ! -z "$mac" ] && local tmptotal=`usage get ${mac} bytes` - [ ! -z "$tmptotal" ] && awk 'BEGIN{printf "%.0f\n",'$tmptotal'/'204800'}' 2>/dev/null >> ${dir}sheep_usage - done - old_sheep_usage=`cat ${dir}old_sheep_usage` 2>/dev/null - sheep_usage=`cat ${dir}sheep_usage` 2>/dev/null - [ "$old_sheep_usage" == "$sheep_usage" ] && [ -z "$sheep_nousage_starttime" ] && sheep_nousage_starttime=`date +%s` - [ "$old_sheep_usage" != "$sheep_usage" ] && unset sheep_nousage_starttime && cat ${dir}sheep_usage 2>/dev/null > ${dir}old_sheep_usage - [ ! -z "$sheep_nousage_starttime" ] && [ "$((`date +%s`-$sheep_nousage_starttime))" -ge "300" ] && unset err_mac - fi - [ -z "$err_mac" ] -} - -# 无人值守任务 -function unattended(){ - [ -z "$err_enable" ] || [ "$err_enable" -ne "1" ] && return - [ ! -z "$err_sheep_enable" ] && [ "$err_sheep_enable" -eq "1" ] && [ -z "$sheep_starttime" ] && return - geterrdevicealiases;[ $? -eq "1" ] && return - - if [ ! -z "$system_time_event" ]; then - local interfaceuptime=`getinterfaceuptime` - if [ ! -z "$autoreboot_time" ] && [ `cat /proc/uptime|awk -F. '{run_hour=$1/3600;printf("%d",run_hour)}'` -ge "$autoreboot_time" ] && [ "$system_time_event" -eq "1" ]; then - echo "`date "+%Y-%m-%d %H:%M:%S"` 【无人值守任务】重启路由器咯" >> ${logfile} - cat ${logfile} > /usr/share/serverchan/errlog - sleep 2 && reboot && exit - elif [ ! -z "$network_restart_time" ] && [ ! -z "$interfaceuptime" ] && [ `echo "$interfaceuptime"|awk -F. '{run_hour=$1/3600;printf("%d",run_hour)}'` -ge "$network_restart_time" ] && [ "$system_time_event" -eq "2" ]; then - echo "`date "+%Y-%m-%d %H:%M:%S"` 【无人值守任务】重新拨号咯" >> ${logfile} - ifup wan >/dev/null 2>&1 - sleep 60 - fi - fi - - [ -z "$public_ip_today" ] && public_ip_today=`date +"%d"` - [ -z "$public_ip_count" ] && public_ip_count="0" - [ $public_ip_today -ne `date +"%d"` ] && public_ip_today=`date +"%d"` && public_ip_count=1 - if [ ! -z "$public_ip_event" ] && [ ! -z "$public_ip_retry_count" ] && [ "$public_ip_count" -le "$public_ip_retry_count" ]; then - public_ip_count=`expr $public_ip_count + 1` - local wanIP=`getip wanipv4` - local hostIP=`getip hostipv4` - if [ ! -z "$wanIP" ] && [ ! -z "$hostIP" ] && ( ! echo "$wanIP"|grep -q -w ${hostIP} );then - echo "`date "+%Y-%m-%d %H:%M:%S"` 【无人值守任务】重拨尝试获取公网 ip,当前第 $public_ip_count 次 " >> ${logfile} - ifup wan >/dev/null 2>&1 - sleep 60 - local wanIP=`getip wanipv4` && local hostIP=`getip hostipv4` - [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -eq "1" ] && local IPv4=${wanIP} - [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -eq "2" ] && local IPv4=${hostIP} - [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -eq "1" ] && local IPv6=`getip wanipv6` - [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -eq "2" ] && local IPv6=`getip hostipv6` - [ ! -z "$wanIP" ] && [ ! -z "$hostIP" ] && ( ! echo "$wanIP"|grep -q -w ${hostIP} ) && echo IPv4 $IPv4 > ${dir}ip && echo -e IPv6 $last_IPv6 >> ${dir}ip - fi - fi -} - -# 检测网络状态 -function rand_geturl(){ - function getcheck(){ - local urllist="https://www.163.com https://www.qq.com https://www.baidu.com https://www.qidian.com https://www.douban.com" - local url_number=`expr $(echo "$urllist"|grep -o ' '|wc -l) + 1` - local url_str=`echo "$urllist"|awk -v i=$(rand 1 $url_number) '{print $i}'` - echo `curl -k -s -w "%{http_code}" -m 5 ${url_str} -A "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36" -o /dev/null` - } - local check=`getcheck` - while [ -z "$check" ] || [ "$check" -ne "200" ]; do - local check=`getcheck` - if [ ! -z "$check" ] && [ "$check" -eq "200" ]; then - [ ! -z "$network_enable" ] && [ "$network_enable" -eq "404" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【网络状态】网络恢复正常.." >> ${logfile} - local network_enable="200" - else - [ -z "$network_enable" ] || [ "$network_enable" -eq "200" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】当前网络不通!停止检测! " >> ${logfile} - local network_enable="404" - [ -z "$network_err_time" ] && network_err_time=`date +%s` - if [ ! -z "$network_err_event" ] && [ "$((`date +%s`-$network_err_time))" -ge "600" ]; then - > ${dir}send_enable.lock && serverchan_first && deltemp - geterrdevicealiases - if [ "$?" -eq "0" ]; then - [ -f /usr/share/serverchan/autoreboot_count ] && retry_count=`cat /usr/share/serverchan/autoreboot_count` && rm -f /usr/share/serverchan/autoreboot_count >/dev/null 2>&1 - [ ! -z ${retry_count} ] && retry_count=0;retry_count=`expr $retry_count + 1` - if [ "$network_err_event" -eq "1" ] ;then - if [ "$retry_count" -lt "3" ] ;then - echo "$retry_count" > /usr/share/serverchan/autoreboot_count - echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】正在尝试重启路由,当前第 $retry_count 次 " >> ${logfile} - cat ${logfile} > /usr/share/serverchan/errlog - sleep 2 && reboot && exit - fi - [ "$retry_count" -eq "3" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】已经重启路由2次,修复失败,请主人自行修复哦" >> ${logfile} - elif [ "$network_err_event" -eq "2" ] ;then - [ "$retry_count" -lt "3" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】正在尝试重启网络,当前第 $retry_count 次 " >> ${logfile} && ifup wan >/dev/null 2>&1 - [ "$retry_count" -eq "3" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】已经重启网络2次,修复失败,请主人自行修复哦 " >> ${logfile} - elif [ "$network_err_event" -eq "3" ] ;then - if [ "$retry_count" -eq "1" ] ;then - echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】正在尝试修复网络,当前第 1 次,重启网络服务中 " >> ${logfile} && network_restart - elif [ "$retry_count" -eq "2" ] ;then - echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】正在尝试修复网络,当前第 2 次,关闭可能造成网络断开的软件" >> ${logfile} - [ `uci get koolproxy.@global[0].enabled 2>/dev/null` -eq "1" ] && [ `uci get koolproxy.@global[0].koolproxy_mode 2>/dev/null` -eq "1" ] && /etc/init.d/koolproxy stop >/dev/null 2>&1 - [ `uci get adbyby.@adbyby[0].enable 2>/dev/null` -eq "1" ] && [ `uci get adbyby.@adbyby[0].wan_mode 2>/dev/null` -eq "0" ] && /etc/init.d/adbyby stop >/dev/null 2>&1 - [ `uci get passwall.@global[0].enabled 2>/dev/null` -eq "1" ] && [ `uci get passwall.@global[0].proxy_mode 2>/dev/null|grep global` ] && /etc/init.d/koolproxy stop >/dev/null 2>&1 - local shadowsocksr_enabled=`uci get shadowsocksr.@global[0].global_server 2>/dev/null|grep nil` - local shadowsocksr_run_mode=`uci get shadowsocksr.@global[0].run_mode 2>/dev/null|grep all` - [ -z "$shadowsocksr_enabled" ] && [ ! -z "$shadowsocksr_run_mode" ] && /etc/init.d/shadowsocksr stop >/dev/null 2>&1 - sleep 60 && network_restart - elif [ "$retry_count" -eq "3" ] ;then - echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】正在尝试修复网络,当前第 3 次,备份设置项,并修改相关设置" >> ${logfile} - mkdir -p /usr/share/serverchan/configbak - cp -p -f /etc/config/network /usr/share/serverchan/configbak/network - cp -p -f /etc/config/dhcp /usr/share/serverchan/configbak/dhcp - cp -p -f /etc/config/firewall /usr/share/serverchan/configbak/firewall - cp -p -f /etc/firewall.user /usr/share/serverchan/configbak/firewall.user - uci set network.wan.peerdns='0' - uci delete network.wan.dns - uci add_list network.wan.dns='223.5.5.5' - uci add_list network.wan.dns='119.29.29.29' - uci delete network.wan.mtu - uci commit network - uci set dhcp.@dnsmasq[0].port='53' - uci set dhcp.@dnsmasq[0].resolvfile='/tmp/resolv.conf.auto' - uci delete dhcp.@dnsmasq[0].server - uci delete dhcp.@dnsmasq[0].noresolv - uci commit dhcp - uci delete firewall.redirect - >/etc/firewall.user - uci commit firewall - sleep 60 && network_restart - elif [ "$retry_count" -eq "4" ] ;then - echo "$retry_count" > /usr/share/serverchan/autoreboot_count - cat ${logfile} > /usr/share/serverchan/errlog - sleep 2 && reboot && exit - elif [ "$retry_count" -eq "5" ] ;then - echo "$retry_count" > /usr/share/serverchan/autoreboot_count - echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】修复失败,还原设置中,请自行检查网络设置" >> ${logfile} - cp -p -f /usr/share/serverchan/configbak/network /etc/config/network - cp -p -f /usr/share/serverchan/configbak/dhcp /etc/config/dhcp - cp -p -f /usr/share/serverchan/configbak/firewall /etc/config/firewall - cp -p -f /usr/share/serverchan/configbak/firewall.user /etc/firewall.user - cat ${logfile} > /usr/share/serverchan/errlog - sleep 2 && reboot && exit - fi - fi - fi - elif [ -f /usr/share/serverchan/autoreboot_count ]; then - network_err_time=`expr $network_err_time - 600` && sleep 60 - fi - enable_detection - sleep $sleeptime - fi - continue - done - rm -f /usr/share/serverchan/autoreboot_count >/dev/null 2>&1 -} - -# 检测 ip 状况 -function ip_changes(){ - [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -eq "1" ] && local IPv4=`getip wanipv4` - [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -eq "2" ] && local IPv4=`getip hostipv4` - [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -eq "1" ] && local IPv6=`getip wanipv6` - [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -eq "2" ] && local IPv6=`getip hostipv6` - - if [ -f ${dir}ip ]; then - local last_IPv4=$(cat "${dir}ip"|grep IPv4|awk '{print $2}'|grep -v "^$"|sort -u|head -n1) - local last_IPv6=$(cat "${dir}ip"|grep IPv6|awk '{print $2}'|grep -v "^$"|sort -u|head -n1) - if [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -ne "0" ] && [ ! -z "$IPv4" ] && ( ! echo ${IPv4}|grep -w -q ${last_IPv4} ); then - echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}当前IP:${IPv4}" >> ${logfile} - echo IPv4 $IPv4 > ${dir}ip && echo -e IPv6 $last_IPv6 >> ${dir}ip - title="IP 地址变化" - content="${content}${str_splitline}${str_title_start} IP 地址变化${str_title_end}${str_linefeed}${str_tab}当前 IP:${IPv4}" - elif [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -ne "0" ] && [ -z "$IPv4" ]; then - echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】获取 IPv4 地址失败" >> ${logfile} - fi - - if [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -ne "0" ] && [ ! -z "$IPv6" ] && ( ! echo "$IPv6"|grep -w -q ${last_IPv6} ); then - echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}当前IPv6:${IPv6}" >> ${logfile} - echo IPv4 $IPv4 > ${dir}ip && echo -e IPv6 $IPv6 >> ${dir}ip - [ -z "$title" ] && title="IPv6 地址变化" - [ ! -z "$title" ] && title="IP 地址变化" - content="${content}${str_splitline}${str_title_start} IPv6 地址变化${str_title_end}${str_linefeed}${str_tab}当前 IPv6:${IPv6}" - elif [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -ne "0" ] && [ -z "$IPv6" ]; then - echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】获取 IPv6 地址失败" >> ${logfile} - fi - - else - echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}路由器已经重启!" >> ${logfile} - [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -ne "0" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 当前IP: ${IPv4}" >> ${logfile} - [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -ne "0" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 当前IPv6: ${IPv6}" >> ${logfile} - echo IPv4 $IPv4 > ${dir}ip && echo -e IPv6 $IPv6 >> ${dir}ip - title="路由器重新启动" - content="${content}${str_splitline}${str_title_start} 路由器重新启动${str_title_end}" - [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -ne "0" ] && content="${content}${str_linefeed}${str_tab}当前IP:${IPv4}" - [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -ne "0" ] && content="${content}${str_linefeed}${str_tab}当前IPv6:${IPv6}" - fi - - if [ ! -z "$content" ] ;then - [ -z "$ddns_enabled" ] && ddns_enabled=$(uci show ddns|grep "enabled"|grep "1") - [ -z "$ddns_enabled" ] && ddns_logrow=0 || ddns_logrow=$(echo "$ddns_enabled"|wc -l) - if [ $ddns_logrow -ge 1 ]; then - /etc/init.d/ddns restart >/dev/null 2>&1 - fi - [ -z "$zerotier_enabled" ] && zerotier_enabled=$(uci get zerotier.sample_config.enabled) - if [ ! -z "$zerotier_enabled" ] && [ $zerotier_enabled -eq "1" ] ; then - /etc/init.d/zerotier restart >/dev/null 2>&1 - fi - fi -} - -# 检测设备上线 -function up(){ - [ -f ${dir}ipAddress ] && ( cat ${dir}ipAddress|grep -q -w $1 ) && return - local ip_mac=`getmac $1` - local ip_name=`getname ${1} ${ip_mac}` - local ip_interface=`getinterface ${ip_mac}` - getping ${1} ${ip_mac} ${up_timeout} "1";local ping_online=$? - if [ "$ping_online" -eq "0" ]; then - LockFile lock - [ ! -z "$serverchan_blacklist" ] && local tmp_mac=`echo "${serverchan_blacklist}"|grep -w -i ${ip_mac}` - [ ! -z "$serverchan_whitelist" ] && local tmp_mac=`echo "${serverchan_whitelist}"|grep -w -i ${ip_mac}` - echo "{'ip': '${1}','mac': '${ip_mac}','name': '${ip_name}','uptime': '0秒','interface': '${ip_interface}','usage': '0 bytes'}" > ${dir}client/${1} - if [ ! -z "$tmp_mac" ] && ( cat ${dir}ipAddress|grep -q -w -i ${tmp_mac} ); then - usage down ${1} - echo "${1} ${ip_mac} ${ip_name} `date +%s` ${ip_interface}" >> ${dir}ipAddress - LockFile unlock && return - elif [ ! -z "$tmp_mac" ] && [ -f "${dir}tmp_downlist" ] && ( cat ${dir}tmp_downip|grep -q -w -i ${tmp_mac} ); then - local tmp_downip=`cat ${dir}tmp_downlist|grep -w -i ${tmp_mac}|awk '{print $1}'|grep -v "^$"|sort -u|head -n1` - usage down $tmp_downip - sed -i "/^${tmp_downip} /d" ${dir}tmp_downlist - LockFile unlock && return - fi - [ -f "${dir}tmp_downlist" ] && local tmp_downip=`cat ${dir}tmp_downlist|grep -w ${1}|grep -v "^$"|sort -u|head -n1` - if [ ! -z "$tmp_downip" ]; then - cat ${dir}tmp_downlist|grep -w ${1}|grep -v "^$"|sort -u|head -n1 >> ${dir}ipAddress - sed -i "/^${1} /d" ${dir}tmp_downlist - else - usage down $1 - echo "$1 ${ip_mac} ${ip_name} `date +%s` ${ip_interface}" >> ${dir}ipAddress - blackwhitelist ${ip_mac};local ip_blackwhite=$? - [ -f "${dir}send_enable.lock" ] || [ -z "$serverchan_up" ] || [ -z "$ip_blackwhite" ] && LockFile unlock && return - [ ! -z "$serverchan_up" ] && [ "$serverchan_up" -ne "1" ] && LockFile unlock && return - [ -z "$ip_blackwhite" ] || [ "$ip_blackwhite" -ne "0" ] && LockFile unlock && return - [ -f "${dir}title" ] && local title=`cat ${dir}title` - [ -f "${dir}content" ] && local content=`cat ${dir}content` - if [ -z "$title" ]; then - local title="$ip_name 连接了你的路由器" - local content="${str_splitline}${str_title_start} 新设备连接${str_title_end}${str_linefeed}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${1}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${ip_mac}${str_linefeed}${str_tab}网络接口:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_interface}" - elif ( echo ${title}|grep -q "连接了你的路由器" ); then - local title="${ip_name} ${title}" - local content="${str_splitline}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${1}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${ip_mac}${str_linefeed}${str_tab}网络接口:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_interface}" - else - local title="设备状态变化" - local content="${str_splitline}${str_title_start} 新设备连接${str_title_end}${str_linefeed}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${1}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${ip_mac}${str_linefeed}${str_tab}网络接口:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_interface}" - fi - echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}新设备 ${ip_name} ${1} 连接了">> ${logfile} - #[ ! -z "$serverchan_blacklist" ] && local title="你偷偷关注的设备上线了" - [ ! -z "$title" ] && echo "$title" >${dir}title - [ ! -z "$content" ] && echo -n "$content" >>${dir}content - fi - fi - LockFile unlock -} - -# 检测设备离线 -function down(){ - local ip_mac=`getmac $1` - local ip_name=`getname ${1} ${ip_mac}` - local ip_interface=`getinterface ${ip_mac}` - getping ${1} ${ip_mac} ${down_timeout} ${timeout_retry_count};local ping_online=$? - if [ "$ping_online" -eq "1" ]; then - LockFile lock - [ ! -f "${dir}send_enable.lock" ] && cat ${dir}ipAddress|grep -w ${1}|grep -v "^$"|sort -u|head -n1 >> ${dir}tmp_downlist - sed -i "/^${1} /d" ${dir}ipAddress - rm -f ${dir}client/${1} >/dev/null 2>&1 - LockFile unlock - else - local tmp_name=`cat ${dir}ipAddress|grep -w ${1}|awk '{print $3}'|grep -v "^$"|sort -u|head -n1` - if [ ${ip_name} != ${tmp_name} ]; then - LockFile lock - local tmp_str=$(echo "$1 ${ip_mac} ${ip_name} `cat ${dir}ipAddress|grep -w ${1}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` ${ip_interface}") - sed -i "/^${1} /d" ${dir}ipAddress - echo "$tmp_str" >> ${dir}ipAddress - LockFile unlock - fi - local time_up=`cat ${dir}ipAddress|grep -w ${1}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` - local time1=`date +%s` - local time1=$(time_for_humans `expr ${time1} - ${time_up}`) - echo "{'ip': '${1}','mac': '${ip_mac}','name': '${ip_name}','uptime': '${time1}','interface': '${ip_interface}','usage': '`usage get $ip_mac`'}" > ${dir}client/${1} - fi -} - -# 设备离线通知 -function down_send(){ - [ ! -f "${dir}tmp_downlist" ] && return - local IPLIST=`cat ${dir}tmp_downlist|awk '{print $1}'` - for ip in $IPLIST; do - local ip_mac=`getmac ${ip}` - blackwhitelist ${ip_mac};local ip_blackwhite=$? - [ -z "$serverchan_down" ] || [ -z "$ip_blackwhite" ] && continue - [ ! -z "$serverchan_down" ] && [ "$serverchan_down" -ne "1" ] && continue - [ -z "$ip_blackwhite" ] || [ "$ip_blackwhite" -ne "0" ] && continue - [ ! -z "$serverchan_blacklist" ] && local tmp_mac=`echo "${serverchan_blacklist}"|grep -w -i ${ip_mac}` - [ ! -z "$serverchan_whitelist" ] && local tmp_mac=`echo "${serverchan_whitelist}"|grep -w -i ${ip_mac}` - [ ! -z "$tmp_mac" ] && ( cat ${dir}ipAddress|grep -q -w -i ${tmp_mac} ) && continue - local ip_name=`getname ${ip} ${ip_mac}` - local time_up=`cat ${dir}tmp_downlist|grep -w ${ip}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` - local ip_total=`usage get $ip_mac` && [ ! -z "$ip_total" ] && local ip_total="${str_linefeed}${str_tab}总计流量: ${str_space}${str_space}${str_space}${str_space}${ip_total}" - local time1=`date +%s` - local time1=$(time_for_humans `expr ${time1} - ${time_up}`) - if [ -z "$title" ]; then - title="${ip_name} 断开连接" - content="${content}${str_splitline}${str_title_start} 设备断开连接${str_title_end}${str_linefeed}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${ip}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${ip_mac}$ip_total${str_linefeed}${str_tab}在线时间: ${str_space}${str_space}${str_space}${str_space}${time1}" - elif ( echo "$title"|grep -q "断开连接" ); then - title="${ip_name} ${title}" - content="${content}${str_splitline}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${ip}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${ip_mac}$ip_total${str_linefeed}${str_tab}在线时间: ${str_space}${str_space}${str_space}${str_space}${time1}" - else - title="设备状态变化" - content="${content}${str_splitline}${str_title_start} 设备断开连接${str_title_end}${str_linefeed}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${ip}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${ip_mac}$ip_total${str_linefeed}${str_tab}在线时间: ${str_space}${str_space}${str_space}${str_space}${time1}" - fi - echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}设备 ${ip_name} ${ip} 断开连接 " >> ${logfile} - done - rm -f ${dir}tmp_downlist >/dev/null 2>&1 -} - -# 当前设备列表 -function current_device(){ - ( echo "$lite_enable"|grep -q "content" ) || ( echo "$lite_enable"|grep -q "device" ) && return - [ -f ${dir}ipAddress ] && local logrow=$(grep -c "" ${dir}ipAddress) || local logrow="0";[ $logrow -eq "0" ] && return - [ -f ${dir}usage.db ] && local ip_total_db="总计流量${str_space}${str_space}${str_space}${str_space}" - content="${content}${str_splitline}${str_title_start} 现有在线设备 ${logrow} 台,具体如下${str_title_end}${str_linefeed}${str_tab}IP 地址${str_space}${str_space}${str_space}${str_space}${str_space}${str_space}${str_space}${str_space}${str_space}${ip_total_db}客户端名" - local IPLIST=`cat ${dir}ipAddress|awk '{print $1}'` - for ip in $IPLIST; do - local ip_mac=`getmac ${ip}` - local ip_total=`usage get ${ip_mac}` - local ip_name=`getname ${ip} ${ip_mac}` - local ip_name=`cut_str $ip_name 15` - if [ "${#ip}" -lt "15" ]; then - local n=`expr 15 - ${#ip}` - for i in `seq 1 $n`; do - local ip="${ip}${str_space}" - done - unset i n - fi - if [ ! -z "$ip_total" ]; then - local n=`expr 11 - ${#ip_total}` - for i in `seq 1 $n`; do - local ip_total="${ip_total}${str_space}" - done - fi - content="${content}${str_linefeed}${str_tab}${ip}${ip_total}${ip_name}" - unset i n ip_total ip_mac ip_name - done -} - -# 检测 cpu 状态 -function cpu_load(){ - if [ ! -z "$temperature_enable" ] && [ "$temperature_enable" -eq "1" ] && [ ! -z "$temperature" ]; then - [ -z "$temperature_time" ] && temperature_time=`date +%s` - local cpu_wendu=`soc_temp`; - [ -z "$cpu_wendu" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】无法读取设备温度,请检查命令" >> ${logfile} - - if [ `expr $cpu_wendu \> $temperature` -eq "1" ]; then - echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!警报!!】 CPU 温度过高: ${cpu_wendu}" >> ${logfile} - else - temperature_time=`date +%s` - fi - - if [ "$((`date +%s`-$temperature_time))" -ge "300" ] && [ -z "$temperaturecd_time" ]; then - title="CPU 温度过高!" - temperaturecd_time=`date +%s` - echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text} CPU 温 度过高: ${cpu_wendu}" >> ${logfile} - content="${content}${str_splitline}${str_title_start} CPU 温度过高${str_title_end}${str_linefeed}${str_tab}CPU 温度已连续五分钟超过预设${str_linefeed}${str_tab}接下来一小 时不再提示${str_linefeed}${str_tab}当前温度:${cpu_wendu}℃" - elif [ ! -z "$temperaturecd_time" ] && [ "$((`date +%s`-$temperaturecd_time))" -ge "3300" ] ;then - unset temperaturecd_time - fi - fi - - if [ ! -z "$cpuload_enable" ] && [ "$cpuload_enable" -eq "1" ] && [ ! -z "$cpuload" ]; then - [ -z "$cpuload_time" ] && cpuload_time=`date +%s` - local cpu_fuzai=`cat /proc/loadavg|awk '{print $1}'` 2>/dev/null - [ -z "$cpu_fuzai" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】无法读取设备负载,请检查命令" >> ${logfile} - - if [ `expr $cpu_fuzai \> $cpuload` -eq "1" ]; then - echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!警报!!】 CPU 负载过高: ${cpu_fuzai}" >> ${logfile} - cputop log - else - cpuload_time=`date +%s` - fi - - if [ "$((`date +%s`-$cpuload_time))" -ge "300" ] && [ -z "$cpucd_time" ]; then - unset getlogtop - if [ ! -z "$title" ] && ( echo "$title"|grep -q "过高" ); then - title="设备报警!" - else - title="CPU 负载过高!" - fi - cpucd_time=`date +%s` - echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text} CPU 负 载过高: ${cpu_fuzai}" >> ${logfile} - content="${content}${str_splitline}${str_title_start} CPU 负载过高${str_title_end}${str_linefeed}${str_tab}CPU 负载已连续五分钟超过预设${str_linefeed}${str_tab}接下来一小 时不再提示${str_linefeed}${str_tab}当前负载:${cpu_fuzai}" - cputop - elif [ ! -z "$cpucd_time" ] && [ "$((`date +%s`-$cpucd_time))" -ge "3300" ] ;then - unset cpucd_time - fi - fi -} - -function cputop(){ - [ -z "$1" ] && content="${content}${str_splitline}${str_title_start} 当前 CPU 占用前三的进程${str_title_end}" - local gettop=`top -bn 1|grep -v "top -bn 1"` - for i in `seq 5 7`; do - local top_name=`echo "${gettop}"|awk 'NR=='${i}|awk '{print ($8 ~ /\/bin\/sh|\/bin\/bash/) ? $9 : $8}'` - local top_load=`echo "${gettop}"|awk 'NR=='${i}|awk '{print $7}'` - local temp_top="${top_name} ${top_load}" - [ ! -z "$1" ] && local logtop="$logtop $temp_top" - [ -z "$1" ] && content="${content}${str_linefeed}${str_tab}${temp_top}" - done - unset i - [ ! -z "$1" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!警报!!】 CPU 占用前三: ${logtop}" >> ${logfile} -} - -# 生成日志监控文件,避免后台影响 wait 语句 -function get_syslog(){ - kill -9 `pgrep -f "logread -f -p notice"` 2>/dev/null - [ -z "$web_logged" ] && [ -z "$ssh_logged" ] && [ -z "$web_login_failed" ] && [ -z "$ssh_login_failed" ] && return - rm -f ${dir}login_monitor >/dev/null 2>&1 - -cat>${dir}get_syslog<> ${dir}login_monitor & -EOF - chmod 0755 ${dir}get_syslog && ${dir}get_syslog - rm -f ${dir}get_syslog >/dev/null 2>&1 -} - -# 登陆提醒通知 -function login_send(){ - [ -z "$web_logged" ] && [ -z "$ssh_logged" ] && [ -z "$web_login_failed" ] && [ -z "$ssh_login_failed" ] && return - [ ! -f ${dir}login_monitor ] && return - cat ${dir}login_monitor|grep -i "accepted login"|awk '{print $4" "$NF}' >> ${dir}web_login - cat ${dir}login_monitor|grep -i "Password auth succeeded\|Pubkey auth succeeded"|grep -Eo "[0-9]{2}:[0-9]{2}:[0-9]{2}.*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"|awk '{print $1" "$NF" "$5}' >> ${dir}ssh_login - cat ${dir}login_monitor|grep -i "failed login"|grep -Eo "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" >> ${dir}web_failed - cat ${dir}login_monitor|grep -i "Exit before auth from"|grep -Eo "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" >> ${dir}ssh_failed - echo "" > ${dir}login_monitor - add_ip_black - - local login_ip_list=`cat ${dir}web_login|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` - for login_ip in $login_ip_list; do - [ -z "$login_ip" ] && continue - echo "$ip_white_list"|grep -w -q "$login_ip" && continue - local web_login_time=`cat ${dir}web_login|grep -w ${login_ip}|awk '{print $1}'|grep -v "^$"|sort -u|head -n1` - local web_login_mode=`cat ${dir}web_login|grep -w ${login_ip}|awk '{print $3}'|grep -v "^$"|sort -u|head -n1` - if [ ! -z "$web_logged" ] && [ "$web_logged" -eq "1" ]; then - if [ -z "$title" ]; then - title="${login_ip} 通过 web 登陆了路由器" - content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}时间:${str_space}${str_space}${str_space}${str_space}${str_space}${web_login_time}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}${content_mode}" - elif ( echo "$title"|grep -q "登陆了路由器" ); then - title="${login_ip} ${title}" - content="${content}${str_splitline}${str_tab}时间:${str_space}${str_space}${str_space}${str_space}${str_space}${web_login_time}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}${content_mode}" - else - title="设备状态变化" - content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}时间:${str_space}${str_space}${str_space}${str_space}${str_space}${web_login_time}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}${content_mode}" - fi - fi - echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}设备 ${login_ip} 通过 web ${web_login_mode} 登陆了路由器 " >> ${logfile} - done - echo "" > ${dir}web_login - unset login_ip login_ip_list - - local login_ip_list=`cat ${dir}ssh_login|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` - for login_ip in $login_ip_list; do - [ -z "$login_ip" ] && continue - echo "$ip_white_list"|grep -w -q "$login_ip" && continue - local ssh_login_time=`cat ${dir}ssh_login|grep -w ${login_ip}|awk '{print $1}'|grep -v "^$"|sort -u|head -n1` - local ssh_login_mode=`cat ${dir}ssh_login|grep -w ${login_ip}|awk '{print $3}'|grep -v "^$"|sort -u|head -n1` - [ ! -z "$ssh_login_mode" ] && local content_mode="${str_linefeed}${str_tab}登录方式: ${str_space}${str_space}${str_space}${str_space}${ssh_login_mode}" - if [ ! -z "$ssh_logged" ] && [ "$ssh_logged" -eq "1" ]; then - if [ -z "$title" ]; then - title="${login_ip} 通过 ssh 登陆了路由器" - content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}时间:${str_space}${str_space}${str_space}${str_space}${str_space}${ssh_login_time}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}${content_mode}" - elif ( echo "$title"|grep -q "登陆了路由器" ); then - title="${login_ip} ${title}" - content="${content}${str_splitline}${str_tab}时间:${str_space}${str_space}${str_space}${str_space}${str_space}${ssh_login_time}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}${content_mode}" - else - title="设备状态变化" - content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}时间:${str_space}${str_space}${str_space}${str_space}${str_space}${ssh_login_time}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}${content_mode}" - fi - fi - echo "`date "+%Y-%m-%d %H:%M:%S"` 【info】设备 ${login_ip} 通过 ssh ${ssh_login_mode} 登陆了路由器 " >> ${logfile} - done - echo "" > ${dir}ssh_login - unset login_ip login_ip_list - - local login_ip_list=`cat ${dir}web_failed|awk '{print $1}'|grep -v "^$"|sort -u|head -n1` - for login_ip in $login_ip_list; do - [ -z "$login_ip" ] && continue - echo "$ip_white_list"|grep -w -q "$login_ip" && continue - local web_login_sum=`cat ${dir}web_failed|grep -w "${login_ip}"|wc -l` - if [ "$web_login_sum" -ge "$login_max_num" ] ;then - if [ ! -z "$web_login_failed" ] && [ "$web_login_failed" -eq "1" ]; then - if [ -z "$title" ]; then - title="${login_ip} 通过 web 频繁尝试登陆" - content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}" - elif ( echo "$title"|grep -q "频繁尝试登陆" ); then - title="${login_ip} ${title}" - content="${content}${str_splitline}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}" - else - title="设备状态变化" - content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}" - fi - fi - sed -i "/^${login_ip}$/d" ${dir}web_failed - echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】设备 ${login_ip} 通过 web 频繁尝试登陆" >> ${logfile} - add_ip_black $login_ip - fi - done - unset login_ip - - local login_ip_list=`cat ${dir}ssh_failed|awk '{print $1}'|grep -v "^$"|sort -u|head -n1` - for login_ip in $login_ip_list; do - [ -z "$login_ip" ] && continue - echo "$ip_white_list"|grep -w -q "$login_ip" && continue - local ssh_login_sum=`cat ${dir}ssh_failed|grep -w "${login_ip}"|wc -l` - if [ "$ssh_login_sum" -ge "$login_max_num" ] ;then - if [ ! -z "$ssh_login_failed" ] && [ "$ssh_login_failed" -eq "1" ]; then - if [ -z "$title" ]; then - title="${login_ip} 通过 ssh 频繁尝试登陆" - content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}" - elif ( echo "$title"|grep -q "频繁尝试登陆" ); then - title="${login_ip} ${title}" - content="${content}${str_splitline}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}" - else - title="设备状态变化" - content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}" - fi - fi - sed -i "/^${login_ip}$/d" ${dir}ssh_failed - echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】设备 ${login_ip} 通过 ssh 频繁尝试登陆" >> ${logfile} - add_ip_black $login_ip - fi - done - unset login_ip - -} - -# 添加黑名单 -function add_ip_black(){ - [ ! -f "${ip_blacklist_path}" ] && touch ${ip_blacklist_path} - local logrow=$(grep -c "" ${ip_blacklist_path}) - [ ! -z "$web_login_black" ] && [ "$web_login_black" -eq "0" ] || [ -z "$web_login_black" ] && logrow=0 - [ ! -z "$1" ] && logrow=logrow+1 - ipset flush ip_blacklist >/dev/null 2>&1 - - if [ $logrow -le "0" ]; then - iptables -D INPUT -m set --match-set ip_blacklist src -j DROP >/dev/null 2>&1 - ipset destroy ip_blacklist >/dev/null 2>&1 - return - fi - - ipset list ip_blacklist >/dev/null 2>&1 || ipset create ip_blacklist hash:ip timeout ${ip_black_timeout} >/dev/null 2>&1 - iptables -C INPUT -m set --match-set ip_blacklist src -j DROP >/dev/null 2>&1 || iptables -I INPUT -m set --match-set ip_blacklist src -j DROP >/dev/null 2>&1 - echo "$1" >> ${ip_blacklist_path} - for ip_black in `cat ${ip_blacklist_path}`; do - ip_black=`echo "$ip_black"|grep -Eo "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"` - ipset -! add ip_blacklist $ip_black >/dev/null 2>&1 - done - ipset list ip_blacklist|grep -Eo "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" > ${ip_blacklist_path} -} - - -# 发送定时数据 -function send(){ - echo "`date "+%Y-%m-%d %H:%M:%S"` 【定时数据】创建定时任务" >> ${logfile} - serverchan_disturb;local send_disturb=$? - get_config "send_title" "router_status" "router_temp" "router_wan" "client_list" - - [ -z "$send_title" ] && local send_title="路由状态:" - [ ! -z "$1" ] && local send_title="发送测试:" && local send_content="${str_splitline}${str_title_start}内容1${str_title_end}${str_linefeed}${str_tab}设备1${str_linefeed}${str_tab}设备2${str_splitline}${str_title_start}内容2${str_title_end}${str_linefeed}${str_tab}设备3${str_linefeed}${str_tab}设备4" - [ -z "$1" ] && [ ! -z "$client_list" ] && [ "$client_list" -eq "1" ] && > ${dir}send_enable.lock && serverchan_first & - - if [ -z "$1" ] && [ ! -z "$router_status" ] && [ "$router_status" -eq "1" ]; then - local systemload=`cat /proc/loadavg|awk '{print $1" "$2" "$3}'` - local cpuload=`getcpu` - local ramload=`free -m|sed -n '2p'|awk '{printf "%.2f%%\n",($3/$2)*100}'` - local Qwai=`curl -o /dev/null --connect-timeout 5 -s -w %{http_code} www.google.com` - if [[ "$Qwai" -eq "200" ]] || [[ "$Qwai" -eq "301" ]] || [[ "$Qwai" -eq "302" ]]; then - local Qwai_status="已连通!" - else - local Qwai_status="已断开!" - fi - local systemstatustime=`cat /proc/uptime|awk -F. '{run_days=$1 / 86400;run_hour=($1 % 86400)/3600;run_minute=($1 % 3600)/60;run_second=$1 % 60;printf("运行时间:%d天%d时%d分%d秒",run_days,run_hour,run_minute,run_second)}'`;unset run_days run_hour run_minute run_second - local send_content="${send_content}${str_splitline}${str_title_start} 系统运行状态${str_title_end}" - local send_content="${send_content}${str_linefeed}${str_tab}平均负载:${systemload}" - local send_content="${send_content}${str_linefeed}${str_tab}CPU占用:${cpuload}" - local send_content="${send_content}${str_linefeed}${str_tab}内存占用:${ramload}" - local send_content="${send_content}${str_linefeed}${str_tab}全球互联:${Qwai_status}" - local send_content="${send_content}${str_linefeed}${str_tab}${systemstatustime}" - fi - - if [ -z "$1" ] && [ ! -z "$router_temp" ] && [ "$router_temp" -eq "1" ]; then - local cputemp=`soc_temp` - [ ! -z "$cputemp" ] && local send_content="${send_content}${str_splitline}${str_title_start} 设备温度${str_title_end}${str_linefeed}${str_tab}CPU:${cputemp}℃" - [ -z "$cputemp" ] && local send_content="${send_content}${str_splitline}${str_title_start} 设备温度${str_title_end}${str_linefeed}${str_tab}无法获取设备温度" - fi - - if [ -z "$1" ] && [ ! -z "$router_wan" ] && [ "$router_wan" -eq "1" ]; then - local send_wanIP=`getip wanipv4`;local send_hostIP=`getip hostipv4` - local send_content="${send_content}${str_splitline}${str_title_start} WAN 口信息${str_title_end}${str_linefeed}${str_tab}接口 IPv4:${send_wanIP}" - local send_content="${send_content}${str_linefeed}${str_tab}外网 IPv4:${send_hostIP}" - if [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -ne "0" ]; then - local send_wanIPv6=`getip wanipv6`;local send_hostIPv6=`getip hostipv6` - local send_content="${send_content}${str_linefeed}${str_tab}接口 IPv6:${send_wanIPv6}" - local send_content="${send_content}${str_linefeed}${str_tab}外网 IPv6:${send_hostIPv6}" - fi - ( ! echo "$send_wanIP"|grep -q -w ${send_hostIP} ) && local send_content="${send_content}${str_linefeed}${str_tab}外网 IP 与接口 IP 不一致,你的 IP 可能不是公网 IP" - local interfaceuptime=`getinterfaceuptime` - [ ! -z "$interfaceuptime" ] && local wanstatustime=`getinterfaceuptime|awk -F. '{run_days=$1 / 86400;run_hour=($1 % 86400)/3600;run_minute=($1 % 3600)/60;run_second=$1 % 60;printf("在线时间:%d天%d时%d分%d秒",run_days,run_hour,run_minute,run_second)}'` && unset run_days run_hour run_minute run_second - local send_content="${send_content}${str_linefeed}${str_tab}${wanstatustime}" - fi - - if [ -z "$1" ] && [ ! -z "$client_list" ] && [ "$client_list" -eq "1" ]; then - wait - local IPLIST=`cat ${dir}ipAddress 2>/dev/null|awk '{print $1}'` - [ -f ${dir}ipAddress ] && local logrow=$(grep -c "" ${dir}ipAddress) || local logrow="0" - [ "$logrow" -eq "0" ] && local send_content="${send_content}${str_splitline}${str_title_start} 当前无在线设备${str_title_end}" || local send_content="${send_content}${str_splitline}${str_title_start} 现有在线设备 ${logrow} 台${str_title_end}" - for ip in $IPLIST; do - local time_up=`cat ${dir}ipAddress|grep -w ${ip}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` - local time1=`date +%s` - local time1=$(time_for_humans `expr ${time1} - ${time_up}`) - local ip_mac=`getmac ${ip}` - local ip_name=`getname ${ip} ${ip_mac}` - local ip_total=`usage get ${ip_mac}`;[ ! -z "$ip_total" ] && local ip_total="总计流量:${ip_total} " - local ip_name=`cut_str $ip_name 18` - local send_content="${send_content}${str_linefeed}${str_tab}【${ip_name}】 ${ip}${str_linefeed}${str_tab}${ip_total}在线 ${time1}" - unset ip_total time_down time_up time1 ip_mac ip_name - done - fi - [ ! -z "$device_name" ] && local send_title="【$device_name】${send_title}" - [ -z "$send_content" ] && local send_content="${str_splitline}${str_title_start} 我遇到了一个难题${str_title_end}${str_linefeed}${str_tab}定时发送选项错误,你没有选择需要发送的项目,该怎 么办呢${str_splitline}" - [ "$send_disturb" -eq "0" ] && diy_send "${send_title}" "${send_content}" "${jsonpath}" >/dev/null 2>&1 - [ $? -eq 1 ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】定时推送失败,请检查网络或设置信息" >> ${logfile} || echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}定时推送任务完成" >> ${logfile} - deltemp -} - -# 初始化 -read_config -deltemp -serverchan_cron - -# 限制并发进程 -[ -z "$thread_num" ] || [ "$thread_num" -eq "0" ] && thread_num=5 -[ -e ${dir}fd1 ] || mkfifo ${dir}fd1 -exec 5<>${dir}fd1 -rm -f ${dir}fd1 >/dev/null 2>&1 -for i in `seq 1 $thread_num`; do - echo >&5 -done -unset i - -# 启动参数 -if [ "$1" ] ;then - [ $1 == "send" ] && send - [ $1 == "soc" ] && echo `soc_temp` > ${dir}soc_tmp - [ $1 == "test" ] && send test - exit -fi - -# 载入在线设备 -serverchan_init;[ $? -eq 1 ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】读取设置出错,请检查设置项 " >> ${logfile} && exit -echo "`date "+%Y-%m-%d %H:%M:%S"` 【初始化】载入在线设备" >> ${logfile} -> ${dir}send_enable.lock && serverchan_first && deltemp -echo "`date "+%Y-%m-%d %H:%M:%S"` 【初始化】初始化完成" >> ${logfile} - -# 循环 -while [ "$serverchan_enable" -eq "1" ]; do - deltemp - usage update - serverchan_disturb;disturb=$? - - [ -f ${dir}ipAddress ] && ipAddress_logrow=$(grep -c "" ${dir}ipAddress) || ipAddress_logrow="0"; - if [ $ipAddress_logrow -ne "0" ]; then - online_list=`cat ${dir}ipAddress|awk '{print $2}'|grep -v "^$"|sort -u` - for online_mac in $online_list; do - [ ! -z "$online_mac" ] && mac_online_status="`echo "$mark_mac_list"|grep -i $online_mac|grep -v "^$"|sort -u|head -n1`${mac_online_status}" - done - fi - - if [ "$serverchan_ipv4" -ne "0" ] || [ "$serverchan_ipv6" -ne "0" ]; then - rand_geturl - ip_changes - fi - - # 设备列表 - if [ ! -f "${dir}send_enable.lock" ]; then - [ ! -z "$title" ] && echo "$title" > ${dir}title - [ ! -z "$content" ] && echo "$content" > ${dir}content - serverchan_first - [ -f "${dir}title" ] && title=`cat ${dir}title` && rm -f ${dir}title >/dev/null 2>&1 - [ -f "${dir}content" ] && content=`cat ${dir}content` && rm -f ${dir}content >/dev/null 2>&1 - fi - - # 离线缓存区推送 - [ ! -f "${dir}send_enable.lock" ] && down_send - - # 当前设备列表 - [ ! -z "$content" ] && [ ! -f "${dir}send_enable.lock" ] && current_device - - # 无人值守任务 - [ ! -f "${dir}send_enable.lock" ] && unattended - - # CPU 检测 - [ ! -f "${dir}send_enable.lock" ] && cpu_load - - # 异常流量检测 - [ ! -f "${dir}send_enable.lock" ] && get_client_usage - - # 登陆提醒通知 - [ ! -f "${dir}send_enable.lock" ] && login_send - - if [ ! -f "${dir}send_enable.lock" ] && [ ! -z "$title" ] && [ ! -z "$content" ]; then - [ ! -z "$device_name" ] && title="【$device_name】$title" - ( echo "$lite_enable"|grep -q "content" ) && content="$title" - [ "$disturb" -eq "0" ] && diy_send "${title}" "${content}" "${jsonpath}" >/dev/null 2>&1 - [ $? -eq 1 ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】推送失败,请检查网络或设置信息 " >> ${logfile} - fi - - while [ -f "${dir}send_enable.lock" ]; do - sleep $sleeptime - done - sleep $sleeptime -done +#!/bin/sh + +# 读取设置文件 +function get_config(){ + while [[ "$*" != "" ]]; do + eval ${1}='`uci get serverchan.serverchan.$1`' 2>/dev/null + shift + done +} + +# 初始化设置信息 +function read_config(){ + get_config "serverchan_enable" "lite_enable" "device_name" "sleeptime" "oui_data" "oui_dir" "reset_regularly" "debuglevel" "device_aliases" \ + "serverchan_ipv4" "ipv4_interface" "serverchan_ipv6" "ipv6_interface" "serverchan_up" "serverchan_down" "cpuload_enable" "cpuload" "temperature_enable" "temperature" "client_usage" "client_usage_max" "client_usage_disturb" "client_usage_whitelist" "web_logged" "ssh_logged" "web_login_failed" "ssh_login_failed" "login_max_num" "web_login_black" "ip_white_list" "ip_black_timeout"\ + "regular_time" "regular_time_2" "regular_time_3" "interval_time" \ + "serverchan_sheep" "starttime" "endtime" "serverchan_whitelist" "serverchan_blacklist" "serverchan_interface" "MAC_online_list" "MAC_offline_list" \ + "up_timeout" "down_timeout" "timeout_retry_count" "thread_num" "soc_code" "server_host" "server_port" "err_enable" "err_sheep_enable" "err_device_aliases" "network_err_event" "system_time_event" "autoreboot_time" "network_restart_time" "public_ip_event" "public_ip_retry_count" \ + "jsonpath" "sckey" "corpid" "userid" "agentid" "corpsecret" "mediapath" "wxpusher_apptoken" "wxpusher_uids" "wxpusher_topicIds" "pushplus_token" "tg_token" "chat_id" \ + "gateway_info_enable" "gateway_host_url" "gateway_info_url" "gateway_logout_url" "gateway_username_id" "gateway_password_id" "gateway_username" "gateway_password" + + for str_version in "wrtbwmon" "iputils-arping" "curl" "iw"; do + eval `echo ${str_version:0:2}"_version"`=`opkg list-installed|grep -w ^${str_version}|awk '{print $3}'` 2>/dev/null + done + dir="/tmp/serverchan/" && mkdir -p ${dir} && mkdir -p ${dir}/client + tempjsonpath="/tmp/serverchan/temp.json" + ip_blacklist_path="/usr/bin/serverchan/api/ip_blacklist" + [ ! -z "$oui_dir" ] && [ "$oui_dir" -eq "1" ] && oui_base="${dir}oui_base.txt" || oui_base="/usr/bin/serverchan/oui_base.txt" + debuglevel=`echo "$debuglevel"` && [ -z "$debuglevel" ] && logfile="/dev/null" || logfile="${dir}serverchan.log" + serverchan_blacklist=`echo "$serverchan_blacklist"|sed 's/ /\n/g'` 2>/dev/null + serverchan_whitelist=`echo "$serverchan_whitelist"|sed 's/ /\n/g'` 2>/dev/null + device_aliases=`echo "$device_aliases"|sed 's/ /\n/g'|sed 's/-/ /'` 2>/dev/null + err_device_aliases=`echo "$err_device_aliases"|sed 's/ /\n/g'` 2>/dev/null + client_usage_whitelist=`echo "$client_usage_whitelist"|sed 's/ /\n/g'` 2>/dev/null + ip_white_list=`echo "$ip_white_list"|sed 's/ /\n/g'` 2>/dev/null + mark_mac_list="${MAC_online_list} ${MAC_offline_list}" + mark_mac_list=`echo "$mark_mac_list"|sed 's/ /\n/g'|sed 's/-/ /'` 2>/dev/null + ipv4_urllist=`cat /usr/bin/serverchan/api/ipv4.list` 2>/dev/null + ipv6_urllist=`cat /usr/bin/serverchan/api/ipv6.list` 2>/dev/null + [ -z "$serverchan_ipv4" ] && serverchan_ipv4=0 + [ -z "$serverchan_ipv6" ] && serverchan_ipv6=0 + [ "$iw_version" ] && wlan_interface=`iw dev|grep Interface|awk '{print $2}'` >/dev/null 2>&1 + [ -z "$up_timeout" ] || [ "$up_timeout" -eq "0" ] && up_timeout="2" + [ -z "$down_timeout" ] || [ "$down_timeout" -eq "0" ] && down_timeout="20";down_timeout=`expr ${down_timeout} / 2 + 1` + [ -z "$timeout_retry_count" ] && timeout_retry_count="2";[ "$timeout_retry_count" -eq "0" ] && timeout_retry_count="1" + [ -z "$server_port" ] && server_port="22" + str_title_start=`/usr/bin/jq -r '.str_title_start' ${jsonpath}` + str_title_end=`/usr/bin/jq -r '.str_title_end' ${jsonpath}` + str_linefeed=`/usr/bin/jq -r '.str_linefeed' ${jsonpath}` + str_splitline=`/usr/bin/jq -r '.str_splitline' ${jsonpath}` + str_space=`/usr/bin/jq -r '.str_space' ${jsonpath}` + str_tab=`/usr/bin/jq -r '.str_tab' ${jsonpath}` + ( echo "$lite_enable"|grep -q "content" ) && str_title_start="" && str_title_end="" && str_splitline="" && str_linefeed="" && str_tab="" +} + +# 初始化 +function serverchan_init(){ + enable_detection + if [ -f "/usr/bin/serverchan/errlog" ]; then + cat /usr/bin/serverchan/errlog > ${logfile} + echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】载入上次重启前日志" >> ${logfile} + echo "--------------------------------------------------------" >> ${logfile} + fi + down_oui & + get_syslog + add_ip_black + + rm -f ${dir}fd1 ${dir}sheep_usage ${dir}old_sheep_usage ${dir}client_usage_aliases ${dir}old_client_usage_aliases /usr/bin/serverchan/errlog >/dev/null 2>&1 + [ ! -f "/usr/sbin/wrtbwmon" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】未安装 wrtbwmon ,流量统计不可用" >> ${logfile} + [ -z "$ip_version" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】无法获取依赖项 iputils-arping 版本号,请确认插件是否正常运行" >> ${logfile} + [ -z "$cu_version" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】无法获取依赖项 curl 版本号,请确认插件是否正常运行" >> ${logfile} + [ -z "${sckey}${tg_token}${pushplus_token}${corpid}${wxpusher_apptoken}${wxpusher_uids}${wxpusher_topicIds}" -a "${jsonpath}" != "/usr/bin/serverchan/api/diy.json" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】请填写正确的 key " >> ${logfile} && return 1 + local interfacelist=`getinterfacelist` && [ -z "$interfacelist" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】无法获取接口在线时间等信息,可能存在多个接口或配置错误,请确认插件是否正常运行" >> ${logfile} + return 0 +} + +# 推送 +function diy_send(){ + ( ! echo "$lite_enable"|grep -q "content" ) && ( ! echo "$lite_enable"|grep -q "nowtime" ) && local nowtime=`date "+%Y-%m-%d %H:%M:%S"` + local diyurl=`/usr/bin/jq -r .url ${3}` && local diyurl=`eval echo ${diyurl}` + local type=`/usr/bin/jq -r '.type' ${3}` && local type=`eval echo ${type}` + local data=`/usr/bin/jq -r '.data' ${3}` && local data=`eval echo ${data}` + local content_type=`/usr/bin/jq -r '.content_type' ${3}` + /usr/bin/jq ".type + $type" ${jsonpath} > ${tempjsonpath} + + /usr/bin/jq -r '.[]' ${tempjsonpath}|grep -w "null" && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】参数值错误,请检查设置项 `/usr/bin/jq -r '.' ${tempjsonpath}|grep "null"`" >> ${logfile} && return 1 + [ -f ${tempjsonpath} ] && local logrow=$(grep -c "" ${tempjsonpath}) || local logrow="0" + [ $logrow -eq "0" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】json 文件生成失败,请检查文件格式" >> ${logfile} && return 1 + /usr/bin/jq -r '.[]' ${tempjsonpath}|grep "null" && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】参数变量生成失败,请检查设置项 `/usr/bin/jq -r '.' ${tempjsonpath}|grep "null"`" >> ${logfile} + + curl -X POST -H "$content_type" -d "${data}" "${diyurl}" +} + +# 下载设备MAC厂商信息 +function down_oui(){ + [ -f ${oui_base} ] && local logrow=$(grep -c "" ${oui_base}) || local logrow="0" + [ $logrow -lt "10" ] && rm -f ${oui_base} >/dev/null 2>&1 + if [ ! -z "$oui_data" ] && [ "$oui_data" -ne "3" ] && [ ! -f ${oui_base} ]; then + echo "`date "+%Y-%m-%d %H:%M:%S"` 【初始化】设备MAC厂商信息不存在,重新下载" >> ${logfile} + wget --no-check-certificate -t 3 -T 15 -O ${dir}oui.txt https://standards-oui.ieee.org/oui/oui.txt >/dev/null 2>&1 + if [ -f ${dir}oui.txt ] && [ "$oui_data" -eq "1" ]; then + cat ${dir}oui.txt|grep "base 16"|grep -i "apple\|aruba\|asus\|autelan\|belkin\|bhu\|buffalo\|cctf\|cisco\|comba\|datang\|dell\|dlink\|dowell\|ericsson\|fast\|feixun\|\ +fiberhome\|fujitsu\|grentech\|h3c\|hisense\|hiwifi\|honghai\|honghao\|hp\|htc\|huawei\|intel\|jinli\|jse\|lenovo\|lg\|liteon\|malata\|meizu\|mercury\|meru\|moto\|netcore\|\ +netgear\|nokia\|omron\|oneplus\|oppo\|philips\|router_unkown\|samsung\|shanzhai\|sony\|start_net\|sunyuanda\|tcl\|tenda\|texas\|tianyu\|tp-link\|ubq\|undefine\|VMware\|\ +utstarcom\|volans\|xerox\|xiaomi\|zdc\|zhongxing\|smartisan" > ${oui_base} && echo "`date "+%Y-%m-%d %H:%M:%S"` 【初始化】设备MAC厂商信息下载成功" >> ${logfile} || echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】设备MAC厂商信息下载失败" >> ${logfile} + fi + if [ -f ${dir}oui.txt ] && [ "$oui_data" -eq "2" ]; then + cat ${dir}oui.txt|grep "base 16" > ${oui_base} && echo "`date "+%Y-%m-%d %H:%M:%S"` 【初始化】设备MAC厂商信息下载成功" >> ${logfile} || echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】设备MAC厂商信息下载失败" >> ${logfile} + fi + rm -f ${dir}oui.txt >/dev/null 2>&1 + fi +} + +# 清理临时文件 +function deltemp(){ + unset title content ipAddress_logrow online_list online_mac mac_online_status gatewayinfo gateway_iplist + rm -f ${dir}title ${dir}content ${dir}tmp_downlist ${dir}send_enable.lock ${tempjsonpath} ${dir}cookies.txt >/dev/null 2>&1 + [ ! -f ${dir}ipAddress ] && rm -f ${dir}client/* >/dev/null 2>&1 + LockFile unlock + [ -f ${logfile} ] && local logrow=$(grep -c "" ${logfile}) || local logrow="0" + [ $logrow -gt 500 ] && sed -i '1,100d' ${logfile} && echo "`date "+%Y-%m-%d %H:%M:%S"` 【清理】日志超出上限,删除前 100 条" >> ${logfile} +} + +# 检测程序开关 +function enable_detection(){ + [ ! "$1" ] && local time_n=1 + for i in `seq 1 $time_n`; do + get_config serverchan_enable;[ -z "$serverchan_enable" ] || [ "$serverchan_enable" -eq "0" ] && `/etc/init.d/serverchan stop` || sleep 1 + done +} + +# 获取 ip +function getip(){ + [ ! "$1" ] && return + if [ $1 == "wanipv4" ] ;then + [ ! -z "$ipv4_interface" ] && local wanIP=$(/sbin/ifconfig ${ipv4_interface}|awk '/inet addr/ {print $2}'|awk -F: '{print $2}'|grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') + [ -z "$ipv4_interface" ] && local wanIP=$(getinterfacelist|grep '\"address\"'|grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') + echo "$wanIP" + elif [ $1 == "hostipv4" ] ;then + function get_hostipv4() + { + local url_number=`echo "$ipv4_urllist"|wc -l` + local ipv4_URL=`echo "$ipv4_urllist"| sed -n "$(rand 1 $url_number)p"|sed -e 's/\r//g'` + [ ! -z "$ipv4_interface" ] && local hostIP=$(curl -k -s -4 --interface ${ipv4_interface} -m 5 ${ipv4_URL}) || local hostIP=$(curl -k -s -4 -m 5 ${ipv4_URL}) + echo $hostIP|grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'|head -n1 + } + local hostIP=`get_hostipv4` + [ -z "$hostIP" ] && sleep 1 && local hostIP=`get_hostipv4` + [ -z "$hostIP" ] && sleep 1 && local hostIP=`get_hostipv4` + echo $hostIP # 重试,偷懒,有空再优化 + elif [ $1 == "wanipv6" ] ;then + [ ! -z "$ipv6_interface" ] && local wanIPv6=$(ip addr show ${ipv6_interface}|grep -v deprecated|grep -A1 'inet6 [^f:]'|sed -nr ':a;N;s#^ +inet6 ([a-f0-9:]+)/.+? scope global .*? valid_lft ([0-9]+sec) .*#\2 \1#p;ta'|sort -nr|head -n1|awk '{print $2}') + [ -z "$ipv6_interface" ] && local wanIPv6=$(ip addr show|grep -v deprecated|grep -A1 'inet6 [^f:]'|sed -nr ':a;N;s#^ +inet6 ([a-f0-9:]+)/.+? scope global .*? valid_lft ([0-9]+sec) .*#\2 \1#p;ta'|sort -nr|head -n1|awk '{print $2}') + echo "$wanIPv6" + elif [ $1 == "hostipv6" ] ;then + function get_hostipv6() + { + local urlv6_number=`echo "$ipv6_urllist"|wc -l` + local ipv6_URL=`echo "$ipv6_urllist"| sed -n "$(rand 1 $urlv6_number)p"|sed -e 's/\r//g'` + [ ! -z "$ipv6_interface" ] && local hostIPv6=$(curl -k -s -6 --interface ${ipv6_interface} -m 5 ${ipv6_URL}) || local hostIPv6=$(curl -k -s -6 -m 5 ${ipv6_URL}) + echo $hostIPv6|grep -oE '([\da-fA-F0-9]{1,4}(:{1,2})){1,15}[\da-fA-F0-9]{1,4}'|head -n1 + } + local hostIPv6=`get_hostipv6` + [ -z "$hostIPv6" ] && sleep 1 && local hostIPv6=`get_hostipv6` + [ -z "$hostIPv6" ] && sleep 1 && local hostIPv6=`get_hostipv6` + echo $hostIPv6 # 重试,偷懒,有空再优化 + fi +} + +# 获取接口信息 +function getinterfacelist(){ + [ `ubus list|grep -w -i "network.interface.wan"|wc -l` -ge "1" ] && ubus call network.interface.wan status && return + local ubuslist=`ubus list|grep -i "network.interface."|grep -v "loopback"|grep -v -i "wan6"|grep -v -i "lan6"|grep -v -i "ipsec_server"` + [ `echo "${ubuslist}" |wc -l` -eq "1" ] && ubus call ${ubuslist} status && return +} + +# 获取接口在线时间 +function getinterfaceuptime(){ + getinterfacelist|grep \"uptime\"|sed $'s/\"uptime": //g'|sed $'s/\,//g' +} + +# 查询 MAC 地址 +function getmac(){ + [ -f "${dir}ipAddress" ] && local tmp_mac=`cat ${dir}ipAddress|grep -w ${1}|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` + ( echo "$tmp_mac"|grep -q "unknown" ) && unset tmp_mac # 为unknown时重新读取 + [ -f "${dir}tmp_downlist" ] && [ -z "$tmp_mac" ] && local tmp_mac=`cat ${dir}tmp_downlist|grep -w ${1}|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` + ( echo "$tmp_mac"|grep -q "unknown" ) && unset tmp_mac # 为unknown时重新读取 + [ -f "/tmp/dhcp.leases" ] && [ -z "$tmp_mac" ] && local tmp_mac=`cat /tmp/dhcp.leases|grep -w ${1}|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` + [ -z "$tmp_mac" ] && local tmp_mac=`cat /proc/net/arp|grep "0x2\|0x6"|grep -w ${1}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` + [ -z "$tmp_mac" ] && local tmp_mac="unknown" + echo $tmp_mac |tr -d '\n\r' +} + +# 查询主机名 +function getname(){ + local tmp_name=`echo "$device_aliases"|grep -i $2|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` + [ -f "${dir}ipAddress" ] && [ -z "$tmp_name" ] && local tmp_name=`cat ${dir}ipAddress|grep -w ${1}|awk '{print $3}'|grep -v "^$"|sort -u|head -n1` + ( ! echo "$tmp_name"|grep -q -w "unknown\|*" ) && [ ! -z "$tmp_name" ] && echo "$tmp_name" && return || unset tmp_name # 为unknown时重新读取 + [ -f "${dir}tmp_downlist" ] && [ -z "$tmp_name" ] && local tmp_name=`cat ${dir}tmp_downlist|grep -w ${1}|awk '{print $3}'|grep -v "^$"|sort -u|head -n1` + ( ! echo "$tmp_name"|grep -q -w "unknown\|*" ) && [ ! -z "$tmp_name" ] && echo "$tmp_name" && return || unset tmp_name # 为unknown时重新读取 + [ -f "/tmp/dhcp.leases" ] && [ -z "$tmp_name" ] && local tmp_name=`cat /tmp/dhcp.leases|grep -w ${1}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` + ( ! echo "$tmp_name"|grep -q -w "unknown\|*" ) && [ ! -z "$tmp_name" ] && echo "$tmp_name" && return || unset tmp_name # 为unknown时重新读取 + [ -z "$dhcp_config" ] && dhcp_config=`uci show dhcp|grep "ip\|mac\|name"` + for dhcp_config_str in "host" "domain"; do + local dhcp_ip_n=`echo "$dhcp_config"|grep -w ^dhcp.@${dhcp_config_str}.*ip=.${1}|sed -nr 's#^dhcp.(.*).ip.*#\1#gp'` 2>/dev/null + [ ! -z "$dhcp_ip_n" ] && [ -z "$tmp_name" ] && local tmp_name=`uci get dhcp.${dhcp_ip_n}.name` 2>/dev/null + local dhcp_mac_n=`echo "$dhcp_config"|grep -i ^dhcp.@${dhcp_config_str}.*mac=.${2}|sed -nr 's#^dhcp.(.*).mac.*#\1#gp'` 2>/dev/null + [ ! -z "$dhcp_mac_n" ] && [ -z "$tmp_name" ] && local tmp_name=`uci get dhcp.${dhcp_ip_n}.name` 2>/dev/null + [ ! -z "$tmp_name" ] && break + done + ( ! echo "$tmp_name"|grep -q -w "unknown\|*" ) && [ ! -z "$tmp_name" ] && echo "$tmp_name" && return || unset tmp_name # 为unknown时重新读取 + local tmp_name=`echo "$gatewayinfo"|grep -w ${1}|awk '{print $2}'` + ( ! echo "$tmp_name"|grep -q -w "unknown\|*" ) && [ ! -z "$tmp_name" ] && echo "$tmp_name" && return || unset tmp_name # 为unknown时重新读取 + [ -f "$oui_base" ] && local tmp_name=$(cat $oui_base|grep -i $(echo "$2"|cut -c 1,2,4,5,7,8)|sed -nr 's#^.*16)..(.*)#\1#gp'|sed 's/ /_/g') + [ ! -z "$oui_data" ] && [ "$oui_data" -eq "4" ] && local tmp_name=$(curl -sS "https://standards-oui.ieee.org/oui/oui.txt"|grep -i $(echo "$2"|cut -c 1,2,4,5,7,8)|sed -nr 's#^.*16)..(.*)#\1#gp'|sed 's/ /_/g') + [ -z "$tmp_name" ] && local tmp_name="unknown" + echo $tmp_name |tr -d '\n\r' +} + +# 从光猫处获取设备信息 +function getgateway(){ + local loginfo=`curl -s -L "${gateway_host_url}" -c ${dir}cookies.txt -d "${gateway_username_id}=${gateway_username}&${gateway_password_id}=${gateway_password}"` 2>/dev/null + [ ! -z "$loginfo" ] && local mytoken=$(echo $loginfo |sed 's/{/\n/g' | grep token |awk '/realRestart/{print $2}'| sed $'s/\'//g') + [ ! -z "$mytoken" ] && local get_gateway=`curl -s -b ${dir}cookies.txt "${gateway_info_url}" -d 'token='$mytoken | /usr/bin/jq '.[] | iterables| "\(.ip) \(.devName) \(.model)"'|sed 's/unknown//g'|sed 's/ / /g'|sed 's/ /_/g'|sed 's/_/ /'|sed 's/\"//g'` + [ ! -z "$get_gateway" ] && curl -s -b ${dir}cookies.txt "${gateway_logout_url}" -d 'token='$mytoken 2>/dev/null + echo "$get_gateway" +} + +# 查询设备接口 +function getinterface(){ + [ -z "${1}" ] && return + [ "${1}" == "unknown" ] && return + [ -f "${dir}ipAddress" ] && local ip_interface=`cat ${dir}ipAddress|grep -w ${1}|awk '{print $5}'|grep -v "^$"|sort -u|head -n1` + [ -f "${dir}tmp_downlist" ] && [ -z "$ip_interface" ] && local ip_interface=`cat ${dir}tmp_downlist|grep -w ${1}|awk '{print $5}'|grep -v "^$"|sort -u|head -n1` + if [ -z "$ip_interface" ] && [ ! -z "$wlan_interface" ]; then + for interface in $wlan_interface; do + local ip_interface=`iw dev $interface station dump 2>/dev/null|grep Station|grep -i -w ${1}|sed -nr 's#^.*on (.*))#\1#gp'` >/dev/null 2>&1 + [ ! -z "$ip_interface" ] && echo "$ip_interface" && return + done + fi + [ -z "$ip_interface" ] && local ip_interface=`cat /proc/net/arp|grep "0x2\|0x6"|grep -i -w ${1}|awk '{print $6}'|grep -v "^$"|sort -u|head -n1` + echo $ip_interface |tr -d '\n\r' +} + +# ping +function getping(){ + local ip_interface=`getinterface ${2}` + [ "$iw_version" ] && [ "$ip_interface" ] && local wlan_online=`iw dev ${ip_interface} station dump|grep -i -w ${2}|grep Station` >/dev/null 2>&1 + [ "$wlan_online" ] && return 0 + for i in `seq 1 ${4}`; do + ( ! echo "$ip_ms"|grep -q "ms" ) && local interface=`cat /proc/net/arp|grep -w ${1}|awk '{print $6}'|grep -v "^$"|sort -u|head -n1` && [ ! -z "$interface" ] && local ip_ms=`arping -I ${interface} -c 20 -f -w ${3} ${1}` 2>/dev/null + ( ! echo "$ip_ms"|grep -q "ms" ) && local ip_ms=`ping -c 5 -w ${3} ${1}|grep -v '100% packet loss'` 2>/dev/null + ( ! echo "$ip_ms"|grep -q "ms" ) && sleep 1 + done + ( echo "$ip_ms"|grep -q "ms" ) +} + +# CPU 占用率 +function getcpu(){ + local AT=$(cat /proc/stat|grep "^cpu "|awk '{print $2+$3+$4+$5+$6+$7+$8 " " $2+$3+$4+$7+$8}') + sleep 3 + local BT=$(cat /proc/stat|grep "^cpu "|awk '{print $2+$3+$4+$5+$6+$7+$8 " " $2+$3+$4+$7+$8}') + printf "%.01f%%" $(echo ${AT} ${BT}|awk '{print (($4-$2)/($3-$1))*100}') +} + +# 获取SOC温度 (取所有传感器温度最大值) +function soc_temp(){ + [ -z "$soc_code" ] && local soctemp=`sensors 2>/dev/null|grep °C|sed -nr 's#^.*:.*\+(.*)°C .*#\1#gp'|sort -nr|head -n1` + [ -z "$soc_code" ] && [ -z "$soctemp" ] && local soctemp=`cat /sys/class/thermal/thermal_zone*/temp 2>/dev/null|sort -nr|head -n1|cut -c-2` + [ "$soc_code" == "pve" ] && [ ! -z "$server_host" ] && local soctemp=`ssh -i /root/.ssh/id_rsa root@${server_host} -p ${server_port} sensors 2>/dev/null|grep Core|sed -nr 's#^.*:.*\+(.*)°C .*#\1#gp'|sort -nr|head -n1` + [ ! -z "$soctemp" ] && echo "$soctemp" && return + [ ! -z "$soc_code" ] && eval `echo "$soc_code"` 2>/dev/null +} + +# 流量数据 +function usage(){ + [ ! -f "/usr/sbin/wrtbwmon" ] || [ ! "$1" ] && return + if [ $1 == "update" ] ;then + function version_le() { test "$(echo "$@"|tr " " "\n"|sort -n|head -n 1)" == "$1"; } + function version_ge() { test "$(echo "$@"|tr " " "\n"|sort -r|head -n 1)" == "$1"; } + [ ! -z "$wr_version" ] && ( version_ge "${wr_version}" "1.2.0" ) && wrtbwmon -f ${dir}usage.db 2>/dev/null && return + [ ! -z "$wr_version" ] && ( version_le "${wr_version}" "1.0.0" ) || [ -z "$wr_version" ] && wrtbwmon update ${dir}usage.db 2>/dev/null && return + elif [ $1 == "get" ] ;then + [ ! -f "${dir}usage.db" ] && [ ! "$3" ] && echo `bytes_for_humans 0` && return + [ ! -f "${dir}usage.db" ] && [ "$3" ] && echo 0 && return + [ -z "$total_n" ] && total_n=`cat ${dir}usage.db|head -n1|grep "total"|sed 's/,/\n/g'|awk '/total/{print NR}'` 2>/dev/null + [ -z "$total_n" ] && total_n="6" + [ "$2" ] && local tmptotal=`cat ${dir}usage.db|sed 's/,,,/,0,0,/g'|sed 's/,,/,0,/g'|sed 's/,/ /g'|grep -i -w ${2}|awk "{print "'$'$total_n"}"|grep -v "^$"|sort -u|head -n1` 2>/dev/null + [ -z "$tmptotal" ] && local tmptotal="0" + [ ! "$3" ] && echo `bytes_for_humans ${tmptotal}` || echo $tmptotal + elif [ $1 == "down" ] ;then + [ "$2" ] && sed -i "/,${2},/d" ${dir}usage.db 2>/dev/null + fi +} + +# 流量数据单位换算 +function bytes_for_humans { + [ ! "$1" ] && return + [ "$1" -gt 1073741824 ] && echo "`awk 'BEGIN{printf "%.2f\n",'$1'/'1073741824'}'` GB" && return + [ "$1" -gt 1048576 ] && echo "`awk 'BEGIN{printf "%.2f\n",'$1'/'1048576'}'` MB" && return + [ "$1" -gt 1024 ] && echo "`awk 'BEGIN{printf "%.2f\n",'$1'/'1024'}'` KB" && return + echo "${1} bytes" +} + +# 设备异常流量检测 +function get_client_usage(){ + [ -z "$client_usage" ] && return + [ "$client_usage" -ne "1" ] && return + [ -z "$client_usage_max" ] && return + [ -z "$get_client_usage_time" ] && get_client_usage_time=`date +%s` + ( echo $client_usage_max|sed -r 's/.*(.)$/\1/'|grep -q "K\|k" ) && client_usage_max=`expr ${client_usage_max%?} \* 1024` + ( echo $client_usage_max|sed -r 's/.*(.)$/\1/'|grep -q "M\|m" ) && client_usage_max=`expr ${client_usage_max%?} \* 1048576` + ( echo $client_usage_max|sed -r 's/.*(.)$/\1/'|grep -q "G\|g" ) && client_usage_max=`expr ${client_usage_max%?} \* 1073741824` + [ -z "$client_usage_disturb" ] && client_usage_disturb="0" + [ "$client_usage_disturb" -eq "0" ] && [ -f "${dir}ipAddress" ] && local MACLIST=`cat ${dir}ipAddress|awk '{print $2}'|grep -v "^$"|sort -u` + [ "$client_usage_disturb" -eq "1" ] && [ ! -z "$client_usage_whitelist" ] && local MACLIST=`echo "$client_usage_whitelist"` + [ -z "$MACLIST" ] && return + + if [ "$((`date +%s`-$get_client_usage_time))" -ge "60" ]; then + > ${dir}client_usage_aliases + for mac in $MACLIST; do + ( ! cat ${dir}ipAddress|grep -q -i -w $mac|grep -v "^$"|sort -u|head -n1 ) && continue + echo "$mac" `usage get ${mac} bytes` >> ${dir}client_usage_aliases + [ -f "${dir}old_client_usage_aliases" ] && get_client_usage_bytes=`cat ${dir}old_client_usage_aliases|grep -i -w $mac|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` || continue + [ -z "$get_client_usage_bytes" ] && get_client_usage_bytes="0" + if [ "$((`usage get ${mac} bytes`-$get_client_usage_bytes))" -ge "$client_usage_max" ]; then + local ip=`cat ${dir}ipAddress|grep -i -w $mac|awk '{print $1}'|grep -v "^$"|sort -u|head -n1` + local ip_name=`getname ${ip} ${mac}` + local tmp_usage=$(bytes_for_humans $(expr `usage get ${mac} bytes` - ${get_client_usage_bytes})) + local time_up=`cat ${dir}ipAddress|grep -w ${ip}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` + local ip_total=`usage get $mac` && [ ! -z "$ip_total" ] && local ip_total="${str_linefeed}${str_tab}总计流量: ${str_space}${str_space}${str_space}${str_space}${ip_total}" + local time1=`date +%s` + local time1=$(time_for_humans `expr ${time1} - ${time_up}`) + if [ -z "$title" ]; then + title="${ip_name} 流量异常" + content="${content}${str_splitline}${str_title_start} 设备流量异常${str_title_end}${str_linefeed}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${ip}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${mac}$ip_total${str_linefeed}${str_tab}一分钟内流量: ${str_space}${str_space}${tmp_usage}${str_linefeed}${str_tab}在线时间: ${str_space}${str_space}${str_space}${str_space}${time1}" + elif ( echo "$title"|grep -q "流量异常" ); then + title="${ip_name} ${title}" + content="${content}${str_splitline}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${ip}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${mac}$ip_total${str_linefeed}${str_tab}一分钟内流量: ${str_space}${str_space}${str_space}${tmp_usage}${str_linefeed}${str_tab}在线时间: ${str_space}${str_space}${str_space}${str_space}${time1}" + else + title="设备状态变化" + content="${content}${str_splitline}${str_title_start} 设备流量异常${str_title_end}${str_linefeed}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${ip}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${mac}$ip_total${str_linefeed}${str_tab}一分钟内流量: ${str_space}${str_space}${str_space}${tmp_usage}${str_linefeed}${str_tab}在线时间: ${str_space}${str_space}${str_space}${str_space}${time1}" + fi + fi + done + cat ${dir}client_usage_aliases > ${dir}old_client_usage_aliases + get_client_usage_time=`date +%s` + fi +} + +# 时间单位换算 +function time_for_humans { + [ ! "$1" ] && return + if [ "$1" -lt 60 ]; then + echo "${1} 秒" + elif [ "$1" -lt 3600 ]; then + local usetime_min=`expr $1 / 60` + local usetime_sec=`expr $usetime_min \* 60` + local usetime_sec=`expr $1 - $usetime_sec` + echo "${usetime_min} 分 ${usetime_sec} 秒" + elif [ "$1" -lt 86400 ]; then + local usetime_hour=`expr $1 / 3600` + local usetime_min=`expr $usetime_hour \* 3600` + local usetime_min=`expr $1 - $usetime_min` + local usetime_min=`expr $usetime_min / 60` + echo "${usetime_hour} 小时 ${usetime_min} 分" + else + local usetime_day=`expr $1 / 86400` + local usetime_hour=`expr $usetime_day \* 86400` + local usetime_hour=`expr $1 - $usetime_hour` + local usetime_hour=`expr $usetime_hour / 3600` + echo "${usetime_day} 天 ${usetime_hour} 小时" + fi +} + +# 计算字符真实长度 +function length_str { + [ ! "$1" ] && return + local length_zh=`echo "$1"|awk '{print gensub(/[\u4e00-\u9FA5A-Za-z0-9_]/,"","g",$0)}'|awk -F "" '{print NF}'` + local length_en=`echo "$1"|awk '{print gensub(/[^\u4e00-\u9FA5A-Za-z0-9_]/,"","g",$0)}'|awk -F "" '{print NF}'` + echo `expr $length_zh / 3 \* 2 + $length_en` +} + +# 截取字符,避免中文乱码 +function cut_str { + [ ! "$1" ] && return + [ ! "$2" ] && return + [ `length_str $1` -le "$2" ] && echo "$1" && return + local temp_length=$2 + while [ $(length_str `echo "$1"|cut -c -$temp_length`) -lt "$2" ]; do + temp_length=`expr $temp_length + 1` + done + while [ $(printf "%d" \'`echo "$1"|cut -c $temp_length`) -ge "128" ] && [ $(printf "%d" \'`echo "$1"|cut -c $temp_length`) -lt "224" ]; do + temp_length=`expr $temp_length + 1` + done + temp_length=`expr $temp_length - 1` + echo $(echo "$1"|cut -c -$temp_length)"*" +} + +# 随机数 +function rand(){ + local min=$1 + local max=$(($2- $min + 1)) + local num=$(date +%s%N) + echo $(($num % $max + $min)) +} + +# 在线设备列表 +function serverchan_first(){ + gatewayinfo=`getgateway` + [ -f "${dir}ipAddress" ] && local IPLIST=`cat ${dir}ipAddress|awk '{print $1}'|grep -v "^$"|sort -u` + for ip in $IPLIST; do + read -u 5 + { + down $ip + echo "" >&5 + }& + done + wait + unset ip IPLIST + local IPLIST=`cat /proc/net/arp|grep "0x2\|0x6"|awk '{print $1}'|grep -v "^169.254."|grep -v "^$"|sort -u|grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'` + local gateway_iplist=`echo "${gatewayinfo}"|awk '{print $1}'` + [ ! -z "$gateway_iplist" ] && local IPLIST=`echo -e "${IPLIST}\n${gateway_iplist}"|grep -v "^$"|sort -u` + for ip in $IPLIST; do + read -u 5 + { + up $ip + echo "" >&5 + }& + done + wait +} + +# 创建计划任务 +function serverchan_cron(){ + function del_cron(){ + ( echo `crontab -l 2>/dev/null`|grep -q "serverchan" ) && crontab -l > conf && sed -i "/serverchan/d" conf && crontab conf && rm -f conf >/dev/null 2>&1 + } + function re_cron(){ + /etc/init.d/cron stop + /etc/init.d/cron start + } + del_cron + if [ -z "$serverchan_enable" ]; then + re_cron + return + fi + + # 重置流量 + if [ ! -z "$reset_regularly" ] && [ "$reset_regularly" -eq "1" ]; then + crontab -l 2>/dev/null > conf && echo -e "0 0 * * * rm /tmp/serverchan/usage.db >/dev/null 2>&1" >> conf && crontab conf && rm -f conf >/dev/null 2>&1 + crontab -l 2>/dev/null > conf && echo -e "0 0 * * * rm /tmp/serverchan/usage6.db >/dev/null 2>&1" >> conf && crontab conf && rm -f conf >/dev/null 2>&1 + fi + [ ! -z "$regular_time_2" ] && local regular_time_2=",${regular_time_2}" + [ ! -z "$regular_time_3" ] && local regular_time_3=",${regular_time_3}" + # 定时发送 + if [ ! -z "$regular_time" ] || [ ! -z "$regular_time_2" ] || [ ! -z "$regular_time_3" ]; then + crontab -l 2>/dev/null > conf && echo -e "0 $regular_time$regular_time_2$regular_time_3 * * * /usr/bin/serverchan/serverchan send &" >> conf && crontab conf && rm -f conf >/dev/null 2>&1 + # 间隔发送 + elif [ ! -z "$interval_time" ]; then + crontab -l 2>/dev/null > conf && echo -e "0 */$interval_time * * * /usr/bin/serverchan/serverchan send &" >> conf && crontab conf && rm -f conf >/dev/null 2>&1 + fi + re_cron +} + +# 免打扰检测 +function serverchan_disturb(){ + [ -z "$serverchan_sheep" ] || [ -z "$starttime" ] || [ -z "$endtime" ] && return 0 + if [ `date +%H` -ge $endtime -a $starttime -lt $endtime ] || [ `date +%H` -lt $starttime -a $starttime -lt $endtime ] || [ `date +%H` -lt $starttime -a `date +%H` -ge $endtime -a $starttime -gt $endtime ]; then + unset sheep_starttime + rm -f ${dir}sheep_usage ${dir}old_sheep_usage 2>/dev/null + disturb_text=`/usr/bin/jq -r '._api' ${jsonpath}` + return 0 + else + [ -z "$sheep_starttime" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【免打扰】夜深了,该休息了" >> ${logfile} && sheep_starttime=`date +%s` + if [ "$serverchan_sheep" -eq "1" ] ;then + while [ `date +%H` -lt "$endtime" ]; do + enable_detection + sleep $sleeptime + done + elif [ "$serverchan_sheep" -eq "2" ] ;then + disturb_text="【免打扰】" + return 1 + fi + fi +} + +# 文件锁 +function LockFile(){ + if [ $1 = "lock" ] ;then + [ ! -f "${dir}serverchan.lock" ] && > ${dir}serverchan.lock && return + while [ -f "${dir}serverchan.lock" ]; do + enable_detection 1 + done + LockFile lock + fi + [ $1 = "unlock" ] && rm -f ${dir}serverchan.lock >/dev/null 2>&1 + return 0 +} + +# 检测黑白名单 +function blackwhitelist(){ + [ ! "$1" ] && return 1 + [ -z "$serverchan_whitelist" ] && [ -z "$serverchan_blacklist" ] && [ -z "$serverchan_interface" ] && [ -z "$MAC_online_list" ] && [ -z "$MAC_offline_list" ] && return 0 + [ ! -z "$serverchan_whitelist" ] && ( echo "$serverchan_whitelist"|grep -q -i -w $1 ) && return 1 + [ ! -z "$serverchan_blacklist" ] && ( ! echo "$serverchan_blacklist"|grep -q -i -w $1 ) && return 1 + [ ! -z "$serverchan_interface" ] && ( ! echo `getinterface ${1}`|grep -q -i -w $serverchan_interface ) && return 1 + [ ! -z "$MAC_online_list" ] && [ ! -z "$mac_online_status" ] && return 1 + [ ! -z "$MAC_online_list" ] && ( echo "$MAC_online_list"|grep -q -i -w $1 ) && return 1 + [ ! -z "$MAC_offline_list" ] && [ -z "$mac_online_status" ] && return 1 + return 0 +} + +# 重启网络服务 +function network_restart(){ +cat>${dir}network_restart</dev/null 2>&1 & +/etc/init.d/firewall restart >/dev/null 2>&1 & +/etc/init.d/dnsmasq restart >/dev/null 2>&1 & +EOF + chmod 0755 ${dir}network_restart && ${dir}network_restart + rm -f ${dir}network_restart >/dev/null 2>&1 +} + +# 查看无人值守任务设备是否在线 +function geterrdevicealiases(){ + [ -z "$err_device_aliases" ] && return + [ -f ${dir}ipAddress ] && local logrow=$(grep -c "" ${dir}ipAddress) || local logrow="0";[ $logrow -eq "0" ] && return + local MACLIST=`cat ${dir}ipAddress|awk '{print $2}'|grep -v "^$"|sort -u` + for mac in $MACLIST; do + [ -z "$err_mac" ] && [ ! -z "$mac" ] && local err_mac=`echo "$err_device_aliases"|grep -i $mac|grep -v "^$"|sort -u|head -n1` + done + # 进入免打扰时间已经超过一小时 + if [ ! -z "$sheep_starttime" ] && [ "$((`date +%s`-$sheep_starttime))" -ge "3600" ]; then + > ${dir}sheep_usage + local MACLIST=`echo "$err_device_aliases"|grep -v "^$"|sort -u` + for mac in $MACLIST; do + [ ! -z "$mac" ] && local tmptotal=`usage get ${mac} bytes` + [ ! -z "$tmptotal" ] && awk 'BEGIN{printf "%.0f\n",'$tmptotal'/'204800'}' 2>/dev/null >> ${dir}sheep_usage + done + old_sheep_usage=`cat ${dir}old_sheep_usage` 2>/dev/null + sheep_usage=`cat ${dir}sheep_usage` 2>/dev/null + [ "$old_sheep_usage" == "$sheep_usage" ] && [ -z "$sheep_nousage_starttime" ] && sheep_nousage_starttime=`date +%s` + [ "$old_sheep_usage" != "$sheep_usage" ] && unset sheep_nousage_starttime && cat ${dir}sheep_usage 2>/dev/null > ${dir}old_sheep_usage + [ ! -z "$sheep_nousage_starttime" ] && [ "$((`date +%s`-$sheep_nousage_starttime))" -ge "300" ] && unset err_mac + fi + [ -z "$err_mac" ] +} + +# 无人值守任务 +function unattended(){ + [ -z "$err_enable" ] || [ "$err_enable" -ne "1" ] && return + [ ! -z "$err_sheep_enable" ] && [ "$err_sheep_enable" -eq "1" ] && [ -z "$sheep_starttime" ] && return + geterrdevicealiases;[ $? -eq "1" ] && return + + if [ ! -z "$system_time_event" ]; then + local interfaceuptime=`getinterfaceuptime` + if [ ! -z "$autoreboot_time" ] && [ `cat /proc/uptime|awk -F. '{run_hour=$1/3600;printf("%d",run_hour)}'` -ge "$autoreboot_time" ] && [ "$system_time_event" -eq "1" ]; then + echo "`date "+%Y-%m-%d %H:%M:%S"` 【无人值守任务】重启路由器咯" >> ${logfile} + cat ${logfile} > /usr/bin/serverchan/errlog + sleep 2 && reboot && exit + elif [ ! -z "$network_restart_time" ] && [ ! -z "$interfaceuptime" ] && [ `echo "$interfaceuptime"|awk -F. '{run_hour=$1/3600;printf("%d",run_hour)}'` -ge "$network_restart_time" ] && [ "$system_time_event" -eq "2" ]; then + echo "`date "+%Y-%m-%d %H:%M:%S"` 【无人值守任务】重新拨号咯" >> ${logfile} + ifup wan >/dev/null 2>&1 + sleep 60 + fi + fi + + [ -z "$public_ip_today" ] && public_ip_today=`date +"%d"` + [ -z "$public_ip_count" ] && public_ip_count="0" + [ $public_ip_today -ne `date +"%d"` ] && public_ip_today=`date +"%d"` && public_ip_count=1 + if [ ! -z "$public_ip_event" ] && [ ! -z "$public_ip_retry_count" ] && [ "$public_ip_count" -le "$public_ip_retry_count" ]; then + public_ip_count=`expr $public_ip_count + 1` + local wanIP=`getip wanipv4` + local hostIP=`getip hostipv4` + if [ ! -z "$wanIP" ] && [ ! -z "$hostIP" ] && ( ! echo "$wanIP"|grep -q -w ${hostIP} );then + echo "`date "+%Y-%m-%d %H:%M:%S"` 【无人值守任务】重拨尝试获取公网 ip,当前第 $public_ip_count 次 " >> ${logfile} + ifup wan >/dev/null 2>&1 + sleep 60 + local wanIP=`getip wanipv4` && local hostIP=`getip hostipv4` + [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -eq "1" ] && local IPv4=${wanIP} + [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -eq "2" ] && local IPv4=${hostIP} + [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -eq "1" ] && local IPv6=`getip wanipv6` + [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -eq "2" ] && local IPv6=`getip hostipv6` + [ ! -z "$wanIP" ] && [ ! -z "$hostIP" ] && ( ! echo "$wanIP"|grep -q -w ${hostIP} ) && echo IPv4 $IPv4 > ${dir}ip && echo -e IPv6 $last_IPv6 >> ${dir}ip + fi + fi +} + +# 检测网络状态 +function rand_geturl(){ + function getcheck(){ + local urllist="https://www.163.com https://www.qq.com https://www.baidu.com https://www.qidian.com https://www.douban.com" + local url_number=`expr $(echo "$urllist"|grep -o ' '|wc -l) + 1` + local url_str=`echo "$urllist"|awk -v i=$(rand 1 $url_number) '{print $i}'` + echo `curl -k -s -w "%{http_code}" -m 5 ${url_str} -A "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36" -o /dev/null` + } + local check=`getcheck` + while [ -z "$check" ] || [ "$check" -ne "200" ]; do + local check=`getcheck` + if [ ! -z "$check" ] && [ "$check" -eq "200" ]; then + [ ! -z "$network_enable" ] && [ "$network_enable" -eq "404" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【网络状态】网络恢复正常.." >> ${logfile} + local network_enable="200" + else + [ -z "$network_enable" ] || [ "$network_enable" -eq "200" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】当前网络不通!停止检测! " >> ${logfile} + local network_enable="404" + [ -z "$network_err_time" ] && network_err_time=`date +%s` + if [ ! -z "$network_err_event" ] && [ "$((`date +%s`-$network_err_time))" -ge "600" ]; then + > ${dir}send_enable.lock && serverchan_first && deltemp + geterrdevicealiases + if [ "$?" -eq "0" ]; then + [ -f /usr/bin/serverchan/autoreboot_count ] && retry_count=`cat /usr/bin/serverchan/autoreboot_count` && rm -f /usr/bin/serverchan/autoreboot_count >/dev/null 2>&1 + [ ! -z ${retry_count} ] && retry_count=0;retry_count=`expr $retry_count + 1` + if [ "$network_err_event" -eq "1" ] ;then + if [ "$retry_count" -lt "3" ] ;then + echo "$retry_count" > /usr/bin/serverchan/autoreboot_count + echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】正在尝试重启路由,当前第 $retry_count 次 " >> ${logfile} + cat ${logfile} > /usr/bin/serverchan/errlog + sleep 2 && reboot && exit + fi + [ "$retry_count" -eq "3" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】已经重启路由2次,修复失败,请主人自行修复哦" >> ${logfile} + elif [ "$network_err_event" -eq "2" ] ;then + [ "$retry_count" -lt "3" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】正在尝试重启网络,当前第 $retry_count 次 " >> ${logfile} && ifup wan >/dev/null 2>&1 + [ "$retry_count" -eq "3" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】已经重启网络2次,修复失败,请主人自行修复哦 " >> ${logfile} + elif [ "$network_err_event" -eq "3" ] ;then + if [ "$retry_count" -eq "1" ] ;then + echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】正在尝试修复网络,当前第 1 次,重启网络服务中 " >> ${logfile} && network_restart + elif [ "$retry_count" -eq "2" ] ;then + echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】正在尝试修复网络,当前第 2 次,关闭可能造成网络断开的软件" >> ${logfile} + [ `uci get koolproxy.@global[0].enabled 2>/dev/null` -eq "1" ] && [ `uci get koolproxy.@global[0].koolproxy_mode 2>/dev/null` -eq "1" ] && /etc/init.d/koolproxy stop >/dev/null 2>&1 + [ `uci get adbyby.@adbyby[0].enable 2>/dev/null` -eq "1" ] && [ `uci get adbyby.@adbyby[0].wan_mode 2>/dev/null` -eq "0" ] && /etc/init.d/adbyby stop >/dev/null 2>&1 + [ `uci get passwall.@global[0].enabled 2>/dev/null` -eq "1" ] && [ `uci get passwall.@global[0].proxy_mode 2>/dev/null|grep global` ] && /etc/init.d/koolproxy stop >/dev/null 2>&1 + local shadowsocksr_enabled=`uci get shadowsocksr.@global[0].global_server 2>/dev/null|grep nil` + local shadowsocksr_run_mode=`uci get shadowsocksr.@global[0].run_mode 2>/dev/null|grep all` + [ -z "$shadowsocksr_enabled" ] && [ ! -z "$shadowsocksr_run_mode" ] && /etc/init.d/shadowsocksr stop >/dev/null 2>&1 + sleep 60 && network_restart + elif [ "$retry_count" -eq "3" ] ;then + echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】正在尝试修复网络,当前第 3 次,备份设置项,并修改相关设置" >> ${logfile} + mkdir -p /usr/bin/serverchan/configbak + cp -p -f /etc/config/network /usr/bin/serverchan/configbak/network + cp -p -f /etc/config/dhcp /usr/bin/serverchan/configbak/dhcp + cp -p -f /etc/config/firewall /usr/bin/serverchan/configbak/firewall + cp -p -f /etc/firewall.user /usr/bin/serverchan/configbak/firewall.user + uci set network.wan.peerdns='0' + uci delete network.wan.dns + uci add_list network.wan.dns='223.5.5.5' + uci add_list network.wan.dns='119.29.29.29' + uci delete network.wan.mtu + uci commit network + uci set dhcp.@dnsmasq[0].port='53' + uci set dhcp.@dnsmasq[0].resolvfile='/tmp/resolv.conf.auto' + uci delete dhcp.@dnsmasq[0].server + uci delete dhcp.@dnsmasq[0].noresolv + uci commit dhcp + uci delete firewall.redirect + >/etc/firewall.user + uci commit firewall + sleep 60 && network_restart + elif [ "$retry_count" -eq "4" ] ;then + echo "$retry_count" > /usr/bin/serverchan/autoreboot_count + cat ${logfile} > /usr/bin/serverchan/errlog + sleep 2 && reboot && exit + elif [ "$retry_count" -eq "5" ] ;then + echo "$retry_count" > /usr/bin/serverchan/autoreboot_count + echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!!】修复失败,还原设置中,请自行检查网络设置" >> ${logfile} + cp -p -f /usr/bin/serverchan/configbak/network /etc/config/network + cp -p -f /usr/bin/serverchan/configbak/dhcp /etc/config/dhcp + cp -p -f /usr/bin/serverchan/configbak/firewall /etc/config/firewall + cp -p -f /usr/bin/serverchan/configbak/firewall.user /etc/firewall.user + cat ${logfile} > /usr/bin/serverchan/errlog + sleep 2 && reboot && exit + fi + fi + fi + elif [ -f /usr/bin/serverchan/autoreboot_count ]; then + network_err_time=`expr $network_err_time - 600` && sleep 60 + fi + enable_detection + sleep $sleeptime + fi + continue + done + rm -f /usr/bin/serverchan/autoreboot_count >/dev/null 2>&1 +} + +# 检测 ip 状况 +function ip_changes(){ + [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -eq "1" ] && local IPv4=`getip wanipv4` + [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -eq "2" ] && local IPv4=`getip hostipv4` + [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -eq "1" ] && local IPv6=`getip wanipv6` + [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -eq "2" ] && local IPv6=`getip hostipv6` + + if [ -f ${dir}ip ]; then + local last_IPv4=$(cat "${dir}ip"|grep IPv4|awk '{print $2}'|grep -v "^$"|sort -u|head -n1) + local last_IPv6=$(cat "${dir}ip"|grep IPv6|awk '{print $2}'|grep -v "^$"|sort -u|head -n1) + if [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -ne "0" ] && [ ! -z "$IPv4" ] && ( ! echo ${IPv4}|grep -w -q ${last_IPv4} ); then + echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}当前IP:${IPv4}" >> ${logfile} + echo IPv4 $IPv4 > ${dir}ip && echo -e IPv6 $last_IPv6 >> ${dir}ip + title="IP 地址变化" + content="${content}${str_splitline}${str_title_start} IP 地址变化${str_title_end}${str_linefeed}${str_tab}当前 IP:${IPv4}" + elif [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -ne "0" ] && [ -z "$IPv4" ]; then + echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】获取 IPv4 地址失败" >> ${logfile} + fi + + if [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -ne "0" ] && [ ! -z "$IPv6" ] && ( ! echo "$IPv6"|grep -w -q ${last_IPv6} ); then + echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}当前IPv6:${IPv6}" >> ${logfile} + echo IPv4 $IPv4 > ${dir}ip && echo -e IPv6 $IPv6 >> ${dir}ip + [ -z "$title" ] && title="IPv6 地址变化" + [ ! -z "$title" ] && title="IP 地址变化" + content="${content}${str_splitline}${str_title_start} IPv6 地址变化${str_title_end}${str_linefeed}${str_tab}当前 IPv6:${IPv6}" + elif [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -ne "0" ] && [ -z "$IPv6" ]; then + echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】获取 IPv6 地址失败" >> ${logfile} + fi + + else + echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}路由器已经重启!" >> ${logfile} + [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -ne "0" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 当前IP: ${IPv4}" >> ${logfile} + [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -ne "0" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 当前IPv6: ${IPv6}" >> ${logfile} + echo IPv4 $IPv4 > ${dir}ip && echo -e IPv6 $IPv6 >> ${dir}ip + title="路由器重新启动" + content="${content}${str_splitline}${str_title_start} 路由器重新启动${str_title_end}" + [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -ne "0" ] && content="${content}${str_linefeed}${str_tab}当前IP:${IPv4}" + [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -ne "0" ] && content="${content}${str_linefeed}${str_tab}当前IPv6:${IPv6}" + fi + + if [ ! -z "$content" ] ;then + [ -z "$ddns_enabled" ] && ddns_enabled=$(uci show ddns|grep "enabled"|grep "1") + [ -z "$ddns_enabled" ] && ddns_logrow=0 || ddns_logrow=$(echo "$ddns_enabled"|wc -l) + if [ $ddns_logrow -ge 1 ]; then + /etc/init.d/ddns restart >/dev/null 2>&1 + fi + [ -z "$zerotier_enabled" ] && zerotier_enabled=$(uci get zerotier.sample_config.enabled) + if [ ! -z "$zerotier_enabled" ] && [ $zerotier_enabled -eq "1" ] ; then + /etc/init.d/zerotier restart >/dev/null 2>&1 + fi + fi +} + +# 检测设备上线 +function up(){ + [ -f ${dir}ipAddress ] && ( cat ${dir}ipAddress|grep -q -w $1 ) && return + local ip_mac=`getmac $1` + local ip_name=`getname ${1} ${ip_mac}` + local ip_interface=`getinterface ${ip_mac}` + getping ${1} ${ip_mac} ${up_timeout} "1";local ping_online=$? + if [ "$ping_online" -eq "0" ]; then + LockFile lock + [ ! -z "$serverchan_blacklist" ] && local tmp_mac=`echo "${serverchan_blacklist}"|grep -w -i ${ip_mac}` + [ ! -z "$serverchan_whitelist" ] && local tmp_mac=`echo "${serverchan_whitelist}"|grep -w -i ${ip_mac}` + echo "{'ip': '${1}','mac': '${ip_mac}','name': '${ip_name}','uptime': '0秒','interface': '${ip_interface}','usage': '0 bytes'}" > ${dir}client/${1} + if [ ! -z "$tmp_mac" ] && ( cat ${dir}ipAddress|grep -q -w -i ${tmp_mac} ); then + usage down ${1} + echo "${1} ${ip_mac} ${ip_name} `date +%s` ${ip_interface}" >> ${dir}ipAddress + LockFile unlock && return + elif [ ! -z "$tmp_mac" ] && [ -f "${dir}tmp_downlist" ] && ( cat ${dir}tmp_downip|grep -q -w -i ${tmp_mac} ); then + local tmp_downip=`cat ${dir}tmp_downlist|grep -w -i ${tmp_mac}|awk '{print $1}'|grep -v "^$"|sort -u|head -n1` + usage down $tmp_downip + sed -i "/^${tmp_downip} /d" ${dir}tmp_downlist + LockFile unlock && return + fi + [ -f "${dir}tmp_downlist" ] && local tmp_downip=`cat ${dir}tmp_downlist|grep -w ${1}|grep -v "^$"|sort -u|head -n1` + if [ ! -z "$tmp_downip" ]; then + cat ${dir}tmp_downlist|grep -w ${1}|grep -v "^$"|sort -u|head -n1 >> ${dir}ipAddress + sed -i "/^${1} /d" ${dir}tmp_downlist + else + usage down $1 + echo "$1 ${ip_mac} ${ip_name} `date +%s` ${ip_interface}" >> ${dir}ipAddress + blackwhitelist ${ip_mac};local ip_blackwhite=$? + [ -f "${dir}send_enable.lock" ] || [ -z "$serverchan_up" ] || [ -z "$ip_blackwhite" ] && LockFile unlock && return + [ ! -z "$serverchan_up" ] && [ "$serverchan_up" -ne "1" ] && LockFile unlock && return + [ -z "$ip_blackwhite" ] || [ "$ip_blackwhite" -ne "0" ] && LockFile unlock && return + [ -f "${dir}title" ] && local title=`cat ${dir}title` + [ -f "${dir}content" ] && local content=`cat ${dir}content` + if [ -z "$title" ]; then + local title="$ip_name 连接了你的路由器" + local content="${str_splitline}${str_title_start} 新设备连接${str_title_end}${str_linefeed}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${1}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${ip_mac}${str_linefeed}${str_tab}网络接口:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_interface}" + elif ( echo ${title}|grep -q "连接了你的路由器" ); then + local title="${ip_name} ${title}" + local content="${str_splitline}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${1}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${ip_mac}${str_linefeed}${str_tab}网络接口:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_interface}" + else + local title="设备状态变化" + local content="${str_splitline}${str_title_start} 新设备连接${str_title_end}${str_linefeed}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${1}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${ip_mac}${str_linefeed}${str_tab}网络接口:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_interface}" + fi + echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}新设备 ${ip_name} ${1} 连接了">> ${logfile} + #[ ! -z "$serverchan_blacklist" ] && local title="你偷偷关注的设备上线了" + [ ! -z "$title" ] && echo "$title" >${dir}title + [ ! -z "$content" ] && echo -n "$content" >>${dir}content + fi + fi + LockFile unlock +} + +# 检测设备离线 +function down(){ + local ip_mac=`getmac $1` + local ip_name=`getname ${1} ${ip_mac}` + local ip_interface=`getinterface ${ip_mac}` + getping ${1} ${ip_mac} ${down_timeout} ${timeout_retry_count};local ping_online=$? + if [ "$ping_online" -eq "1" ]; then + LockFile lock + [ ! -f "${dir}send_enable.lock" ] && cat ${dir}ipAddress|grep -w ${1}|grep -v "^$"|sort -u|head -n1 >> ${dir}tmp_downlist + sed -i "/^${1} /d" ${dir}ipAddress + rm -f ${dir}client/${1} >/dev/null 2>&1 + LockFile unlock + else + local tmp_name=`cat ${dir}ipAddress|grep -w ${1}|awk '{print $3}'|grep -v "^$"|sort -u|head -n1` + if [ ${ip_name} != ${tmp_name} ]; then + LockFile lock + local tmp_str=$(echo "$1 ${ip_mac} ${ip_name} `cat ${dir}ipAddress|grep -w ${1}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` ${ip_interface}") + sed -i "/^${1} /d" ${dir}ipAddress + echo "$tmp_str" >> ${dir}ipAddress + LockFile unlock + fi + local time_up=`cat ${dir}ipAddress|grep -w ${1}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` + local time1=`date +%s` + local time1=$(time_for_humans `expr ${time1} - ${time_up}`) + echo "{'ip': '${1}','mac': '${ip_mac}','name': '${ip_name}','uptime': '${time1}','interface': '${ip_interface}','usage': '`usage get $ip_mac`'}" > ${dir}client/${1} + fi +} + +# 设备离线通知 +function down_send(){ + [ ! -f "${dir}tmp_downlist" ] && return + local IPLIST=`cat ${dir}tmp_downlist|awk '{print $1}'` + for ip in $IPLIST; do + local ip_mac=`getmac ${ip}` + blackwhitelist ${ip_mac};local ip_blackwhite=$? + [ -z "$serverchan_down" ] || [ -z "$ip_blackwhite" ] && continue + [ ! -z "$serverchan_down" ] && [ "$serverchan_down" -ne "1" ] && continue + [ -z "$ip_blackwhite" ] || [ "$ip_blackwhite" -ne "0" ] && continue + [ ! -z "$serverchan_blacklist" ] && local tmp_mac=`echo "${serverchan_blacklist}"|grep -w -i ${ip_mac}` + [ ! -z "$serverchan_whitelist" ] && local tmp_mac=`echo "${serverchan_whitelist}"|grep -w -i ${ip_mac}` + [ ! -z "$tmp_mac" ] && ( cat ${dir}ipAddress|grep -q -w -i ${tmp_mac} ) && continue + local ip_name=`getname ${ip} ${ip_mac}` + local time_up=`cat ${dir}tmp_downlist|grep -w ${ip}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` + local ip_total=`usage get $ip_mac` && [ ! -z "$ip_total" ] && local ip_total="${str_linefeed}${str_tab}总计流量: ${str_space}${str_space}${str_space}${str_space}${ip_total}" + local time1=`date +%s` + local time1=$(time_for_humans `expr ${time1} - ${time_up}`) + if [ -z "$title" ]; then + title="${ip_name} 断开连接" + content="${content}${str_splitline}${str_title_start} 设备断开连接${str_title_end}${str_linefeed}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${ip}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${ip_mac}$ip_total${str_linefeed}${str_tab}在线时间: ${str_space}${str_space}${str_space}${str_space}${time1}" + elif ( echo "$title"|grep -q "断开连接" ); then + title="${ip_name} ${title}" + content="${content}${str_splitline}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${ip}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${ip_mac}$ip_total${str_linefeed}${str_tab}在线时间: ${str_space}${str_space}${str_space}${str_space}${time1}" + else + title="设备状态变化" + content="${content}${str_splitline}${str_title_start} 设备断开连接${str_title_end}${str_linefeed}${str_tab}客户端名:${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}${str_linefeed}${str_tab}客户端IP: ${str_space}${str_space}${str_space}${str_space}${ip}${str_linefeed}${str_tab}客户端MAC:${str_space}${str_space}${str_space}${str_space}${ip_mac}$ip_total${str_linefeed}${str_tab}在线时间: ${str_space}${str_space}${str_space}${str_space}${time1}" + fi + echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}设备 ${ip_name} ${ip} 断开连接 " >> ${logfile} + done + rm -f ${dir}tmp_downlist >/dev/null 2>&1 +} + +# 当前设备列表 +function current_device(){ + ( echo "$lite_enable"|grep -q "content" ) || ( echo "$lite_enable"|grep -q "device" ) && return + [ -f ${dir}ipAddress ] && local logrow=$(grep -c "" ${dir}ipAddress) || local logrow="0";[ $logrow -eq "0" ] && return + [ -f ${dir}usage.db ] && local ip_total_db="总计流量${str_space}${str_space}${str_space}${str_space}" + content="${content}${str_splitline}${str_title_start} 现有在线设备 ${logrow} 台,具体如下${str_title_end}${str_linefeed}${str_tab}IP 地址${str_space}${str_space}${str_space}${str_space}${str_space}${str_space}${str_space}${str_space}${str_space}${ip_total_db}客户端名" + local IPLIST=`cat ${dir}ipAddress|awk '{print $1}'` + for ip in $IPLIST; do + local ip_mac=`getmac ${ip}` + local ip_total=`usage get ${ip_mac}` + local ip_name=`getname ${ip} ${ip_mac}` + local ip_name=`cut_str $ip_name 15` + if [ "${#ip}" -lt "15" ]; then + local n=`expr 15 - ${#ip}` + for i in `seq 1 $n`; do + local ip="${ip}${str_space}" + done + unset i n + fi + if [ ! -z "$ip_total" ]; then + local n=`expr 11 - ${#ip_total}` + for i in `seq 1 $n`; do + local ip_total="${ip_total}${str_space}" + done + fi + content="${content}${str_linefeed}${str_tab}${ip}${ip_total}${ip_name}" + unset i n ip_total ip_mac ip_name + done +} + +# 检测 cpu 状态 +function cpu_load(){ + if [ ! -z "$temperature_enable" ] && [ "$temperature_enable" -eq "1" ] && [ ! -z "$temperature" ]; then + [ -z "$temperature_time" ] && temperature_time=`date +%s` + local cpu_wendu=`soc_temp`; + [ -z "$cpu_wendu" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】无法读取设备温度,请检查命令" >> ${logfile} + + if [ `expr $cpu_wendu \> $temperature` -eq "1" ]; then + echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!警报!!】 CPU 温度过高: ${cpu_wendu}" >> ${logfile} + else + temperature_time=`date +%s` + fi + + if [ "$((`date +%s`-$temperature_time))" -ge "300" ] && [ -z "$temperaturecd_time" ]; then + title="CPU 温度过高!" + temperaturecd_time=`date +%s` + echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text} CPU 温 度过高: ${cpu_wendu}" >> ${logfile} + content="${content}${str_splitline}${str_title_start} CPU 温度过高${str_title_end}${str_linefeed}${str_tab}CPU 温度已连续五分钟超过预设${str_linefeed}${str_tab}接下来一小 时不再提示${str_linefeed}${str_tab}当前温度:${cpu_wendu}℃" + elif [ ! -z "$temperaturecd_time" ] && [ "$((`date +%s`-$temperaturecd_time))" -ge "3300" ] ;then + unset temperaturecd_time + fi + fi + + if [ ! -z "$cpuload_enable" ] && [ "$cpuload_enable" -eq "1" ] && [ ! -z "$cpuload" ]; then + [ -z "$cpuload_time" ] && cpuload_time=`date +%s` + local cpu_fuzai=`cat /proc/loadavg|awk '{print $1}'` 2>/dev/null + [ -z "$cpu_fuzai" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】无法读取设备负载,请检查命令" >> ${logfile} + + if [ `expr $cpu_fuzai \> $cpuload` -eq "1" ]; then + echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!警报!!】 CPU 负载过高: ${cpu_fuzai}" >> ${logfile} + cputop log + else + cpuload_time=`date +%s` + fi + + if [ "$((`date +%s`-$cpuload_time))" -ge "300" ] && [ -z "$cpucd_time" ]; then + unset getlogtop + if [ ! -z "$title" ] && ( echo "$title"|grep -q "过高" ); then + title="设备报警!" + else + title="CPU 负载过高!" + fi + cpucd_time=`date +%s` + echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text} CPU 负 载过高: ${cpu_fuzai}" >> ${logfile} + content="${content}${str_splitline}${str_title_start} CPU 负载过高${str_title_end}${str_linefeed}${str_tab}CPU 负载已连续五分钟超过预设${str_linefeed}${str_tab}接下来一小 时不再提示${str_linefeed}${str_tab}当前负载:${cpu_fuzai}" + cputop + elif [ ! -z "$cpucd_time" ] && [ "$((`date +%s`-$cpucd_time))" -ge "3300" ] ;then + unset cpucd_time + fi + fi +} + +function cputop(){ + [ -z "$1" ] && content="${content}${str_splitline}${str_title_start} 当前 CPU 占用前三的进程${str_title_end}" + local gettop=`top -bn 1|grep -v "top -bn 1"` + for i in `seq 5 7`; do + local top_name=`echo "${gettop}"|awk 'NR=='${i}|awk '{print ($8 ~ /\/bin\/sh|\/bin\/bash/) ? $9 : $8}'` + local top_load=`echo "${gettop}"|awk 'NR=='${i}|awk '{print $7}'` + local temp_top="${top_name} ${top_load}" + [ ! -z "$1" ] && local logtop="$logtop $temp_top" + [ -z "$1" ] && content="${content}${str_linefeed}${str_tab}${temp_top}" + done + unset i + [ ! -z "$1" ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!警报!!】 CPU 占用前三: ${logtop}" >> ${logfile} +} + +# 生成日志监控文件,避免后台影响 wait 语句 +function get_syslog(){ + kill -9 `pgrep -f "logread -f -p notice"` 2>/dev/null + [ -z "$web_logged" ] && [ -z "$ssh_logged" ] && [ -z "$web_login_failed" ] && [ -z "$ssh_login_failed" ] && return + rm -f ${dir}login_monitor >/dev/null 2>&1 + +cat>${dir}get_syslog<> ${dir}login_monitor & +EOF + chmod 0755 ${dir}get_syslog && ${dir}get_syslog + rm -f ${dir}get_syslog >/dev/null 2>&1 +} + +# 登陆提醒通知 +function login_send(){ + [ -z "$web_logged" ] && [ -z "$ssh_logged" ] && [ -z "$web_login_failed" ] && [ -z "$ssh_login_failed" ] && return + [ ! -f ${dir}login_monitor ] && return + cat ${dir}login_monitor|grep -i "accepted login"|awk '{print $4" "$NF}' >> ${dir}web_login + cat ${dir}login_monitor|grep -i "Password auth succeeded\|Pubkey auth succeeded"|grep -Eo "[0-9]{2}:[0-9]{2}:[0-9]{2}.*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"|awk '{print $1" "$NF" "$5}' >> ${dir}ssh_login + cat ${dir}login_monitor|grep -i "failed login"|grep -Eo "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" >> ${dir}web_failed + cat ${dir}login_monitor|grep -i "Exit before auth from"|grep -Eo "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" >> ${dir}ssh_failed + echo "" > ${dir}login_monitor + add_ip_black + + local login_ip_list=`cat ${dir}web_login|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` + for login_ip in $login_ip_list; do + [ -z "$login_ip" ] && continue + echo "$ip_white_list"|grep -w -q "$login_ip" && continue + local web_login_time=`cat ${dir}web_login|grep -w ${login_ip}|awk '{print $1}'|grep -v "^$"|sort -u|head -n1` + local web_login_mode=`cat ${dir}web_login|grep -w ${login_ip}|awk '{print $3}'|grep -v "^$"|sort -u|head -n1` + if [ ! -z "$web_logged" ] && [ "$web_logged" -eq "1" ]; then + if [ -z "$title" ]; then + title="${login_ip} 通过 web 登陆了路由器" + content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}时间:${str_space}${str_space}${str_space}${str_space}${str_space}${web_login_time}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}${content_mode}" + elif ( echo "$title"|grep -q "登陆了路由器" ); then + title="${login_ip} ${title}" + content="${content}${str_splitline}${str_tab}时间:${str_space}${str_space}${str_space}${str_space}${str_space}${web_login_time}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}${content_mode}" + else + title="设备状态变化" + content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}时间:${str_space}${str_space}${str_space}${str_space}${str_space}${web_login_time}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}${content_mode}" + fi + fi + echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}设备 ${login_ip} 通过 web ${web_login_mode} 登陆了路由器 " >> ${logfile} + done + echo "" > ${dir}web_login + unset login_ip login_ip_list + + local login_ip_list=`cat ${dir}ssh_login|awk '{print $2}'|grep -v "^$"|sort -u|head -n1` + for login_ip in $login_ip_list; do + [ -z "$login_ip" ] && continue + echo "$ip_white_list"|grep -w -q "$login_ip" && continue + local ssh_login_time=`cat ${dir}ssh_login|grep -w ${login_ip}|awk '{print $1}'|grep -v "^$"|sort -u|head -n1` + local ssh_login_mode=`cat ${dir}ssh_login|grep -w ${login_ip}|awk '{print $3}'|grep -v "^$"|sort -u|head -n1` + [ ! -z "$ssh_login_mode" ] && local content_mode="${str_linefeed}${str_tab}登录方式: ${str_space}${str_space}${str_space}${str_space}${ssh_login_mode}" + if [ ! -z "$ssh_logged" ] && [ "$ssh_logged" -eq "1" ]; then + if [ -z "$title" ]; then + title="${login_ip} 通过 ssh 登陆了路由器" + content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}时间:${str_space}${str_space}${str_space}${str_space}${str_space}${ssh_login_time}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}${content_mode}" + elif ( echo "$title"|grep -q "登陆了路由器" ); then + title="${login_ip} ${title}" + content="${content}${str_splitline}${str_tab}时间:${str_space}${str_space}${str_space}${str_space}${str_space}${ssh_login_time}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}${content_mode}" + else + title="设备状态变化" + content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}时间:${str_space}${str_space}${str_space}${str_space}${str_space}${ssh_login_time}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}${content_mode}" + fi + fi + echo "`date "+%Y-%m-%d %H:%M:%S"` 【info】设备 ${login_ip} 通过 ssh ${ssh_login_mode} 登陆了路由器 " >> ${logfile} + done + echo "" > ${dir}ssh_login + unset login_ip login_ip_list + + local login_ip_list=`cat ${dir}web_failed|awk '{print $1}'|grep -v "^$"|sort -u|head -n1` + for login_ip in $login_ip_list; do + [ -z "$login_ip" ] && continue + echo "$ip_white_list"|grep -w -q "$login_ip" && continue + local web_login_sum=`cat ${dir}web_failed|grep -w "${login_ip}"|wc -l` + if [ "$web_login_sum" -ge "$login_max_num" ] ;then + if [ ! -z "$web_login_failed" ] && [ "$web_login_failed" -eq "1" ]; then + if [ -z "$title" ]; then + title="${login_ip} 通过 web 频繁尝试登陆" + content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}" + elif ( echo "$title"|grep -q "频繁尝试登陆" ); then + title="${login_ip} ${title}" + content="${content}${str_splitline}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}" + else + title="设备状态变化" + content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}" + fi + fi + sed -i "/^${login_ip}$/d" ${dir}web_failed + echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】设备 ${login_ip} 通过 web 频繁尝试登陆" >> ${logfile} + add_ip_black $login_ip + fi + done + unset login_ip + + local login_ip_list=`cat ${dir}ssh_failed|awk '{print $1}'|grep -v "^$"|sort -u|head -n1` + for login_ip in $login_ip_list; do + [ -z "$login_ip" ] && continue + echo "$ip_white_list"|grep -w -q "$login_ip" && continue + local ssh_login_sum=`cat ${dir}ssh_failed|grep -w "${login_ip}"|wc -l` + if [ "$ssh_login_sum" -ge "$login_max_num" ] ;then + if [ ! -z "$ssh_login_failed" ] && [ "$ssh_login_failed" -eq "1" ]; then + if [ -z "$title" ]; then + title="${login_ip} 通过 ssh 频繁尝试登陆" + content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}" + elif ( echo "$title"|grep -q "频繁尝试登陆" ); then + title="${login_ip} ${title}" + content="${content}${str_splitline}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}" + else + title="设备状态变化" + content="${content}${str_splitline}${str_title_start} 登陆信息${str_title_end}${str_linefeed}${str_tab}设备 IP: ${str_space}${str_space}${str_space}${str_space}${login_ip}" + fi + fi + sed -i "/^${login_ip}$/d" ${dir}ssh_failed + echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】设备 ${login_ip} 通过 ssh 频繁尝试登陆" >> ${logfile} + add_ip_black $login_ip + fi + done + unset login_ip + +} + +# 添加黑名单 +function add_ip_black(){ + [ ! -f "${ip_blacklist_path}" ] && touch ${ip_blacklist_path} + local logrow=$(grep -c "" ${ip_blacklist_path}) + [ ! -z "$web_login_black" ] && [ "$web_login_black" -eq "0" ] || [ -z "$web_login_black" ] && logrow=0 + [ ! -z "$1" ] && logrow=logrow+1 + ipset flush ip_blacklist >/dev/null 2>&1 + + if [ $logrow -le "0" ]; then + iptables -D INPUT -m set --match-set ip_blacklist src -j DROP >/dev/null 2>&1 + ipset destroy ip_blacklist >/dev/null 2>&1 + return + fi + + ipset list ip_blacklist >/dev/null 2>&1 || ipset create ip_blacklist hash:ip timeout ${ip_black_timeout} >/dev/null 2>&1 + iptables -C INPUT -m set --match-set ip_blacklist src -j DROP >/dev/null 2>&1 || iptables -I INPUT -m set --match-set ip_blacklist src -j DROP >/dev/null 2>&1 + echo "$1" >> ${ip_blacklist_path} + for ip_black in `cat ${ip_blacklist_path}`; do + ip_black=`echo "$ip_black"|grep -Eo "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"` + ipset -! add ip_blacklist $ip_black >/dev/null 2>&1 + done + ipset list ip_blacklist|grep -Eo "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" > ${ip_blacklist_path} +} + + +# 发送定时数据 +function send(){ + echo "`date "+%Y-%m-%d %H:%M:%S"` 【定时数据】创建定时任务" >> ${logfile} + serverchan_disturb;local send_disturb=$? + get_config "send_title" "router_status" "router_temp" "router_wan" "client_list" + + [ -z "$send_title" ] && local send_title="路由状态:" + [ ! -z "$1" ] && local send_title="发送测试:" && local send_content="${str_splitline}${str_title_start}内容1${str_title_end}${str_linefeed}${str_tab}设备1${str_linefeed}${str_tab}设备2${str_splitline}${str_title_start}内容2${str_title_end}${str_linefeed}${str_tab}设备3${str_linefeed}${str_tab}设备4" + [ -z "$1" ] && [ ! -z "$client_list" ] && [ "$client_list" -eq "1" ] && > ${dir}send_enable.lock && serverchan_first & + + if [ -z "$1" ] && [ ! -z "$router_status" ] && [ "$router_status" -eq "1" ]; then + local systemload=`cat /proc/loadavg|awk '{print $1" "$2" "$3}'` + local cpuload=`getcpu` + local ramload=`free -m|sed -n '2p'|awk '{printf "%.2f%%\n",($3/$2)*100}'` + local Qwai=`curl -o /dev/null --connect-timeout 5 -s -w %{http_code} www.google.com` + if [[ "$Qwai" -eq "200" ]] || [[ "$Qwai" -eq "301" ]] || [[ "$Qwai" -eq "302" ]]; then + local Qwai_status="已连通!" + else + local Qwai_status="已断开!" + fi + local systemstatustime=`cat /proc/uptime|awk -F. '{run_days=$1 / 86400;run_hour=($1 % 86400)/3600;run_minute=($1 % 3600)/60;run_second=$1 % 60;printf("运行时间:%d天%d时%d分%d秒",run_days,run_hour,run_minute,run_second)}'`;unset run_days run_hour run_minute run_second + local send_content="${send_content}${str_splitline}${str_title_start} 系统运行状态${str_title_end}" + local send_content="${send_content}${str_linefeed}${str_tab}平均负载:${systemload}" + local send_content="${send_content}${str_linefeed}${str_tab}CPU占用:${cpuload}" + local send_content="${send_content}${str_linefeed}${str_tab}内存占用:${ramload}" + local send_content="${send_content}${str_linefeed}${str_tab}全球互联:${Qwai_status}" + local send_content="${send_content}${str_linefeed}${str_tab}${systemstatustime}" + fi + + if [ -z "$1" ] && [ ! -z "$router_temp" ] && [ "$router_temp" -eq "1" ]; then + local cputemp=`soc_temp` + [ ! -z "$cputemp" ] && local send_content="${send_content}${str_splitline}${str_title_start} 设备温度${str_title_end}${str_linefeed}${str_tab}CPU:${cputemp}℃" + [ -z "$cputemp" ] && local send_content="${send_content}${str_splitline}${str_title_start} 设备温度${str_title_end}${str_linefeed}${str_tab}无法获取设备温度" + fi + + if [ -z "$1" ] && [ ! -z "$router_wan" ] && [ "$router_wan" -eq "1" ]; then + local send_wanIP=`getip wanipv4`;local send_hostIP=`getip hostipv4` + local send_content="${send_content}${str_splitline}${str_title_start} WAN 口信息${str_title_end}${str_linefeed}${str_tab}接口 IPv4:${send_wanIP}" + local send_content="${send_content}${str_linefeed}${str_tab}外网 IPv4:${send_hostIP}" + if [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -ne "0" ]; then + local send_wanIPv6=`getip wanipv6`;local send_hostIPv6=`getip hostipv6` + local send_content="${send_content}${str_linefeed}${str_tab}接口 IPv6:${send_wanIPv6}" + local send_content="${send_content}${str_linefeed}${str_tab}外网 IPv6:${send_hostIPv6}" + fi + ( ! echo "$send_wanIP"|grep -q -w ${send_hostIP} ) && local send_content="${send_content}${str_linefeed}${str_tab}外网 IP 与接口 IP 不一致,你的 IP 可能不是公网 IP" + local interfaceuptime=`getinterfaceuptime` + [ ! -z "$interfaceuptime" ] && local wanstatustime=`getinterfaceuptime|awk -F. '{run_days=$1 / 86400;run_hour=($1 % 86400)/3600;run_minute=($1 % 3600)/60;run_second=$1 % 60;printf("在线时间:%d天%d时%d分%d秒",run_days,run_hour,run_minute,run_second)}'` && unset run_days run_hour run_minute run_second + local send_content="${send_content}${str_linefeed}${str_tab}${wanstatustime}" + fi + + if [ -z "$1" ] && [ ! -z "$client_list" ] && [ "$client_list" -eq "1" ]; then + wait + local IPLIST=`cat ${dir}ipAddress 2>/dev/null|awk '{print $1}'` + [ -f ${dir}ipAddress ] && local logrow=$(grep -c "" ${dir}ipAddress) || local logrow="0" + [ "$logrow" -eq "0" ] && local send_content="${send_content}${str_splitline}${str_title_start} 当前无在线设备${str_title_end}" || local send_content="${send_content}${str_splitline}${str_title_start} 现有在线设备 ${logrow} 台${str_title_end}" + for ip in $IPLIST; do + local time_up=`cat ${dir}ipAddress|grep -w ${ip}|awk '{print $4}'|grep -v "^$"|sort -u|head -n1` + local time1=`date +%s` + local time1=$(time_for_humans `expr ${time1} - ${time_up}`) + local ip_mac=`getmac ${ip}` + local ip_name=`getname ${ip} ${ip_mac}` + local ip_total=`usage get ${ip_mac}`;[ ! -z "$ip_total" ] && local ip_total="总计流量:${ip_total} " + local ip_name=`cut_str $ip_name 18` + local send_content="${send_content}${str_linefeed}${str_tab}【${ip_name}】 ${ip}${str_linefeed}${str_tab}${ip_total}在线 ${time1}" + unset ip_total time_down time_up time1 ip_mac ip_name + done + fi + [ ! -z "$device_name" ] && local send_title="【$device_name】${send_title}" + [ -z "$send_content" ] && local send_content="${str_splitline}${str_title_start} 我遇到了一个难题${str_title_end}${str_linefeed}${str_tab}定时发送选项错误,你没有选择需要发送的项目,该怎 么办呢${str_splitline}" + [ "$send_disturb" -eq "0" ] && diy_send "${send_title}" "${send_content}" "${jsonpath}" >/dev/null 2>&1 + [ $? -eq 1 ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】定时推送失败,请检查网络或设置信息" >> ${logfile} || echo "`date "+%Y-%m-%d %H:%M:%S"` ${disturb_text}定时推送任务完成" >> ${logfile} + deltemp +} + +# 初始化 +read_config +deltemp +serverchan_cron + +# 限制并发进程 +[ -z "$thread_num" ] || [ "$thread_num" -eq "0" ] && thread_num=5 +[ -e ${dir}fd1 ] || mkfifo ${dir}fd1 +exec 5<>${dir}fd1 +rm -f ${dir}fd1 >/dev/null 2>&1 +for i in `seq 1 $thread_num`; do + echo >&5 +done +unset i + +# 启动参数 +if [ "$1" ] ;then + [ $1 == "send" ] && send + [ $1 == "soc" ] && echo `soc_temp` > ${dir}soc_tmp + [ $1 == "test" ] && send test + exit +fi + +# 载入在线设备 +serverchan_init;[ $? -eq 1 ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】读取设置出错,请检查设置项 " >> ${logfile} && exit +echo "`date "+%Y-%m-%d %H:%M:%S"` 【初始化】载入在线设备" >> ${logfile} +> ${dir}send_enable.lock && serverchan_first && deltemp +echo "`date "+%Y-%m-%d %H:%M:%S"` 【初始化】初始化完成" >> ${logfile} + +# 循环 +while [ "$serverchan_enable" -eq "1" ]; do + deltemp + usage update + serverchan_disturb;disturb=$? + + [ -f ${dir}ipAddress ] && ipAddress_logrow=$(grep -c "" ${dir}ipAddress) || ipAddress_logrow="0"; + if [ $ipAddress_logrow -ne "0" ]; then + online_list=`cat ${dir}ipAddress|awk '{print $2}'|grep -v "^$"|sort -u` + for online_mac in $online_list; do + [ ! -z "$online_mac" ] && mac_online_status="`echo "$mark_mac_list"|grep -i $online_mac|grep -v "^$"|sort -u|head -n1`${mac_online_status}" + done + fi + + if [ "$serverchan_ipv4" -ne "0" ] || [ "$serverchan_ipv6" -ne "0" ]; then + rand_geturl + ip_changes + fi + + # 设备列表 + if [ ! -f "${dir}send_enable.lock" ]; then + [ ! -z "$title" ] && echo "$title" > ${dir}title + [ ! -z "$content" ] && echo "$content" > ${dir}content + serverchan_first + [ -f "${dir}title" ] && title=`cat ${dir}title` && rm -f ${dir}title >/dev/null 2>&1 + [ -f "${dir}content" ] && content=`cat ${dir}content` && rm -f ${dir}content >/dev/null 2>&1 + fi + + # 离线缓存区推送 + [ ! -f "${dir}send_enable.lock" ] && down_send + + # 当前设备列表 + [ ! -z "$content" ] && [ ! -f "${dir}send_enable.lock" ] && current_device + + # 无人值守任务 + [ ! -f "${dir}send_enable.lock" ] && unattended + + # CPU 检测 + [ ! -f "${dir}send_enable.lock" ] && cpu_load + + # 异常流量检测 + [ ! -f "${dir}send_enable.lock" ] && get_client_usage + + # 登陆提醒通知 + [ ! -f "${dir}send_enable.lock" ] && login_send + + if [ ! -f "${dir}send_enable.lock" ] && [ ! -z "$title" ] && [ ! -z "$content" ]; then + [ ! -z "$device_name" ] && title="【$device_name】$title" + ( echo "$lite_enable"|grep -q "content" ) && content="$title" + [ "$disturb" -eq "0" ] && diy_send "${title}" "${content}" "${jsonpath}" >/dev/null 2>&1 + [ $? -eq 1 ] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】推送失败,请检查网络或设置信息 " >> ${logfile} + fi + + while [ -f "${dir}send_enable.lock" ]; do + sleep $sleeptime + done + sleep $sleeptime +done diff --git a/luci-app-serverchan/root/usr/share/rpcd/acl.d/luci-app-serverchan.json b/luci-app-serverchan/root/usr/share/rpcd/acl.d/luci-app-serverchan.json index 8f1e66f1..200ccd56 100644 --- a/luci-app-serverchan/root/usr/share/rpcd/acl.d/luci-app-serverchan.json +++ b/luci-app-serverchan/root/usr/share/rpcd/acl.d/luci-app-serverchan.json @@ -1,11 +1,11 @@ -{ - "luci-app-serverchan": { - "description": "Grant UCI access for luci-app-serverchan", - "read": { - "uci": [ "serverchan" ] - }, - "write": { - "uci": [ "serverchan" ] - } - } -} +{ + "luci-app-serverchan": { + "description": "Grant UCI access for luci-app-serverchan", + "read": { + "uci": [ "serverchan" ] + }, + "write": { + "uci": [ "serverchan" ] + } + } +}