From 9daea4eb2f76c2f7cf510dbf7c0cee5a0a842423 Mon Sep 17 00:00:00 2001 From: CN_SZTL Date: Wed, 15 Jan 2020 01:15:02 +0800 Subject: [PATCH] luci-app-serverchan: sync with upstream source --- package/ctcgfw/luci-app-serverchan/Makefile | 11 +- .../luasrc/model/cbi/serverchan.lua | 71 ++- .../root/usr/bin/serverchan/serverchan | 469 ++++++++++++------ .../usr/bin/serverchan/wrtbwmon/readDB.awk | 157 ++++++ .../root/usr/bin/serverchan/wrtbwmon/wrtbwmon | 302 +++++++++++ 5 files changed, 836 insertions(+), 174 deletions(-) create mode 100755 package/ctcgfw/luci-app-serverchan/root/usr/bin/serverchan/wrtbwmon/readDB.awk create mode 100755 package/ctcgfw/luci-app-serverchan/root/usr/bin/serverchan/wrtbwmon/wrtbwmon diff --git a/package/ctcgfw/luci-app-serverchan/Makefile b/package/ctcgfw/luci-app-serverchan/Makefile index e80a15706e..4f411d5754 100644 --- a/package/ctcgfw/luci-app-serverchan/Makefile +++ b/package/ctcgfw/luci-app-serverchan/Makefile @@ -9,18 +9,9 @@ LUCI_TITLE:=LuCI support for serverchan LUCI_DEPENDS:=+iputils-arping +curl LUCI_PKGARCH:=all PKG_NAME:=luci-app-serverchan -PKG_VERSION:=1.21 +PKG_VERSION:=1.26 PKG_RELEASE:=42 include $(TOPDIR)/feeds/luci/luci.mk -define Package/$(PKG_NAME)/postinst -#!/bin/sh -chmod 0755 /etc/init.d/serverchan -chmod 0755 /usr/bin/serverchan/serverchan -/etc/init.d/serverchan enable -exit 0 -endef - # call BuildPackage - OpenWrt buildroot signature - diff --git a/package/ctcgfw/luci-app-serverchan/luasrc/model/cbi/serverchan.lua b/package/ctcgfw/luci-app-serverchan/luasrc/model/cbi/serverchan.lua index b7cd890751..629a9d3463 100644 --- a/package/ctcgfw/luci-app-serverchan/luasrc/model/cbi/serverchan.lua +++ b/package/ctcgfw/luci-app-serverchan/luasrc/model/cbi/serverchan.lua @@ -5,10 +5,15 @@ 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」,是一款从服务器推送报警信息和日志到微信的工具。")) +m=Map("serverchan",translate("ServerChan"), +translate("「Server酱」,英文名「ServerChan」,是一款从服务器推送报警信息和日志到微信的工具。

