Files
yakpanel-core/class/push/panel_push.py

359 lines
13 KiB
Python
Raw Normal View History

2026-04-07 02:04:22 +05:30
#coding: utf-8
# +-------------------------------------------------------------------
# | YakPanel
# +-------------------------------------------------------------------
# | Copyright (c) 2015-2020 YakPanel(https://www.yakpanel.com) All rights reserved.
# +-------------------------------------------------------------------
# | Author: 沐落 <cjx@yakpanel.com>
# | Author: lx
# +-------------------------------------------------------------------
import sys,os,time,psutil,re
panelPath = "/www/server/panel"
os.chdir(panelPath)
sys.path.insert(0, "class/")
import public,time,panelPush,public
try:
from YakPanel import cache
except :
from cachelib import SimpleCache
cache = SimpleCache()
class panel_push:
__push = None
pids = None
def __init__(self):
self.__push = panelPush.panelPush()
#-----------------------------------------------------------start 添加推送 ------------------------------------------------------
def get_version_info(self,get):
"""
获取版本信息
"""
data = {}
data['ps'] = ''
data['version'] = '1.2'
data['date'] = '2022-09-20'
data['author'] = 'YakPanel'
data['help'] = 'https://www.yakpanel.com/forum'
return data
#名取PID
def getPid(self,pname):
try:
if not self.pids: self.pids = psutil.pids()
for pid in self.pids:
if psutil.Process(pid).name() == pname: return True
return False
except: return True
#检测指定进程是否存活
def checkProcess(self,pid):
try:
if not self.pids: self.pids = psutil.pids()
if int(pid) in self.pids: return True
return False
except:
return False
#检查是否启动
def check_run(self,name):
if name == "php-fpm":
status = False
base_path = "/www/server/php"
if not os.path.exists(base_path):
return status
for p in os.listdir(base_path):
pid_file = os.path.join(base_path, p, "var/run/php-fpm.pid")
if os.path.exists(pid_file):
php_pid = int(public.readFile(pid_file))
status = self.checkProcess(php_pid)
if status:
return status
return status
elif name == 'nginx':
status = False
if os.path.exists('/etc/init.d/nginx'):
pidf = '/www/server/nginx/logs/nginx.pid'
if os.path.exists(pidf):
try:
pid = public.readFile(pidf)
status = self.checkProcess(pid)
except:
pass
return status
elif name == 'apache':
status = False
if os.path.exists('/etc/init.d/httpd'):
pidf = '/www/server/apache/logs/httpd.pid'
if os.path.exists(pidf):
pid = public.readFile(pidf)
status = self.checkProcess(pid)
return status
elif name == 'mysql':
res = public.ExecShell("service mysqld status")
if res and not re.search(r"not\s+running", res[0]):
return True
return False
elif name == 'tomcat':
status = False
if os.path.exists('/www/server/tomcat/logs/catalina-daemon.pid'):
if self.getPid('jsvc'): status = True
if not status:
if self.getPid('java'): status = True
return status
elif name == 'pure-ftpd':
pidf = '/var/run/pure-ftpd.pid'
status = False
if os.path.exists(pidf):
pid = public.readFile(pidf)
status = self.checkProcess(pid)
return status
elif name == 'redis':
status = False
pidf = '/www/server/redis/redis.pid'
if os.path.exists(pidf):
pid = public.readFile(pidf)
status = self.checkProcess(pid)
return status
elif name == 'memcached':
status = False
pidf = '/var/run/memcached.pid'
if os.path.exists(pidf):
pid = public.readFile(pidf)
status = self.checkProcess(pid)
return status
return True
def get_server_status(self, server_name):
status = self.check_run(server_name)
if status:
return 1
return 0
"""
@获取推送模块配置
"""
def get_module_config(self,get):
data = []
item = self.__push.format_push_data(push = ["mail",'dingding','weixin',"feishu"],project = 'ssl',type = 'ssl')
item['cycle'] = 30
item['title'] = 'SSL到期提醒'
item['helps'] = ['SSL到期提醒一天只发送一次','证书夹内【剩余天数不足30天】的所有证书.']
data.append(item)
item = self.__push.format_push_data(push = ["mail",'dingding','weixin',"feishu"],project = 'endtime',type = 'endtime')
item['cycle'] = 5
item['title'] = '专业版/企业版到期提醒'
item['helps'] = ['']
data.append(item)
services = ['nginx','apache',"pure-ftpd",'mysql','php-fpm','memcached','redis']
channels = ['mail', 'dingding','weixin','sms',"feishu"]
for x in services:
item = {}
item['project'] = x
item['title'] = '{}服务停止通知'.format(x)
if x == 'other':
item['title'] = '自定义服务停止通知'
else:
ser_name = self.__get_service_name(x)
if self.get_server_status(ser_name) == -1: continue
item['type'] = 'services'
item['keys'] = []
item['interval'] = 300
for x in ['stop']:
item['keys'].append({'key':x,'val':'停止'})
item['push'] = channels
item['helps'] = ['部分服务停止可能会造成业务中断.','短信推送需提前购买,如需帮助请联系 [<a href="https://www.yakpanel.com/forum" target="_blank" class="btlink">YakPanel 社区</a>]']
data.append(item)
import json
public.writeFile('data/push/config/panel_push.json',json.dumps(data))
return data
def get_push_cycle(self,data):
"""
@获取执行周期
"""
result = {}
for skey in data:
result[skey] = data[skey]
m_cycle =[]
m_type = data[skey]['type']
if m_type in ['endtime','ssl']:
m_cycle.append('剩余{}天时每天1次'.format(data[skey]['cycle']))
elif m_type in ['services']:
m_cycle.append('服务停止时,每{}秒1次'.format(data[skey]['interval']))
if len(m_cycle) > 0:
result[skey]['m_cycle'] = ''.join(m_cycle)
return result
#-----------------------------------------------------------end 添加推送 ------------------------------------------------------
"""
@获取服务真实名称
"""
def __get_service_name(self,name):
slist = {"FTP服务端":'pure-ftpd'}
if name in slist: name = slist[name]
return name
"""
@获取推送栏目
"""
def get_total(self):
return True;
def get_push_data(self,data,total):
if data['type'] == 'services':
ser_name = data['project']
ser_name = self.__get_service_name(ser_name)
status = self.get_server_status(ser_name)
if status > 0:
return public.returnMsg(False, public.lang("状态正常,跳过."))
else:
if status == 0:
return self.__get_service_result(data)
return public.returnMsg(False, public.lang("服务未安装,跳过."))
elif data['type'] in ['ssl']:
if time.time() < data['index'] + 86400:
return public.returnMsg(False, public.lang("一天推送一次,跳过."))
import panelSSL
ssl = panelSSL.panelSSL()
clist = []
for x in ssl.GetCertList(None):
timeArray = time.strptime(x['notAfter'], "%Y-%m-%d")
endtime = time.mktime(timeArray)
day = int((endtime - time.time()) / 86400)
if day > data['cycle']: continue
clist.append(x)
return self.__get_ssl_result(data,clist)
elif data['type'] in ['endtime']:
if time.time() < data['index'] + 86400:
return public.returnMsg(False, public.lang("一天推送一次,跳过."))
from pluginAuth import Plugin
softs = Plugin(False).get_plugin_list(True)
if softs['pro'] == 0: return public.returnMsg(False, public.lang("永久专业版,跳过."))
if softs['ltd'] == -2 and softs['pro'] == -2:
pass
else:
pro_data = {}
if softs['ltd'] > 0:
pro_data['endtime'] = softs['ltd']
pro_data['name'] = "Linux企业版"
pro_data['affect'] = '全部企业版插件'
elif softs['pro'] > 0:
pro_data['endtime'] = softs['pro']
pro_data['name'] = "Linux专业版"
pro_data['affect'] = '全部专业版插件'
pro_data['day'] = int((pro_data['endtime'] - time.time()) / 86400)
if pro_data['day'] <= data['cycle']:
return self.__get_ltd_result(data,pro_data)
return public.returnMsg(False, public.lang("未达到阈值,跳过."))
"""
@企业版到期提醒
"""
def __get_ltd_result(self,data,pro_data):
result = {'index':time.time()}
for m_module in data['module'].split(','):
result[m_module] = self.__push.format_msg_data()
newline = ""
if m_module in ['dingding','weixin',"feishu","mail"]:
if m_module in ["mail"]:
newline="<br/>"
result[m_module]["title"] = "YakPanel 业务到期提醒"
else:
newline = "\n\n"
result[m_module]['msg'] = "".join((
"#### YakPanel 业务到期提醒"+newline,
">服务器 "+ public.GetLocalIp() + newline,
">剩余天数:"+ str(pro_data['day'] + 1) +""+newline,
">到期产品:"+ pro_data['name'] +newline,
">到期时间:"+ public.format_date(times =pro_data['endtime']) +newline,
">影响业务:"+ pro_data['affect'] +newline,
">通知时间:" + public.format_date() + newline))
return result
"""
@ssl到期返回
"""
def __get_ssl_result(self,data,clist):
if len(clist) == 0:
return public.returnMsg(False, public.lang("未找到到期证书,跳过."))
result = {'index':time.time() }
for m_module in data['module'].split(','):
result[m_module] = self.__push.format_msg_data()
newline = ""
if m_module in ['dingding','weixin',"feishu","mail"]:
if m_module in ["mail"]:
newline="<br/>"
result[m_module]["title"] = "YakPanel SSL到期提醒"
else:
newline = "\n\n"
p_msg = "";
for x in clist: p_msg+= " 到期:{} 域名:{}".format(x['notAfter'],x['subject']) + newline
result[m_module]['msg'] ="".join((
"#### YakPanel SSL到期提醒" + newline,
">服务器 "+ public.GetLocalIp() +newline,
">检测时间:" + public.format_date() +newline,
">About to expire: "+ str(len(clist)) +" "+newline,
p_msg))
return result
"""
@服务停止返回
"""
def __get_service_result(self,data):
s_idx = int(time.time())
if s_idx < data['index'] + data['interval']:
return public.returnMsg(False, public.lang("The interval is not reached, skip."))
result = {'index':s_idx}
for m_module in data['module'].split(','):
result[m_module] = self.__push.format_msg_data()
newline = ""
if m_module in ['dingding','weixin',"feishu","mail"]:
if m_module in ["mail"]:
newline="<br/>"
result[m_module]["title"] = "堡塔服务停止告警"
else:
newline = "\n\n"
result[m_module]['msg'] = "".join((
"#### 堡塔服务停止告警" + newline,
">服务器 "+ public.GetLocalIp() +newline + " ",
">Type of service: "+ data["project"] +newline + " ",
">Service state: 已停止"+newline+" ",
">检测时间:"+ public.format_date()))
elif m_module in ['sms']:
result[m_module]['sm_type'] = 'servcies'
result[m_module]['sm_args'] = { 'name':'{}'.format(public.GetConfigValue('title')), 'product':data["project"],'product1':data["project"]}
return result