如果你在使用中遇到问题,请到这里提交:") +.. [[]] +.. translate("github 项目地址") +.. [[]] +) + m:section(SimpleSection).template = "serverchan/serverchan_status" - s=m:section(NamedSection,"serverchan","serverchan",translate("Server酱设置")) s:tab("tab_basic", translate("基本设置")) s:tab("tab_basic2", translate("设备状态")) @@ -51,9 +56,56 @@ end e.write=function(e,e,e) end -a=s:taboption("tab_basic2", Flag,"serverchan_ip",translate("WAN ip 变化通知")) -a.default=0 -a.rmempty=true +a=s:taboption("tab_basic2", ListValue,"serverchan_ipv4",translate("ipv4 变动通知")) +a.default="disable" +a:value("0",translate("关闭")) +a:value("1",translate("通过接口获取")) +a:value("2",translate("通过URL获取")) +a = s:taboption("tab_basic2", ListValue, "ipv4_interface", translate("接口名称")) +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("tab_basic2", Value, "ipv4_URL", "URL 地址") +a.rmempty = true +a.default = "members.3322.org/dyndns/getip" +a:depends({serverchan_ipv4="2"}) +a.description = translate("
会因服务器稳定性/连接频繁等原因导致获取失败,一般不推荐") + +a=s:taboption("tab_basic2", ListValue,"serverchan_ipv6",translate("ipv6 变动通知")) +a.default="disable" +a:value("0",translate("关闭")) +a:value("1",translate("通过接口获取")) +a:value("2",translate("通过URL获取")) +a = s:taboption("tab_basic2", ListValue, "ipv6_interface", translate("接口名称")) +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("tab_basic2", Value, "ipv6_URL", "URL 地址") +a.rmempty = true +a.default = "v6.ip.zxinc.org/getip" +a:depends({serverchan_ipv6="2"}) +a.description = translate("
会因服务器稳定性/连接频繁等原因导致获取失败,一般不推荐") + a=s:taboption("tab_basic2", Flag,"serverchan_up",translate("设备上线通知")) a.default=0 a.rmempty=true @@ -134,8 +186,8 @@ end sheep=s:taboption("tab_basic4", ListValue,"serverchan_sheep",translate("免打扰时段设置"),translate("在指定整点时间段内,暂停推送消息
免打扰时间中,定时推送也会被阻止。")) sheep:value("0",translate("关闭")) -sheep:value("1",translate("模式一:脚本挂起,不检测设备")) ---[[sheep:value("2",translate("模式二:脚本继续运行但不发送消息"))--]] +sheep:value("1",translate("模式一:脚本挂起,延迟发送")) +sheep:value("2",translate("模式二:静默模式,不发送任何信息")) sheep.rmempty = true sheep.optional = true sheep=s:taboption("tab_basic4", ListValue,"starttime",translate("免打扰开始时间")) @@ -186,10 +238,9 @@ for _, iface in ipairs(ifaces) do n:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface)) end end - - local apply = luci.http.formvalue("cbi.apply") if apply then io.popen("/etc/init.d/serverchan start") end -return m \ No newline at end of file + +return m diff --git a/package/ctcgfw/luci-app-serverchan/root/usr/bin/serverchan/serverchan b/package/ctcgfw/luci-app-serverchan/root/usr/bin/serverchan/serverchan index 6c865f0bfb..5ddda5481d 100755 --- a/package/ctcgfw/luci-app-serverchan/root/usr/bin/serverchan/serverchan +++ b/package/ctcgfw/luci-app-serverchan/root/usr/bin/serverchan/serverchan @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # 读取设置文件 function get_config(){ @@ -9,18 +9,38 @@ function get_config(){ } function read_config(){ + debuglevel=`get_config debuglevel` + if [ -z "$debuglevel" ] ; then logfile="/dev/null";else logfile="/tmp/serverchan/server_chan.log";fi serverchan_enable=`get_config serverchan_enable` + if [ -z "$serverchan_enable" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取程序开关 " >> ${logfile};fi + #if [ -z "$serverchan_enable" ] || [ "$serverchan_enable" -eq "0" ] ; then exit;fi serverchan_sckey=`get_config sckey` - serverchan_ip=`get_config serverchan_ip` + if [ -z "$serverchan_sckey" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 SCKEY" >> ${logfile};fi + if [ -z "$serverchan_sckey" ] && [ "${#serverchan_sckey}" -lt "50" ] ; then echo "`date "+%H:%M:%S"` 【!!!】请填入正确的 SCKEY " >> ${logfile};fi + if [ -z "$serverchan_sckey" ] && [ "${#serverchan_sckey}" -lt "50" ] ; then exit;fi + serverchan_ipv4=`get_config serverchan_ipv4` + if [ -z "$serverchan_ipv4" ] || [ "$serverchan_ipv4" -ne "0" ] && [ "$serverchan_ipv4" -ne "1" ] && [ "$serverchan_ipv4" -ne "2" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 ipv4 变化通知 开关" >> ${logfile};fi + ipv4_interface=`get_config ipv4_interface` + if [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -eq "1" ] && [ -z "$ipv4_interface" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 ipv4 IP 接口信息" >> ${logfile};fi + ipv4_URL=`get_config ipv4_URL` + if [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -eq "2" ] && [ -z "$ipv4_URL" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 ipv4 IP URL信息" >> ${logfile};fi + serverchan_ipv6=`get_config serverchan_ipv6` + if [ -z "$serverchan_ipv6" ] || [ "$serverchan_ipv6" -ne "0" ] && [ "$serverchan_ipv6" -ne "1" ] && [ "$serverchan_ipv6" -ne "2" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 ipv6 变化通知 开关" >> ${logfile};fi + ipv6_interface=`get_config ipv6_interface` + if [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -eq "1" ] && [ -z "$ipv6_interface" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 ipv6 IP 接口信息" >> ${logfile};fi + ipv6_URL=`get_config ipv6_URL` + if [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -eq "2" ] && [ -z "$ipv6_URL" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 ipv6 IP URL信息" >> ${logfile};fi serverchan_up=`get_config serverchan_up` + if [ -z "$serverchan_up" ] || [ "$serverchan_up" -ne "0" ] && [ "$serverchan_up" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 设备上线提醒 开关" >> ${logfile};fi serverchan_down=`get_config serverchan_down` + if [ -z "$serverchan_down" ] || [ "$serverchan_down" -ne "0" ] && [ "$serverchan_down" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 设备下线提醒 开关" >> ${logfile};fi serverchan_sheep=`get_config serverchan_sheep` if [ -z "$serverchan_sheep" ] ; then serverchan_sheep="0";fi serverchan_whitelist=`get_config serverchan_whitelist` serverchan_blacklist=`get_config serverchan_blacklist` serverchan_interface=`get_config serverchan_interface` device_aliases=`get_config device_aliases` - if [ -z "$device_aliases" ] ; then device_aliases=`echo $device_aliases | sed 's/ /\n/g' | sed 's/-/ /g'`;fi + if [ ! -z "$device_aliases" ] ; then device_aliases=`echo $device_aliases | sed 's/ /\n/g' | sed 's/-/ /g'`;fi starttime=`get_config starttime` endtime=`get_config endtime` sleeptime=60 @@ -29,16 +49,6 @@ function read_config(){ temperature_enable=`get_config temperature_enable` temperature=`get_config temperature` dir="/tmp/serverchan/" - debuglevel=`get_config debuglevel` - if [ -z "$debuglevel" ] ; then logfile="/dev/null";else logfile="/tmp/serverchan/server_chan.log";fi - if [ -z "$serverchan_enable" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取程序开关 " >> ${logfile};fi - if [ -z "$serverchan_enable" ] || [ "$serverchan_enable" -eq "0" ] ; then exit;fi - if [ -z "$serverchan_sckey" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 SCKEY" >> ${logfile};fi - if [ -z "$serverchan_sckey" ] ; then exit;fi - if [ -z "$serverchan_sckey" ] && [ "${#serverchan_sckey}" -lt "50" ] ; then echo "`date "+%H:%M:%S"` 【!!!】请填入正确的 SCKEY " >> ${logfile};fi - if [ -z "$serverchan_ip" ] || [ "$serverchan_ip" -ne "0" ] && [ "$serverchan_ip" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 ip 变化通知 开关" >> ${logfile};fi - if [ -z "$serverchan_up" ] || [ "$serverchan_up" -ne "0" ] && [ "$serverchan_up" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 设备上线提醒 开关" >> ${logfile};fi - if [ -z "$serverchan_down" ] || [ "$serverchan_down" -ne "0" ] && [ "$serverchan_down" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【!!!】无法读取 设备下线提醒 开关" >> ${logfile};fi } #等待 5s,确保 luci 设置已保存 @@ -71,24 +81,24 @@ Temperature_n=0 cpuload_n=0 send_enable=0 echo "`date "+%H:%M:%S"` 【初始化】载入配置文件" >> ${logfile} -if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【初始化】工作目录为 $dir " >> ${logfile};fi -if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【初始化】log 目录为 $logfile " >> ${logfile};fi +if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【初始化】工作目录为 $dir " >> ${logfile};fi +if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【初始化】log 目录为 $logfile " >> ${logfile};fi # 如果 “忽略列表 为空” 并且 “关注列表为空” if [ -z "$serverchan_whitelist" ] && [ -z "$serverchan_blacklist" ] && [ -z "$serverchan_interface" ]; then - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【初始化】未启用 MAC 过滤" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【初始化】未启用 MAC 过滤" >> ${logfile};fi # 如果 “忽略列表不为空” elif [ ! -z "$serverchan_whitelist" ] ; then - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【初始化】忽略列表内设备" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【初始化】忽略列表内设备" >> ${logfile};fi # 如果 “关注列表不为空” elif [ ! -z "$serverchan_blacklist" ] ; then - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【初始化】仅关注列表内设备" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【初始化】仅关注列表内设备" >> ${logfile};fi # 如果 “仅关注接口选项打开” elif [ ! -z "$serverchan_interface" ] ; then - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【初始化】仅关注接口内设备" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【初始化】仅关注接口内设备" >> ${logfile};fi fi } @@ -139,43 +149,43 @@ fi #免打扰检测 function serverchan_disturb(){ -if [ ! -z "$serverchan_sheep" ] && [ "$serverchan_sheep" -eq "1" ] && [ ! -z "$starttime" ] && [ ! -z "$endtime" ] ;then - 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 enable=1;else enable=0;fi + if [ ! -z "$serverchan_sheep" ] && [ "$serverchan_sheep" -eq "1" ] && [ ! -z "$starttime" ] && [ ! -z "$endtime" ] ;then + 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 enable=1;else enable=0;fi - if [ "$enable" -eq "0" ] ;then - sheep_str=0 - while [ $enable -eq "0" ] ; - do - if [ "$sheep_str" -eq "0" ] ; then - echo "`date "+%H:%M:%S"` 【免打扰】夜深了,该休息了" >> ${logfile} - sheep_str=1 + if [ "$enable" -eq "0" ] ;then + sheep_str=0 + while [ $enable -eq "0" ] ; + do + if [ "$sheep_str" -eq "0" ] ; then + echo "`date "+%H:%M:%S"` 【免打扰】夜深了,该休息了" >> ${logfile} + sheep_str=1 + fi + read_config + 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 + enable=1 + else + enable=0 + enable_detection 1 + fi + continue + done + unset title + unset content + rm -f ${dir}title >/dev/null 2>&1 + rm -f ${dir}content >/dev/null 2>&1 fi - read_config - 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 - enable=1 - else - enable=0 - enable_detection 1 - fi - continue - done - unset title - unset content - rm -f ${dir}title >/dev/null 2>&1 - rm -f ${dir}content >/dev/null 2>&1 fi -fi } #清理日志 function clean_log(){ -logrow=$(grep -c "" ${logfile}) -if [ $logrow -gt 500 ] ;then - #cat /dev/null > ${logfile} - sed -i '1,100d' ${logfile} - echo "`date "+%H:%M:%S"` 【清理】日志超出上限,删除前 100 条" >> ${logfile} -fi + logrow=$(grep -c "" ${logfile}) + if [ $logrow -gt 500 ] ;then + #cat /dev/null > ${logfile} + sed -i '1,100d' ${logfile} + echo "`date "+%H:%M:%S"` 【清理】日志超出上限,删除前 100 条" >> ${logfile} + fi } if [ -f ${logfile} ] ; then clean_log;fi @@ -194,6 +204,82 @@ else fi } +# 流量数据 +function usage(){ + if [ -f "/usr/bin/serverchan/wrtbwmon/wrtbwmon" ] && [ -f "/usr/bin/serverchan/wrtbwmon/readDB.awk" ] ; then + /usr/bin/serverchan/wrtbwmon/wrtbwmon update ${dir}usage.db + else + echo "`date "+%H:%M:%S"` 【!!!】流量数据文件缺失" >> ${logfile} + fi +} + +function usage_ip(){ + if [ "$1" ] ;then + ip=`cat /tmp/serverchan/usage.db | grep -w $1` + if [ ! -z "$ip" ] ; then ip=`echo $ip | sed 's/,/ /g'`;fi + if [ ! -z "$ip" ] ; then ip_total=`echo $ip | awk '{print $6}'`;fi + if [ ! -z "$ip_total" ] ; then echo `bytes_for_humans $ip_total`;fi + fi +} +# 流量数据剔除ip +function usage_down(){ + if [ ! -f "${dir}usage.db" ] ; then return;fi + if [ "$1" ] ;then + sed -i "/$1/d" ${dir}usage.db + logrow_usage=$(grep -c "" ${dir}usage.db) + if [ $logrow_usage -le "1" ] ;then + rm -f ${dir}usage.db + fi + fi +} + +# 流量数据单位换算 +# bytes_for_humans 1024 +function bytes_for_humans { + if [ "$1" ] ;then + if [[ $1 -lt 1024 ]]; then + echo $1 bytes + elif [[ $1 -lt 1048576 ]]; then + echo `awk 'BEGIN{printf "%.2f\n",'$1'/'1024'}'` KB + elif [[ $1 -lt 1073741824 ]]; then + echo `awk 'BEGIN{printf "%.2f\n",'$1'/'1048576'}'` MB + else + echo `awk 'BEGIN{printf "%.2f\n",'$1'/'1073741824'}'` GB + fi + else + echo 0bytes + fi +} + +# 时间单位换算 +# time_for_humans 1024 +function time_for_humans { + if [ "$1" ] ;then + if [[ $1 -lt 60 ]]; then + echo $1 秒 + elif [[ $1 -lt 3600 ]]; then + usetime_min=`expr $1 / 60` + usetime_sec=`expr $usetime_min \* 60` + usetime_sec=`expr $1 - ${usetime_sec}` + echo $usetime_min 分钟 $usetime_sec 秒 + elif [[ $1 -lt 216000 ]]; then + usetime_hour=`expr $1 / 3600` + usetime_min=`expr $usetime_hour \* 3600` + usetime_min=`expr $1 - ${usetime_min}` + usetime_min=`expr ${usetime_min} / 60` + echo $usetime_hour 小时 $usetime_min 分 + else + usetime_day=`expr $1 / 86400` + usetime_hour=`expr $usetime_day \* 86400` + usetime_hour=`expr $1 - ${usetime_hour}` + usetime_hour=`expr ${usetime_hour} / 3600` + echo $usetime_day 天 $usetime_hour 小时 + fi + else + echo 0 秒 + fi +} + #检测设备上线 function up(){ if [ ! -f "${dir}ipAddress" ] ; then > ${dir}ipAddress;fi @@ -205,7 +291,7 @@ if [ "$1" ] ;then # 如果 ipAddress 文件中存在此ip,则跳过,待断线检测 ip_mac=$( cat /var/dhcp.leases | grep -w $1 |awk '{print $2}' | grep -v "^$" | sort -u ) if [ -z "$ip_mac" ] ; then ip_mac=$( cat /proc/net/arp | grep "0x2" | grep -w $1 | awk '{print $4}' | grep -v "^$" | sort -u );fi - + if [ ! -z "$device_aliases" ] && [ ! -z "$ip_mac" ] && ( echo "$device_aliases" | grep -q -i $ip_mac ); then ip_name=$( echo "$device_aliases" | grep -i $ip_mac |awk '{print $2}' | grep -v "^$" | sort -u ) else @@ -215,14 +301,14 @@ if [ "$1" ] ;then if [ -z "$ip_mac" ] ; then ip_mac="unknown";fi if [ -z "$ip_name" ] ; then ip_name="unknown";fi - local ip_ms=`echo $( arping -I $( cat /proc/net/arp | grep -w $1 | awk '{print $6}' | grep -v "^$" | sort -u ) -c 10 -f -w 3 $1)` + local ip_ms=`echo $( arping -I $( cat /proc/net/arp | grep -w $1 | awk '{print $6}' | grep -v "^$" | sort -u ) -c 10 -f -w 1 $1)` if ( ! echo ${ip_ms} | grep -q ms );then - local ip_ms=`ping -c 1 -w 2 $1` + local ip_ms=`ping -c 1 -w 1 $1` if ( ! echo ${ip_ms} | grep -q ms );then - sleep 2 - local ip_ms=`echo $( arping -I $( cat /proc/net/arp | grep -w $1 | awk '{print $6}' | grep -v "^$" | sort -u ) -c 10 -f -w 5 $1)` + sleep 1 + local ip_ms=`echo $( arping -I $( cat /proc/net/arp | grep -w $1 | awk '{print $6}' | grep -v "^$" | sort -u ) -c 10 -f -w 2 $1)` fi fi @@ -231,29 +317,27 @@ if [ "$1" ] ;then if ( echo ${ip_ms} | grep -q ms ); then # 如果连接成功 - LockFile + LockFile + usage_down $1 if ( echo "$ip_mac" | grep -q "unknown" ) || ( echo "$ip_name" | grep -q "unknown" ) ; then + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 获取 $1 $ip_mac 设备信息失败,重试中" >> ${logfile};fi for i in `seq 1 5` do - echo "`date "+%H:%M:%S"` 获取 $1 $ip_mac 设备信息失败,重试中" >> ${logfile} sleep 1 - ip_mac=$( cat /var/dhcp.leases | grep -w $1 |awk '{print $2}' | grep -v "^$" | sort -u ) - if [ -z "$ip_mac" ] ; then ip_mac=$( cat /proc/net/arp | grep "0x2" | grep -w $1 | awk '{print $4}' | grep -v "^$" | sort -u );fi - if [ ! -z "$device_aliases" ] && [ ! -z "$ip_mac" ] && ( echo "$device_aliases" | grep -q -i $ip_mac ); then - ip_name=$( echo "$device_aliases" | grep -i $ip_mac |awk '{print $2}' | grep -v "^$" | sort -u ) - else - ip_name=$( cat /var/dhcp.leases | grep -w $1 |awk '{print $4}' | grep -v "^$" | sort -u ) - fi + if [ -z "$ip_mac" ] ; then ip_mac=$( cat /var/dhcp.leases | grep -w $1 |awk '{print $2}' | grep -v "^$" | sort -u );fi + if [ -z "$ip_mac" ] ; then ip_mac=$( cat /proc/net/arp | grep "0x2" | grep -w $1 | awk '{print $4}' | grep -v "^$" | sort -u );fi + if [ ! -z "$device_aliases" ] && [ ! -z "$ip_mac" ] && ( echo "$device_aliases" | grep -q -i $ip_mac ); then ip_name=$( echo "$device_aliases" | grep -i $ip_mac |awk '{print $2}' | grep -v "^$" | sort -u );fi + if [ -z "$ip_name" ] ; then ip_name=$( cat /var/dhcp.leases | grep -w $1 |awk '{print $4}' | grep -v "^$" | sort -u );fi if [ ! -z "$ip_mac" ] && [ ! -z "$ip_name" ] ; then break;fi done fi if [ -z "$ip_mac" ] ; then ip_mac="unknown" - echo "`date "+%H:%M:%S"` 获取 $1 mac 超时,暂停跳过" >> ${logfile} + echo "`date "+%H:%M:%S"` 获取 $1 mac 超时,跳过" >> ${logfile} fi if [ -z "$ip_name" ] ; then ip_name="unknown" - echo "`date "+%H:%M:%S"` 获取 $1 设备名超时,暂停跳过" >> ${logfile} + echo "`date "+%H:%M:%S"` 获取 $1 设备名超时,跳过" >> ${logfile} fi if [ ! -z "$send_enable" ] && [ "$send_enable" -ne 3 ] ; then @@ -271,7 +355,7 @@ if [ "$1" ] ;then content="%0D%0A%0D%0A---%0D%0A%0D%0A####新设备连接%0D%0A%0D%0A"">$ip_name" fi #echo "$1 $( cat /var/dhcp.leases | grep -w $1 |awk '{print $2" "$4}' )" >> ${dir}ipAddress - echo "$1 $ip_mac $ip_name" >> ${dir}ipAddress + echo "$1 $ip_mac $ip_name `date +%s`" >> ${dir}ipAddress echo "`date "+%H:%M:%S"` 【微信推送】新设备 $ip_name $1 连接了">> ${logfile} if [ ! -z "$serverchan_blacklist" ] ; then @@ -285,18 +369,17 @@ if [ "$1" ] ;then else # 如果定时任务运行 echo "`date "+%H:%M:%S"` 新设备 $ip_name $1 连接了" >> ${logfile} - echo "$1 $ip_mac $ip_name" >> ${dir}ipAddress + echo "$1 $ip_mac $ip_name `date +%s`" >> ${dir}ipAddress unset title unset content fi else - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 设备 $ip_name $1 连接失败" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 设备 $ip_name $1 连接失败" >> ${logfile};fi fi rm -f ${dir}serverchan.lock >/dev/null 2>&1 else - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -eq "5" ] ; then echo "`date "+%H:%M:%S"` $ip_name $1 已存在,跳过" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -eq "5" ] ; then echo "`date "+%H:%M:%S"` $ip_name $1 已存在,跳过" >> ${logfile};fi fi - unset ip_ms fi } @@ -311,26 +394,24 @@ if [ "$1" ] ;then if [ -z "$ip_mac" ] ; then ip_mac=$( cat /proc/net/arp | grep "0x2" | grep -w $1 | awk '{print $4}' | grep -v "^$" | sort -u );fi ip_name=$( cat ${dir}ipAddress | grep -w $1 |awk '{print $3}' | grep -v "^$" | sort -u ) if ( echo "$ip_mac" | grep -q "unknown" ) || ( echo "$ip_name" | grep -q "unknown" ) ; then - echo "`date "+%H:%M:%S"` $1 $ip_mac 无设备名,尝试重新读取" >> ${logfile} + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` $1 $ip_mac 无设备名,尝试重新读取" >> ${logfile};fi + time_up=$( cat ${dir}ipAddress | grep -w $ip |awk '{print $4}' | grep -v "^$" | sort -u ) + if [ -z "$time_up" ] ; then time_up=`date +%s`;fi sed -i "/$1/d" ${dir}ipAddress - ip_mac=$( cat /var/dhcp.leases | grep -w $1 |awk '{print $2}' | grep -v "^$" | sort -u ) + if [ -z "$ip_mac" ] ; then ip_mac=$( cat /var/dhcp.leases | grep -w $1 |awk '{print $2}' | grep -v "^$" | sort -u );fi if [ -z "$ip_mac" ] ; then ip_mac=$( cat /proc/net/arp | grep "0x2" | grep -w $1 | awk '{print $4}' | grep -v "^$" | sort -u );fi - if [ ! -z "$device_aliases" ] && [ ! -z "$ip_mac" ] && ( echo "$device_aliases" | grep -q -i $ip_mac ); then - ip_name=$( echo "$device_aliases" | grep -i $ip_mac |awk '{print $2}' | grep -v "^$" | sort -u ) - else - ip_name=$( cat /var/dhcp.leases | grep -w $1 |awk '{print $4}' | grep -v "^$" | sort -u ) - fi + if [ ! -z "$device_aliases" ] && [ ! -z "$ip_mac" ] && ( echo "$device_aliases" | grep -q -i $ip_mac ); then ip_name=$( echo "$device_aliases" | grep -i $ip_mac |awk '{print $2}' | grep -v "^$" | sort -u );fi + if [ -z "$ip_name" ] ; then ip_name=$( cat /var/dhcp.leases | grep -w $1 |awk '{print $4}' | grep -v "^$" | sort -u );fi if [ -z "$ip_mac" ] ; then ip_mac="unknown";fi if [ -z "$ip_name" ] ; then ip_name="unknown";fi - echo "$1 $ip_mac $ip_name" >> ${dir}ipAddress + echo "$1 $ip_mac $ip_name $time_up" >> ${dir}ipAddress fi - - local ip_ms=`echo $( arping -I $( cat /proc/net/arp | grep -w $1 | awk '{print $6}' | grep -v "^$" | sort -u ) -c 10 -f -w 3 $1)` + local ip_ms=`echo $( arping -I $( cat /proc/net/arp | grep -w $1 | awk '{print $6}' | grep -v "^$" | sort -u ) -c 10 -f -w 10 $1)` if ( ! echo ${ip_ms} | grep -q ms );then - local ip_ms=`ping -c 1 -w 2 $1` + local ip_ms=`ping -c 5 -w 5 $1` if ( ! echo ${ip_ms} | grep -q ms );then - sleep 3 + sleep 1 local ip_ms=`echo $( arping -I $( cat /proc/net/arp | grep -w $1 | awk '{print $6}' | grep -v "^$" | sort -u ) -c 10 -f -w 10 $1)` fi fi @@ -340,7 +421,7 @@ if [ "$1" ] ;then if ( echo ${ip_ms} | grep -q ms ); then # 如果连接成功 - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 设备 $ip_name $1 依然坚挺" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 设备 $ip_name $1 依然坚挺" >> ${logfile};fi else # 如果连接失败 LockFile @@ -350,16 +431,20 @@ if [ "$1" ] ;then # 如果打开了下线提醒 if [ -f "${dir}title" ] ; then title=`cat ${dir}title` ;fi if [ -f "${dir}content" ] ; then content=`cat ${dir}content` ;fi - + ip_total=`usage_ip $1` + time_down=`date +%s` + time_up=$( cat ${dir}ipAddress | grep -w $1 |awk '{print $4}' | grep -v "^$" | sort -u ) + time1=$(($time_down-$time_up)) + time1=`time_for_humans $time1` if [ -z "$title" ] ; then title="设备离线通知" - content="%0D%0A%0D%0A---%0D%0A%0D%0A####设备断开连接%0D%0A%0D%0A"">$ip_name" + content="%0D%0A%0D%0A---%0D%0A%0D%0A####设备断开连接%0D%0A%0D%0A"">$ip_name%0D%0A%0D%0A"">总计流量:$ip_total%0D%0A%0D%0A"">在线 $time1" elif ( echo ${title} | grep -q "设备离线通知" ) ; then title="设备离线通知" - content="%0D%0A%0D%0A"">$ip_name" + content="%0D%0A%0D%0A"">$ip_name%0D%0A%0D%0A"">总计流量:$ip_total%0D%0A%0D%0A"">在线 $time1" else title="设备状态变化" - content="%0D%0A%0D%0A---%0D%0A%0D%0A####设备断开连接%0D%0A%0D%0A"">$ip_name" + content="%0D%0A%0D%0A---%0D%0A%0D%0A####设备断开连接%0D%0A%0D%0A"">$ip_name%0D%0A%0D%0A"">总计流量:$ip_total%0D%0A%0D%0A"">在线 $time1" fi echo "`date "+%H:%M:%S"` 【微信推送】设备 $ip_name $1 断开连接 " >> ${logfile} @@ -368,6 +453,7 @@ if [ "$1" ] ;then fi echo "`date "+%H:%M:%S"` 设备 $ip_name $1 断开连接 " >> ${logfile} sed -i "/$1/d" ${dir}ipAddress + usage_down $1 unset title unset content fi @@ -379,7 +465,7 @@ fi #发送定时数据 function send(){ - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 创建定时任务" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 创建定时任务" >> ${logfile};fi uci set serverchan.serverchan.send_enable=3 uci commit serverchan unset title @@ -395,13 +481,17 @@ function send(){ if [ ! -z "$router_status" ] && [ "$router_status" -eq "1" ] ; then send_content=${send_content}"%0D%0A%0D%0A"" 内存占用:`free -m | sed -n '2p' | awk '{print""($3/$2)*100"%"}'`";fi if [ ! -z "$router_status" ] && [ "$router_status" -eq "1" ] ; then send_content=${send_content}"%0D%0A%0D%0A""`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)}'`";fi router_temp=`get_config router_temp` - if [ ! -z "$router_temp" ] && [ "$router_temp" -eq "1" ] ; then send_content=${send_content}"%0D%0A%0D%0A""---%0D%0A%0D%0A#### 设备温度%0D%0A%0D%0A CPU:`cut -c1-2 /sys/class/thermal/thermal_zone0/temp`%e2%84%83";fi + if [ ! -z "$router_temp" ] && [ "$router_temp" -eq "1" ] ; then send_content=${send_content}"%0D%0A%0D%0A""---%0D%0A%0D%0A#### 设备温度%0D%0A%0D%0A CPU:`cut -c1-2 /sys/class/thermal/thermal_zone*/temp`%e2%84%83";fi router_wan=`get_config router_wan` send_wanIP=$(ubus call network.interface.wan status | grep '\"address\"' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') - send_hostIP=$(curl -k -s "http://members.3322.org/dyndns/getip") + send_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|cut -d' ' -f2) + send_hostIP=$(curl -k -s -4 "http://members.3322.org/dyndns/getip") + send_hostIPv6=$(curl -k -s -6 v6.ip.zxinc.org/getip) if [ ! -z "$router_wan" ] && [ "$router_wan" -eq "1" ] ; then - send_content=${send_content}"%0D%0A%0D%0A""---%0D%0A%0D%0A#### WAN 口信息%0D%0A%0D%0A WAN ip:$send_wanIP" + send_content=${send_content}"%0D%0A%0D%0A""---%0D%0A%0D%0A#### WAN 口信息%0D%0A%0D%0A ip:$send_wanIP" send_content=${send_content}"%0D%0A%0D%0A"" 外网 ip:$send_hostIP" + send_content=${send_content}"%0D%0A%0D%0A"" ipv6:$send_wanIPv6" + send_content=${send_content}"%0D%0A%0D%0A"" 外网 ipv6:$send_hostIPv6" if [ ! -z "$send_content" ] && [ ! -z "$router_wan" ] ; then if ( ! echo ${send_wanIP} | grep -q ${send_hostIP} );then send_content=${send_content}"%0D%0A%0D%0A"" 外网 ip 与接口 ip 不一致,你的 ip 不是公网 ip";fi else @@ -411,7 +501,7 @@ function send(){ fi client_list=`get_config client_list` if [ ! -z "$client_list" ] && [ "$client_list" -eq "1" ] ; then - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 检测客户端列表" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 检测客户端列表" >> ${logfile};fi if [ ! -f "${dir}ipAddress" ] ; then > ${dir}ipAddress;fi if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【连接】开始进行设备下线检测" >> ${logfile};fi @@ -436,27 +526,36 @@ function send(){ if [ "$IPLISTrow" -eq $(grep -c "" ${dir}ipAddress) ] ; then echo "`date "+%H:%M:%S"` 没有新设备连接" >> ${logfile};fi send_content=${send_content}"%0D%0A%0D%0A---%0D%0A%0D%0A#### 在线设备%0D%0A%0D%0A"; - IPLIST=$( cat ${dir}ipAddress| awk '{print $1" "$3}' ) - n=0 + ip=$( cat ${dir}ipAddress | awk '{print $1"}' ) for ip in $IPLIST; do - n=$(($n+1)) - if [ "${#ip}" -gt "20" ] ; then ip=`echo ${ip:0:20}"*"`;fi - [ $((n%2)) -eq 1 ] && send_content=${send_content}"%0D%0A%0D%0A"" $ip " - [ $((n%2)) -eq 0 ] && send_content=${send_content}"$ip" + send_content=${send_content}"%0D%0A%0D%0A"" $ip " + ip_total=`usage_ip $ip` + time_down=`date +%s` + time_up=$( cat ${dir}ipAddress | grep -w $ip |awk '{print $4}' | grep -v "^$" | sort -u ) + time1=$(($time_down-$time_up)) + time1=`time_for_humans $time1` + send_content=${send_content}"`cat ${dir}ipAddress | grep "$ip" | awk '{print $3}' | grep -v "^$" | sort -u`%0D%0A%0D%0A"" 总计流量:$ip_total 在线 $time1" done fi send_title=$( echo $send_title | sed $'s/\ /%20/g'| sed $'s/\"/%22/g'| sed $'s/\#/%23/g'| sed $'s/\&/%26/g'| sed $'s/\,/%2C/g'| sed $'s/\//%2F/g'| sed $'s/\:/%3A/g'| sed $'s/\;/%3B/g'| sed $'s/\=/%3D/g'| sed $'s/\@/%40/g') content=$( echo $content| sed $'s/unknown/%e6%9c%aa%e7%9f%a5%e8%ae%be%e5%a4%87/') #send_content=$( echo $send_content | sed $'s/\ /%20/g'| sed $'s/\"/%22/g'| sed $'s/\#/%23/g'| sed $'s/\&/%26/g'| sed $'s/\,/%2C/g'| sed $'s/\//%2F/g'| sed $'s/\:/%3A/g'| sed $'s/\;/%3B/g'| sed $'s/\=/%3D/g'| sed $'s/\@/%40/g') #未转义 | sed $'s/\(/%28/g' | sed $'s/\)/%29/g' | sed $'s/\+/%2B/g' | sed $'s/\%/%25/g' | sed $'s/\/%3E/g' | sed $'s/\?/%3F/g' | sed $'s/\\/%5C/g' | sed $'s/\|/%7C/g' - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 进行 URL 编码,标题=$send_title" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 进行 URL 编码,标题=$send_title" >> ${logfile};fi if [ -z "$send_content" ] ; then send_content="%0D%0A%0D%0A---%0D%0A%0D%0A#### 我遇到了一个难题%0D%0A%0D%0A>你没有选择需要发送的项目,该怎么办呢%0D%0A%0D%0A---"; echo "`date "+%H:%M:%S"` 【!!!】定时发送选项错误,请检查你的设置" >> ${logfile} fi nowtime=`date "+%Y-%m-%d %H:%M:%S"` - curl -s "http://sc.ftqq.com/$serverchan_sckey.send?text=${send_title}" -d "&desp=${nowtime}%0D%0A%0D%0A${send_content}" >/dev/null - + if [ ! -z "$serverchan_sheep" ] && [ "$serverchan_sheep" -eq "2" ] && [ ! -z "$starttime" ] && [ ! -z "$endtime" ] ;then + 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 + curl -s "http://sc.ftqq.com/$serverchan_sckey.send?text=${send_title}" -d "&desp=${nowtime}%0D%0A%0D%0A${send_content}" >/dev/null + else + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 当前为免打扰时间,消息不发送" >> ${logfile};fi + fi + else + curl -s "http://sc.ftqq.com/$serverchan_sckey.send?text=${send_title}" -d "&desp=${nowtime}%0D%0A%0D%0A${send_content}" >/dev/null + fi uci set serverchan.serverchan.send_enable=0 uci commit serverchan echo "`date "+%H:%M:%S"` 【微信推送】定时发送状态消息" >> ${logfile} @@ -469,10 +568,12 @@ if [ "$1" ] ;then exit fi +if [ -z "$serverchan_enable" ] || [ "$serverchan_enable" -eq "0" ] ; then exit;fi serverchan_init serverchan_cron serverchan_disturb + #初始化在线设备列表 function serverchan_first(){ if [ ! -z "$serverchan_enable" ] && [ "$serverchan_enable" -eq "1" ] ; then @@ -512,7 +613,7 @@ if [ ! -z "$serverchan_enable" ] && [ "$serverchan_enable" -eq "1" ] ; then if ( ! echo $serverchan_whitelist | grep -q -i $ip_mac ); then up $ip & else - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] && ( ! echo ${ip_mac} | grep -q "unknown" ) ; then echo "`date "+%H:%M:%S"` 忽略列表已启用,跳过$ip_name $ip" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] && ( ! echo ${ip_mac} | grep -q "unknown" ) ; then echo "`date "+%H:%M:%S"` 忽略列表已启用,跳过$ip_name $ip" >> ${logfile};fi fi # 如果 “关注列表不为空” @@ -520,14 +621,14 @@ if [ ! -z "$serverchan_enable" ] && [ "$serverchan_enable" -eq "1" ] ; then if ( echo $serverchan_blacklist | grep -q -i $ip_mac ); then up $ip & else - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] && ( ! echo ${ip_mac} | grep -q "unknown" ) ; then echo "`date "+%H:%M:%S"` 关注列表已启用,跳过$ip_name $ip" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] && ( ! echo ${ip_mac} | grep -q "unknown" ) ; then echo "`date "+%H:%M:%S"` 关注列表已启用,跳过$ip_name $ip" >> ${logfile};fi fi # 如果 “仅关注接口选项打开” elif [ ! -z "$serverchan_interface" ] ; then if ( echo $serverchan_interface | grep -q -i $( cat /proc/net/arp | grep $ip |awk '{print $6}' | grep -v "^$" | sort -u )); then up $ip & else - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] && ( ! echo ${ip_mac} | grep -q "unknown" ) ; then echo "`date "+%H:%M:%S"` 仅关注接口已启用,跳过$ip_name $ip" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] && ( ! echo ${ip_mac} | grep -q "unknown" ) ; then echo "`date "+%H:%M:%S"` 仅关注接口已启用,跳过$ip_name $ip" >> ${logfile};fi fi fi fi @@ -538,6 +639,7 @@ if [ ! -z "$serverchan_enable" ] && [ "$serverchan_enable" -eq "1" ] ; then fi } serverchan_first +usage while [ "$serverchan_enable" -eq "1" ] ; do @@ -552,45 +654,88 @@ function rand_geturl(){ rand_geturl if [ -z "$check" ] || [ "$check" -ne "200" ] ; then sleep 1 && rand_geturl;fi if [ ! -z "$check" ] && [ "$check" -eq "200" ] ; then + usage if [ ! -z "$network_enable" ] && [ "$network_enable" -eq "404" ] ; then echo "`date "+%H:%M:%S"` 【网络状态】网络恢复正常.." >> ${logfile};fi network_enable="200" #外网IP变化 - if [ ! -z "$serverchan_ip" ] && [ "$serverchan_ip" -eq "1" ] ; then - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【外网IP】正在检测外网IP变化" >> ${logfile};fi + if [ ! -z "$serverchan_ipv4" ] && [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv4" -ne "0" ] || [ "$serverchan_ipv6" -ne "0" ] ; then + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【外网IP】正在检测外网IP变化" >> ${logfile};fi nowtime=`date "+%Y-%m-%d %H:%M:%S"` - #查询当前ip - #hostIP=$(curl -k -s "http://members.3322.org/dyndns/getip") - wanIP=$(ubus call network.interface.wan status | grep '\"address\"' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') + #查询当前 ipv4 + if [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -eq "1" ] ; then IPv4=$(ip -4 address show "$ipv4_interface" | grep inet | grep -v 127.0.0 | awk '{print $2}' | cut -d'/' -f1 | head -n 1 | grep -v "^$" | sort -u);fi + if [ ! -z "$serverchan_ipv4" ] && [ "$serverchan_ipv4" -eq "2" ] ; then IPv4=$(curl -k -s -4 "$ipv4_URL");fi + + #查询当前 ipv6 + if [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -eq "1" ] ; then IPv6=$(ip -6 address show "$ipv6_interface" | grep inet6 | awk '{print $2}' | cut -d'/' -f1 | head -n 1 | grep -v "^$" | sort -u);fi + if [ ! -z "$serverchan_ipv6" ] && [ "$serverchan_ipv6" -eq "2" ] ; then IPv6=$(curl -k -s -6 "$ipv6_URL");fi + #查询ip历史记录 - if [ -f ${dir}ip ] ; then lastIP=$( cat "${dir}ip");else unset lastIP;fi - if [ ! -z "$lastIP" ] ; then - #if [ "$wanIP" != "$lastIP" ] && [ ! -z "$wanIP" ] ; then - if [ ! -z "$wanIP" ] && ( echo ${wanIP} | grep -w -q ${lastIP} );then - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` IP 无变化,当前 ip 为 $lastIP" >> ${logfile};fi - else - echo "`date "+%H:%M:%S"` 当前 IP: ${wanIP}" >> ${logfile} - echo "`date "+%H:%M:%S"` 上次 IP: ${lastIP}" >> ${logfile} - echo "`date "+%H:%M:%S"` 【微信推送】当前IP:${wanIP}" >> ${logfile} - echo -n $wanIP > ${dir}ip + if [ -f ${dir}ip ] ; then + last_IPv4=$(cat "${dir}ip" | grep IPv4 | awk '{print $2}' | grep -v "^$" | sort -u) + last_IPv6=$(cat "${dir}ip" | grep IPv6 | awk '{print $2}' | grep -v "^$" | sort -u) + if [ "$serverchan_ipv4" -eq "1" ] ;then + if [ ! -z "$IPv4" ] && ( echo ${IPv4} | grep -w -q ${last_IPv4} );then + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` IP 无变化,当前 ip 为 $last_IPv4" >> ${logfile};fi + elif [ ! -z "$IPv4" ] ; then + echo "`date "+%H:%M:%S"` 当前 IP: ${IPv4}" >> ${logfile} + echo "`date "+%H:%M:%S"` 上次 IP: ${last_IPv4}" >> ${logfile} + echo "`date "+%H:%M:%S"` 【微信推送】当前IP:${IPv4}" >> ${logfile} + echo IPv4 $IPv4 > ${dir}ip + echo -e IPv6 $last_IPv6 >> ${dir}ip - if [ -f "${dir}title" ] ; then title=`cat ${dir}title` ;fi - if [ -f "${dir}content" ] ; then content=`cat ${dir}content` ;fi - if ( echo ${title} | grep -q "外网IP地址变化" ) || [ -z "$title" ] ; then - title="外网IP地址变化" + if [ -f "${dir}title" ] ; then title=`cat ${dir}title` ;fi + if [ -f "${dir}content" ] ; then content=`cat ${dir}content` ;fi + if ( echo ${title} | grep -q "IP 地址变化" ) || [ -z "$title" ] ; then + title="IP 地址变化" + else + title="设备状态变化" + fi + + content="%0D%0A%0D%0A---%0D%0A%0D%0A""####IP 地址变化%0D%0A%0D%0A>当前 IP:${IPv4}" + echo $title >${dir}title + echo -n $content >>${dir}content else - title="设备状态变化" + echo "`date "+%H:%M:%S"` 【!!!】获取 IPv4 地址失败" >> ${logfile} fi - - content="%0D%0A%0D%0A---%0D%0A%0D%0A""####外网IP地址变化%0D%0A%0D%0A>当前IP:${wanIP}" - echo $title >${dir}title - echo -n $content >>${dir}content fi + if [ "$serverchan_ipv6" -eq "1" ] ;then + if [ ! -z "$IPv6" ] && ( echo ${IPv6} | grep -w -q ${last_IPv6} );then + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` IPv6 无变化,当前 ipv6 为 $last_IPv6" >> ${logfile};fi + elif [ ! -z "$IPv6" ] ; then + echo "`date "+%H:%M:%S"` 当前 IPv6: ${IPv6}" >> ${logfile} + echo "`date "+%H:%M:%S"` 上次 IPv6: ${last_IPv6}" >> ${logfile} + echo "`date "+%H:%M:%S"` 【微信推送】当前IPv6:${IPv6}" >> ${logfile} + echo IPv4 $IPv4 > ${dir}ip + echo -e IPv6 $IPv6 >> ${dir}ip + + if [ -f "${dir}title" ] ; then title=`cat ${dir}title` ;fi + if [ -f "${dir}content" ] ; then content=`cat ${dir}content` ;fi + if ( echo ${title} | grep -q "IPv6 地址变化" ) || [ -z "$title" ] ; then + title="IPv6 地址变化" + else + title="设备状态变化" + fi + + content="%0D%0A%0D%0A---%0D%0A%0D%0A""####IPv6 地址变化%0D%0A%0D%0A>当前 IPv6:${IPv6}" + echo $title >${dir}title + echo -n $content >>${dir}content + else + echo "`date "+%H:%M:%S"` 【!!!】获取 IPv6 地址失败" >> ${logfile} + fi + fi + else - echo "`date "+%H:%M:%S"` 【微信推送】路由器已经重启!当前IP:${wanIP}" >> ${logfile} - echo "`date "+%H:%M:%S"` 当前IP: ${wanIP}" >> ${logfile} - echo -n $wanIP > ${dir}ip + unset last_IPv4 + unset last_IPv6 + echo "`date "+%H:%M:%S"` 【微信推送】路由器已经重启!当前IP:${IPv4}" >> ${logfile} + echo "`date "+%H:%M:%S"` 当前IP: ${IPv4}" >> ${logfile} + echo "`date "+%H:%M:%S"` 【微信推送】路由器已经重启!当前IPv6:${IPv6}" >> ${logfile} + + echo "`date "+%H:%M:%S"` 当前IP: ${IPv6}" >> ${logfile} + echo IPv4 $IPv4 > ${dir}ip + echo -e IPv6 $IPv6 >> ${dir}ip if [ -f "${dir}title" ] ; then title=`cat ${dir}title` ;fi if [ -f "${dir}content" ] ; then content=`cat ${dir}content` ;fi @@ -600,7 +745,7 @@ function rand_geturl(){ title="设备状态变化" fi - content="%0D%0A%0D%0A---%0D%0A%0D%0A""####路由器重新启动%0D%0A%0D%0A>当前IP:${wanIP}" + content="%0D%0A%0D%0A---%0D%0A%0D%0A""####路由器重新启动%0D%0A%0D%0A>当前IP:${IPv4}%0D%0A%0D%0A---%0D%0A%0D%0A""####IPv6 地址变化%0D%0A%0D%0A>当前 IPv6:${IPv6}" echo $title >${dir}title echo -n $content >>${dir}content fi @@ -625,8 +770,10 @@ function rand_geturl(){ ip_name=$( echo "$device_aliases" | grep -i $ip_mac |awk '{print $2}' | grep -v "^$" | sort -u ) ipAddress_name=$( cat ${dir}ipAddress | grep -w $ip | awk '{print $3}' | grep -v "^$" | sort -u ) if [ ! -z ipAddress_name ] && ( ! echo $ip_name | grep -q $ipAddress_name ) ; then + time_up=$( cat ${dir}ipAddress | grep -w $ip |awk '{print $4}' | grep -v "^$" | sort -u ) + if [ -z "$time_up" ] ; then time_up=`date +%s`;fi sed -i "/$ip/d" ${dir}ipAddress - echo "$ip $ip_mac $ip_name" >> ${dir}ipAddress + echo "$ip $ip_mac $ip_name $time_up" >> ${dir}ipAddress fi else ip_name=$( cat /var/dhcp.leases | grep -w $ip |awk '{print $4}' | grep -v "^$" | sort -u ) @@ -645,6 +792,7 @@ function rand_geturl(){ down $ip & else sed -i "/$ip/d" ${dir}ipAddress + usage_down $ip fi # 如果 “关注列表不为空” @@ -653,6 +801,7 @@ function rand_geturl(){ down $ip & else sed -i "/$ip/d" ${dir}ipAddress + usage_down $ip fi # 如果 “仅关注接口选项打开” elif [ ! -z "$serverchan_interface" ] ; then @@ -660,6 +809,7 @@ function rand_geturl(){ down $ip & else sed -i "/$ip/d" ${dir}ipAddress + usage_down $ip fi fi fi @@ -706,7 +856,7 @@ function rand_geturl(){ if ( ! echo $serverchan_whitelist | grep -q -i $ip_mac ); then up $ip & else - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] && ( ! echo ${ip_mac} | grep -q "unknown" ) ; then echo "`date "+%H:%M:%S"` 忽略列表已启用,跳过$ip_name $ip" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] && ( ! echo ${ip_mac} | grep -q "unknown" ) ; then echo "`date "+%H:%M:%S"` 忽略列表已启用,跳过$ip_name $ip" >> ${logfile};fi fi # 如果 “关注列表不为空” @@ -714,7 +864,7 @@ function rand_geturl(){ if ( echo $serverchan_blacklist | grep -q -i $ip_mac ); then up $ip & else - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] && ( ! echo ${ip_mac} | grep -q "unknown" ) ; then echo "`date "+%H:%M:%S"` 关注列表已启用,跳过$ip_name $ip" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] && ( ! echo ${ip_mac} | grep -q "unknown" ) ; then echo "`date "+%H:%M:%S"` 关注列表已启用,跳过$ip_name $ip" >> ${logfile};fi fi # 如果 “仅关注接口选项打开” @@ -722,7 +872,7 @@ function rand_geturl(){ if ( echo $serverchan_interface | grep -q -i $( cat /proc/net/arp | grep $ip |awk '{print $6}' | grep -v "^$" | sort -u )); then up $ip & else - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] && ( ! echo ${ip_mac} | grep -q "unknown" ) ; then echo "`date "+%H:%M:%S"` 仅关注接口已启用,跳过$ip_name $ip" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] && ( ! echo ${ip_mac} | grep -q "unknown" ) ; then echo "`date "+%H:%M:%S"` 仅关注接口已启用,跳过$ip_name $ip" >> ${logfile};fi fi fi @@ -731,14 +881,16 @@ function rand_geturl(){ wait if [ -f "${dir}content" ] ; then content=`cat ${dir}content` ;fi if [ -z "$content" ] || ( ! echo ${content} | grep -q "新设备连接" ) ; then - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 没有新设备连接" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 没有新设备连接" >> ${logfile};fi + else + usage fi fi #负载状态报警 if [ ! -z "$cpuload_enable" ] && [ "$cpuload_enable" -eq "1" ] ; then - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【负载】正在检测 CPU 负载" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【负载】正在检测 CPU 负载" >> ${logfile};fi cpu_fuzai=`cat /proc/loadavg | awk '{print $1}'` cpuload=`get_config cpuload` if [ ! -z "$cpuload" ] && [ `expr $cpu_fuzai \> $cpuload` -eq "1" ] ; then @@ -746,7 +898,7 @@ function rand_geturl(){ echo "`date "+%H:%M:%S"` 【!!警报!!】当前 CPU 负载过高: ${cpu_fuzai}" >> ${logfile} else cpuload_n=0 - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` CPU 负载正常:$cpu_fuzai" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` CPU 负载正常:$cpu_fuzai" >> ${logfile};fi fi if [ "$cpuload_n" -eq "5" ] ;then @@ -764,15 +916,15 @@ function rand_geturl(){ #温度状态报警 if [ ! -z "$temperature_enable" ] && [ "$temperature_enable" -eq "1" ] ; then - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【温度】正在检测 CPU 温度" >> ${logfile};fi - cpu_wendu=`cut -c1-2 /sys/class/thermal/thermal_zone0/temp` + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【温度】正在检测 CPU 温度" >> ${logfile};fi + cpu_wendu=`cut -c1-2 /sys/class/thermal/thermal_zone*/temp` temperature=`get_config temperature` if [ ! -z "$temperature" ] && [ "$cpu_wendu" -gt "$temperature" ] ; then Temperature_n=$(($Temperature_n+1)) echo "`date "+%H:%M:%S"` 【!!警报!!】当前 CPU 温度过高: ${cpu_wendu}" >> ${logfile} else Temperature_n=0 - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` CPU 温度正常:$cpu_wendu" >> ${logfile};fi + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` CPU 温度正常:$cpu_wendu" >> ${logfile};fi fi if [ "$Temperature_n" -eq "5" ] ;then if [ -f "${dir}title" ] ; then title=`cat ${dir}title` ;fi @@ -826,9 +978,17 @@ function serverchan_send(){ if [ ! -z "$title" ] && [ ! -z "$content" ] ; then nowtime=`date "+%Y-%m-%d %H:%M:%S"` title=$( echo $title | sed $'s/\ /%20/g'| sed $'s/\"/%22/g'| sed $'s/\#/%23/g'| sed $'s/\&/%26/g'| sed $'s/\,/%2C/g'| sed $'s/\//%2F/g'| sed $'s/\:/%3A/g'| sed $'s/\;/%3B/g'| sed $'s/\=/%3D/g'| sed $'s/\@/%40/g') - content=$( echo $content| sed $'s/unknown/%e6%9c%aa%e7%9f%a5%e8%ae%be%e5%a4%87/') - if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 进行 URL 编码,标题=$title" >> ${logfile};fi - curl -s "http://sc.ftqq.com/$serverchan_sckey.send?text=${title}" -d "&desp=${nowtime}%0D%0A%0D%0A${content}" >/dev/null + content=$( echo $content| sed $'s/unknown/%e6%9c%aa%e7%9f%a5%e8%ae%be%e5%a4%87/') + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 进行 URL 编码,标题=$title" >> ${logfile};fi + if [ ! -z "$serverchan_sheep" ] && [ "$serverchan_sheep" -eq "2" ] && [ ! -z "$starttime" ] && [ ! -z "$endtime" ] ;then + 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 + curl -s "http://sc.ftqq.com/$serverchan_sckey.send?text=${title}" -d "&desp=${nowtime}%0D%0A%0D%0A${content}" >/dev/null + else + if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 当前为免打扰时间,消息不发送" >> ${logfile};fi + fi + else + curl -s "http://sc.ftqq.com/$serverchan_sckey.send?text=${title}" -d "&desp=${nowtime}%0D%0A%0D%0A${content}" >/dev/null + fi unset title unset content rm -f ${dir}title >/dev/null 2>&1 @@ -836,18 +996,19 @@ function serverchan_send(){ fi if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【等待】我累了,$sleeptime 秒后再回来" >> ${logfile};fi enable_detection 60 - serverchan_disturb } + serverchan_disturb + serverchan_send - if [ ! -z "$serverchan_sheep" ] && [ "$serverchan_sheep" -eq "1" ] && [ ! -z "$starttime" ] && [ ! -z "$endtime" ] ;then - 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 - serverchan_send - else - serverchan_disturb - fi - else - serverchan_send - fi + #if [ ! -z "$serverchan_sheep" ] && [ "$serverchan_sheep" -eq "1" ] && [ ! -z "$starttime" ] && [ ! -z "$endtime" ] ;then + # 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 + # serverchan_send + # else + # serverchan_disturb + # fi + #else + # serverchan_send + #fi continue done diff --git a/package/ctcgfw/luci-app-serverchan/root/usr/bin/serverchan/wrtbwmon/readDB.awk b/package/ctcgfw/luci-app-serverchan/root/usr/bin/serverchan/wrtbwmon/readDB.awk new file mode 100755 index 0000000000..fe67e4ae8b --- /dev/null +++ b/package/ctcgfw/luci-app-serverchan/root/usr/bin/serverchan/wrtbwmon/readDB.awk @@ -0,0 +1,157 @@ +#!/usr/bin/awk + +function inInterfaces(host){ + return(interfaces ~ "(^| )"host"($| )") +} + +function newRule(arp_ip, + ipt_cmd){ + # checking for existing rules shouldn't be necessary if newRule is + # always called after db is read, arp table is read, and existing + # iptables rules are read. + ipt_cmd="iptables -t mangle -j RETURN -s " arp_ip + system(ipt_cmd " -C RRDIPT_FORWARD 2>/dev/null || " ipt_cmd " -A RRDIPT_FORWARD") + ipt_cmd="iptables -t mangle -j RETURN -d " arp_ip + system(ipt_cmd " -C RRDIPT_FORWARD 2>/dev/null || " ipt_cmd " -A RRDIPT_FORWARD") +} + +function total(i){ + return(bw[i "/in"] + bw[i "/out"]) +} + +function date( cmd, d){ + cmd="date +%d-%m-%Y_%H:%M:%S" + cmd | getline d + close(cmd) + #!@todo could start a process with "while true; do date ...; done" + return(d) +} + +BEGIN { + od="" + fid=1 + debug=0 + rrd=0 +} + +/^#/ { # get DB filename + FS="," + dbFile=FILENAME + next +} + +# data from database; first file +FNR==NR { #!@todo this doesn't help if the DB file is empty. + if($2 == "NA") + #!@todo could get interface IP here + n=$1 + else + n=$2 + + hosts[n] = "" # add this host/interface to hosts + mac[n] = $1 + ip[n] = $2 + inter[n] = $3 + bw[n "/in"] = $4 + bw[n "/out"] = $5 + firstDate[n] = $7 + lastDate[n] = $8 + next +} + +# not triggered on the first file +FNR==1 { + FS=" " + fid++ #!@todo use fid for all files; may be problematic for empty files + next +} + +# arp: ip hw flags hw_addr mask device +fid==2 { + #!@todo regex match IPs and MACs for sanity + arp_ip = $1 + arp_flags = $3 + arp_mac = $4 + arp_dev = $6 + if(arp_flags != "0x0" && !(arp_ip in ip)){ + if(debug) + print "new host:", arp_ip, arp_flags > "/dev/stderr" + hosts[arp_ip] = "" + mac[arp_ip] = arp_mac + ip[arp_ip] = arp_ip + inter[arp_ip] = arp_dev + bw[arp_ip "/in"] = bw[arp_ip "/out"] = 0 + firstDate[arp_ip] = lastDate[arp_ip] = date() + } + next +} + +#!@todo could use mangle chain totals or tailing "unnact" rules to +# account for data for new hosts from their first presence on the +# network to rule creation. The "unnact" rules would have to be +# maintained at the end of the list, and new rules would be inserted +# at the top. + +# skip line +# read the chain name and deal with the data accordingly +fid==3 && $1 == "Chain"{ + rrd=$2 ~ /RRDIPT_.*/ + next +} + +fid==3 && rrd && (NF < 9 || $1=="pkts"){ next } + +fid==3 && rrd { # iptables input + if($6 != "*"){ + m=$6 + n=m "/out" + } else if($7 != "*"){ + m=$7 + n=m "/in" + } else if($8 != "0.0.0.0/0"){ + m=$8 + n=m "/out" + } else { # $9 != "0.0.0.0/0" + m=$9 + n=m "/in" + } + + # remove host from array; any hosts left in array at END get new + # iptables rules + + #!@todo this deletes a host if any rule exists; if only one + # directional rule is removed, this will not remedy the situation + delete hosts[m] + + if($2 > 0){ # counted some bytes + if(mode == "diff" || mode == "noUpdate") + print n, $2 + if(mode!="noUpdate"){ + if(inInterfaces(m)){ # if label is an interface + if(!(m in mac)){ # if label was not in db (also not in + # arp table, but interfaces won't be + # there anyway) + firstDate[m] = date() + mac[m] = inter[m] = m + ip[m] = "NA" + bw[m "/in"]=bw[m "/out"]= 0 + } + } + bw[n]+=$2 + lastDate[m] = date() + } + } +} + +END { + if(mode=="noUpdate") exit + close(dbFile) + system("rm -f " dbFile) + print "#mac,ip,iface,in,out,total,first_date,last_date" > dbFile + OFS="," + for(i in mac) + print mac[i], ip[i], inter[i], bw[i "/in"], bw[i "/out"], total(i), firstDate[i], lastDate[i] > dbFile + close(dbFile) + # for hosts without rules + for(host in hosts) if(!inInterfaces(host)) newRule(host) +} diff --git a/package/ctcgfw/luci-app-serverchan/root/usr/bin/serverchan/wrtbwmon/wrtbwmon b/package/ctcgfw/luci-app-serverchan/root/usr/bin/serverchan/wrtbwmon/wrtbwmon new file mode 100755 index 0000000000..e373d54dc1 --- /dev/null +++ b/package/ctcgfw/luci-app-serverchan/root/usr/bin/serverchan/wrtbwmon/wrtbwmon @@ -0,0 +1,302 @@ +#!/bin/sh +# +# wrtbwmon: traffic logging tool for routers +# +# Peter Bailey (peter.eldridge.bailey+wrtbwmon AT gmail.com) +# +# Based on work by: +# Emmanuel Brucy (e.brucy AT qut.edu.au) +# Fredrik Erlandsson (erlis AT linux.nu) +# twist - http://wiki.openwrt.org/RrdTrafficWatch +# 提取自 luci-app-wrtbwmon + +trap "rm -f /tmp/serverchan/*_$$.tmp; kill $$" INT +binDir=/usr/bin/serverchan/wrtbwmon +dataDir=/tmp/serverchan +lockDir=/tmp/serverchan/wrtbwmon.lock +pidFile=$lockDir/pid +networkFuncs=/lib/functions/network.sh +uci=`which uci 2>/dev/null` +nslookup=`which nslookup 2>/dev/null` +nvram=`which nvram 2>/dev/null` + +chains='INPUT OUTPUT FORWARD' +DEBUG= +interfaces='eth0 tun0' # in addition to detected WAN +DB=$2 +mode= + +# DNS server for reverse lookups provided in "DNS". +# don't perform reverse DNS lookups by default +DO_RDNS=${DNS-} + +header="#mac,ip,iface,in,out,total,first_date,last_date" + +createDbIfMissing() +{ + [ ! -f "$DB" ] && echo $header > "$DB" +} + +checkDbArg() +{ + [ -z "$DB" ] && echo "ERROR: Missing argument 2 (database file)" && exit 1 +} + +checkDB() +{ + [ ! -f "$DB" ] && echo "ERROR: $DB does not exist" && exit 1 + [ ! -w "$DB" ] && echo "ERROR: $DB is not writable" && exit 1 +} + +checkWAN() +{ + [ -z "$wan" ] && echo "Warning: failed to detect WAN interface." +} + +lookup() +{ + MAC=$1 + IP=$2 + userDB=$3 + for USERSFILE in $userDB /tmp/serverchan/dhcp.leases /tmp/serverchan/dnsmasq.conf /etc/dnsmasq.conf /etc/hosts; do + [ -e "$USERSFILE" ] || continue + case $USERSFILE in + /tmp/serverchan/dhcp.leases ) + USER=$(grep -i "$MAC" $USERSFILE | cut -f4 -s -d' ') + ;; + /etc/hosts ) + USER=$(grep "^$IP " $USERSFILE | cut -f2 -s -d' ') + ;; + * ) + USER=$(grep -i "$MAC" "$USERSFILE" | cut -f2 -s -d,) + ;; + esac + [ "$USER" = "*" ] && USER= + [ -n "$USER" ] && break + done + if [ -n "$DO_RDNS" -a -z "$USER" -a "$IP" != "NA" -a -n "$nslookup" ]; then + USER=`$nslookup $IP $DNS | awk '!/server can/{if($4){print $4; exit}}' | sed -re 's/[.]$//'` + fi + [ -z "$USER" ] && USER=${MAC} + echo $USER +} + +detectIF() +{ + if [ -f "$networkFuncs" ]; then + IF=`. $networkFuncs; network_get_device netdev $1; echo $netdev` + [ -n "$IF" ] && echo $IF && return + fi + + if [ -n "$uci" -a -x "$uci" ]; then + IF=`$uci get network.${1}.ifname 2>/dev/null` + [ $? -eq 0 -a -n "$IF" ] && echo $IF && return + fi + + if [ -n "$nvram" -a -x "$nvram" ]; then + IF=`$nvram get ${1}_ifname 2>/dev/null` + [ $? -eq 0 -a -n "$IF" ] && echo $IF && return + fi +} + +detectLAN() +{ + [ -e /sys/class/net/br-lan ] && echo br-lan && return + lan=$(detectIF lan) + [ -n "$lan" ] && echo $lan && return +} + +detectWAN() +{ + [ -n "$WAN_IF" ] && echo $WAN_IF && return + wan=$(detectIF wan) + [ -n "$wan" ] && echo $wan && return + wan=$(ip route show 2>/dev/null | grep default | sed -re '/^default/ s/default.*dev +([^ ]+).*/\1/') + [ -n "$wan" ] && echo $wan && return + [ -f "$networkFuncs" ] && wan=$(. $networkFuncs; network_find_wan wan; echo $wan) + [ -n "$wan" ] && echo $wan && return +} + +lock() +{ + attempts=0 + while [ $attempts -lt 10 ]; do + mkdir $lockDir 2>/dev/null && break + attempts=$((attempts+1)) + pid=`cat $pidFile 2>/dev/null` + if [ -n "$pid" ]; then + if [ -d "/proc/$pid" ]; then + [ -n "$DEBUG" ] && echo "WARNING: Lockfile detected but process $(cat $pidFile) does not exist !" + rm -rf $lockDir + else + sleep 1 + fi + fi + done + mkdir $lockDir 2>/dev/null + echo $$ > $pidFile + [ -n "$DEBUG" ] && echo $$ "got lock after $attempts attempts" + trap '' INT +} + +unlock() +{ + rm -rf $lockDir + [ -n "$DEBUG" ] && echo $$ "released lock" + trap "rm -f /tmp/serverchan/*_$$.tmp; kill $$" INT +} + +# chain +newChain() +{ + chain=$1 + # Create the RRDIPT_$chain chain (it doesn't matter if it already exists). + iptables -t mangle -N RRDIPT_$chain 2> /dev/null + + # Add the RRDIPT_$chain CHAIN to the $chain chain if not present + iptables -t mangle -C $chain -j RRDIPT_$chain 2>/dev/null + if [ $? -ne 0 ]; then + [ -n "$DEBUG" ] && echo "DEBUG: iptables chain misplaced, recreating it..." + iptables -t mangle -I $chain -j RRDIPT_$chain + fi +} + +# chain tun +newRuleIF() +{ + chain=$1 + IF=$2 + + #!@todo test + if [ "$chain" = "OUTPUT" ]; then + cmd="iptables -t mangle -o $IF -j RETURN" + eval $cmd " -C RRDIPT_$chain 2>/dev/null" || eval $cmd " -A RRDIPT_$chain" + elif [ "$chain" = "INPUT" ]; then + cmd="iptables -t mangle -i $IF -j RETURN" + eval $cmd " -C RRDIPT_$chain 2>/dev/null" || eval $cmd " -A RRDIPT_$chain" + fi +} + +update() +{ + #!@todo could let readDB.awk handle this; that would place header + #!info in fewer places + createDbIfMissing + + checkDB + checkWAN + + > /tmp/serverchan/iptables_$$.tmp + lock + # only zero our own chains + for chain in $chains; do + iptables -nvxL RRDIPT_$chain -t mangle -Z >> /tmp/serverchan/iptables_$$.tmp + done + # the iptables and readDB commands have to be separate. Otherwise, + # they will fight over iptables locks + awk -v mode="$mode" -v interfaces=\""$interfaces"\" -f $binDir/readDB.awk \ + $DB \ + /proc/net/arp \ + /tmp/serverchan/iptables_$$.tmp + unlock +} + +############################################################ + +case $1 in + "dump" ) + checkDbArg + lock + tr ',' '\t' < "$DB" + unlock + ;; + + "update" ) + checkDbArg + wan=$(detectWAN) + interfaces="$interfaces $wan" + update + rm -f /tmp/serverchan/*_$$.tmp + exit + ;; + + "publish" ) + checkDbArg + [ -z "$3" ] && echo "ERROR: Missing argument 3 (output html file)" && exit 1 + + # sort DB + lock + + # busybox sort truncates numbers to 32 bits + grep -v '^#' $DB | awk -F, '{OFS=","; a=sprintf("%f",$4/1e6); $4=""; print a,$0}' | tr -s ',' | sort -rn | awk -F, '{OFS=",";$1=sprintf("%f",$1*1e6);print}' > /tmp/serverchan/sorted_$$.tmp + + # create HTML page + rm -f $3.tmp + cp $dataDir/usage.htm1 $3.tmp + + #!@todo fix publishing + while IFS=, read PEAKUSAGE_IN MAC IP IFACE PEAKUSAGE_OUT TOTAL FIRSTSEEN LASTSEEN + do + echo " +new Array(\"$(lookup $MAC $IP $4)\",\"$MAC\",\"$IP\", +$PEAKUSAGE_IN,$PEAKUSAGE_OUT,$TOTAL,\"$FIRSTSEEN\",\"$LASTSEEN\")," >> $3.tmp + done < /tmp/serverchan/sorted_$$.tmp + echo "0);" >> $3.tmp + + sed "s/(date)/`date`/" < $dataDir/usage.htm2 >> $3.tmp + mv $3.tmp $3 + + unlock + + #Free some memory + rm -f /tmp/serverchan/*_$$.tmp + ;; + + "setup" ) + checkDbArg + [ -w "$DB" ] && echo "Warning: using existing $DB" + createDbIfMissing + + for chain in $chains; do + newChain $chain + done + + #lan=$(detectLAN) + wan=$(detectWAN) + checkWAN + interfaces="$interfaces $wan" + + # track local data + for chain in INPUT OUTPUT; do + for interface in $interfaces; do + [ -n "$interface" ] && [ -e "/sys/class/net/$interface" ] && newRuleIF $chain $interface + done + done + + # this will add rules for hosts in arp table + update + + rm -f /tmp/serverchan/*_$$.tmp + ;; + + "remove" ) + iptables-save | grep -v RRDIPT | iptables-restore + rm -rf "$lockDir" + ;; + + *) + echo \ +"Usage: $0 {setup|update|publish|remove} [options...] +Options: + $0 setup database_file + $0 update database_file + $0 publish database_file path_of_html_report [user_file] +Examples: + $0 setup /tmp/serverchan/usage.db + $0 update /tmp/serverchan/usage.db + $0 publish /tmp/serverchan/usage.db /www/user/usage.htm /jffs/users.txt + $0 remove +Note: [user_file] is an optional file to match users with MAC addresses. + Its format is \"00:MA:CA:DD:RE:SS,username\", with one entry per line." + ;; +esac