宝塔面板v6.X破解思路&过程&一键安装SHELL

宝塔面板v6.X破解思路&过程&一键安装SHELL

UPDATE: 201811.12

测试正式版v6.4可用,其中宝塔数据同步工具无法使用,我现在也不知道怎么改,日后再说吧~

引子

不得不吐槽一下宝塔的定价策略,作为非专业向面板定价,单IP永久授权原价1388。20IP永久授权原价6588,折后4388,折算下来每台200出头,但十分不方便,团出来后只能由“团长”代绑定IP,修改IP复杂。作为经常换VPS玩儿的折腾党来说,入正之后,首先单IP不能完全实现需求,其次改绑IP需要频繁联系“团长”,次数多了人家肯定不愿意。

看这个IP策略,宝塔在向专业性面板(供给公司)方向转型,在目前国内环境下这个过程肯定会比较漫长,但不得不说宝塔面板是一款非常不错的国产面版,之前还有人跟我争论说

你都用Linux了还不手敲代码,用什么可视化管理面板

首先,作为爱折腾的搞机党,我不想把精力放在环境配置等一系列问题上。其次,那你去手工编译环境啊..都在用命令行面板,命令行控制面板不也是控制面板吗?

不过是保守派和维新派的争论罢了,历史自然会做出评判。

总而言之,宝塔面板确实对运维效率的提高做出了很大的贡献,在稳定的工作环境下or宝塔提供给个人开发者比较优惠的定价策略后,一定会付费支持他们。

破解思路

破解思路是由 @king51提出并实现的,该dalao盯着宝塔不放,首次放出最完美的5.9专业版破解思路,导致宝塔官方第一次感受到了被破解的压力,将付费插件全部改由云端获取。然而...大佬还是找出了漏洞并且进行了实践,依旧完美破解。该思路其实对比5.9版,更简洁,但想到想到并实现这个思路比较难

破解思路:

  1. 修改插件过期时间
    破解时间

/class/panelPlugin.py第242行后添加两行代码:

        for softInfo in softList['list']:
        softInfo['endtime'] = 0

该段代码将插件过期时间设置为无限,就可以从云端获取插件列表并下载了

  1. 本地破解插件验证
    插件下载下来后其实是只有插件的运行环境等文件的,功能代码文件 Plugin_main.py 内部存在验证,会提示”您未购买或授权已到期!“ 例如 宝塔任务管理器 插件 的 task_manager_main.py 文件代码:

本地破解
需要从正版已安装插件中替换该文件,并做一些修改. 正版插件中的代码开头如下:
本体破解
注意上图红框内的表名,和未破解完成的插件表名不同,需要做一个手动修改:
图
保存并上传后,就可以使用插件了!

备注: 上述修改仅为示例,部分插件内部还存在其他验证,在我做的SHELL脚本中已全部成功修改并通过测试。

SHELL脚本

伟大的哲学家 沃兹基梭德 曾经说过

要想Shell跑的好,见程序就写不能少

Shell Project: https://github.com/madlifer/btpanelv6.1_crack

使用方法

wget -O crack.sh https://git.io/fxiDS && bash crack.sh

源代码

#!/bin/bash
Green_font="\033[32m" && Yellow_font="\033[33m" && Red_font="\033[31m" && Font_suffix="\033[0m"
Info="${Green_font}[Info]${Font_suffix}"
Error="${Red_font}[Error]${Font_suffix}"
Important="${Red_font}[选择前须知:]${Font_suffix}"
PANEL_DIR=/www/server/panel
PLUGIN_RETURN=在面板安装插件完成之后,从下表选择你要破解的插件:
MAIN_RETURN=${Red_font}[宝塔面板v6.1.2破解脚本]${Font_suffix}

git_check(){
    GIT_V=`git --version | grep -q version`
if [ $? = 0 ]; then
    echo -e "${Info} Git已安装,开始下一步操作!"
else
    echo -e "${Error} 未安装Git,开始安装Git!"
    check_system
    install_git
fi
}

check_system() {
    if grep -Eqii "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then
        DISTRO='CentOS'
        PM='yum'
    elif grep -Eqi "Red Hat Enterprise Linux Server" /etc/issue || grep -Eq "Red Hat Enterprise Linux Server" /etc/*-release; then
        DISTRO='RHEL'
        PM='yum'
    elif grep -Eqi "Aliyun" /etc/issue || grep -Eq "Aliyun" /etc/*-release; then
        DISTRO='Aliyun'
        PM='yum'
    elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then
        DISTRO='Debian'
        PM='apt'
    elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then
        DISTRO='Ubuntu'
        PM='sudo'
    else
        DISTRO='unknow'
    fi
}

install_git(){
    case ${PM} in
        yum)
            yum -y install sudo
            yum -y update 
            sudo yum -y install git
        ;;
        apt)
            apt -y install sudo
            sudo apt -y update
            sudo apt-get -y install git
        ;;
        sudo)
            sudo apt -y update
            sudo apt-get -y install git
        ;;
        *)
            echo -e "${Error} 不支持您的系统 !"
        ;;
    esac
    echo -e "${Info} Git安装完成 !"
}

install_bt_panel_pro(){
    curl http://download.bt.cn/install/update6.sh|bash
    echo -e "${Info} 宝塔专业版安装完成,正在进行下一步操作!"
}

get_crack_file(){
    git clone https://github.com/madlifer/btpanelv6.1_crack.git
}

copy_class_file(){
    cp -pf /root/btpanelv6.1_crack/panelPlugin.py ${PANEL_DIR}/class/panelPlugin.py
    echo -e "${Info} 复制Class文件完成,正在进行下一步操作!"
}

restart_btpanel(){
    /etc/init.d/bt restart
    echo -e "${Info} 重启宝塔面板完成,正在进行下一步操作!"
}

install_tamper_proof(){
    cp -pf /root/btpanelv6.1_crack/tamper_proof_main.py ${PANEL_DIR}/plugin/tamper_proof/tamper_proof_main.py
    PLUGIN_RETURN=${Red_font}[网站防篡改程序]${Font_suffix}破解完成,继续破解或返回主菜单: && plugin_choose
}

install_btwaf_httpd(){
    cp -pf /root/btpanelv6.1_crack/btwaf_httpd_main.py ${PANEL_DIR}/plugin/btwaf_httpd/btwaf_httpd_main.py
    PLUGIN_RETURN=${Red_font}[Apache防火墙]${Font_suffix}破解完成,继续破解或返回主菜单: && plugin_choose
}

install_total_main(){
    cp -pf /root/btpanelv6.1_crack/total_main.py ${PANEL_DIR}/plugin/total/total_main.py
    PLUGIN_RETURN=${Red_font}[网站监控报表]${Font_suffix}破解完成,继续破解或返回主菜单: && plugin_choose
}

install_btwaf(){
    cp -pf /root/btpanelv6.1_crack/btwaf_main.py ${PANEL_DIR}/plugin/btwaf/btwaf_main.py
    PLUGIN_RETURN=${Red_font}[Nginx防火墙]${Font_suffix}破解完成,继续破解或返回主菜单: && plugin_choose
}

install_load_leveling(){
    cp -pf /root/btpanelv6.1_crack/load_leveling_main.py ${PANEL_DIR}/plugin/load_leveling/load_leveling_main.py
    PLUGIN_RETURN=${Red_font}[宝塔负载均衡]${Font_suffix}破解完成,继续破解或返回主菜单: && plugin_choose
}

install_masterslave(){
    cp -pf /root/btpanelv6.1_crack/masterslave_main.py ${PANEL_DIR}/plugin/masterslave/masterslave_main.py
    PLUGIN_RETURN=${Red_font}[MYSQL主从复制]${Font_suffix}破解完成,继续破解或返回主菜单: && plugin_choose
}

install_task_manager(){
    cp -pf /root/btpanelv6.1_crack/task_manager_main.py ${PANEL_DIR}/plugin/task_manager/task_manager_main.py
    PLUGIN_RETURN=${Red_font}[任务管理器]${Font_suffix}破解完成,继续破解或返回主菜单: && plugin_choose
}

install_rsync(){
    cp -pf /root/btpanelv6.1_crack/rsync_main.py ${PANEL_DIR}/plugin/rsync/rsync_main.py
    PLUGIN_RETURN=${Red_font}[数据同步工具]${Font_suffix}破解完成,继续破解或返回主菜单: && plugin_choose
}

del_crack_file(){
    rm -rf /root/btpanelv6.1_crack
    MAIN_RETURN=${Red_font}[删除破解包]${Font_suffix}操作已完成。
}

setup(){
    git_check
    install_bt_panel_pro
    get_crack_file
    copy_class_file
    restart_btpanel
    MAIN_RETURN=${Red_font}[安装前准备]${Font_suffix}操作已完成。
    main
}

plugin_choose(){
clear
echo -e "${Green_font}
#====================================================
# ${Important} 必须先在面板成功安装插件才能进行破解。
#====================================================
# ${PLUGIN_RETURN}${Green_font}
#====================================================
#          1.网页防篡改程序
#          2.Apache防火墙
#          3.网站监控报表
#          4.Nginx防火墙
#          5.宝塔负载均衡
#          6.MYSQL主从复制
#          7.任务管理器
#          8.数据同步工具
#          9.返回主菜单
#====================================================
${Font_suffix}
${Font_suffix}"

read -p "输入数字以选择:" choose_function

while [[ ! "${choose_function}" =~ ^[1-9]$ ]]
    do
        echo -e "${Error} 无效输入"
        echo -e "${Info} 请重新选择" && read -p "输入数字以选择:" choose_function
    done

if [[ "${choose_function}" == "1" ]]; then
    install_tamper_proof
elif [[ "${choose_function}" == "2" ]]; then
    install_btwaf_httpd
elif [[ "${choose_function}" == "3" ]]; then
    install_total_main
elif [[ "${choose_function}" == "4" ]]; then
    install_btwaf
elif [[ "${choose_function}" == "5" ]]; then
    install_load_leveling
elif [[ "${choose_function}" == "6" ]]; then
    install_masterslave
elif [[ "${choose_function}" == "7" ]]; then
    install_task_manager
elif [[ "${choose_function}" == "8" ]]; then
    install_rsync
elif [[ "${choose_function}" == "9" ]]; then
    main
fi
}

main(){
clear
echo -e "${Green_font}
#=======================================
# Name:         bt-6.1-crack
# Project:      https://git.io/fxiwt
# requirement:  bt v6.1 free version
# Version:      0.0.1
# Author:       madlifer
# Thanks:       @king51
# Copyright:    https://madevo.net
#=======================================
${Font_suffix}"

echo -e "${MAIN_RETURN}"
echo -e "1.安装前准备\n2.进行安装\n3.删除破解包\n4.退出脚本"
read -p "输入数字以选择:" function

while [[ ! "${function}" =~ ^[1-4]$ ]]
    do
        echo -e "${Error} 无效输入"
        echo -e "${Info} 请重新选择" && read -p "输入数字以选择:" function
    done

if [[ "${function}" == "1" ]]; then
    setup
elif [[ "${function}" == "2" ]]; then
    plugin_choose
elif [[ "${function}" == "2" ]]; then
    del_crack_file
else
    clear
    exit 1
fi
}

main

评论

14 条

一念成风

宝塔6.4破解宝塔数据同步工具 2.3 会提示下方代码,请问应该怎么解决呢?
Traceback (most recent call last):
File "/www/server/panel/class/panelPlugin.py", line 1401, in a
plugin_main = __import__(get.name+'_main');
File "/usr/lib64/python2.7/site-packages/gevent/builtins.py", line 96, in __import__
result = _import(*args, **kwargs)
File "plugin/rsync/rsync_main.py", line 161
session['rsync'] = True
^
SyntaxError: invalid syntax

回复 ·

madlifer 作者

你好,我现在也不知道怎么解决,在研究中 emmmm.

回复 ·

快乐哈哈

这个我貌似解决了哦

回复 ·

快乐哈哈

#coding: utf-8
# +-------------------------------------------------------------------
# | 宝塔Linux面板
# +-------------------------------------------------------------------
# | Copyright (c) 2015-2019 宝塔软件(http://bt.cn) All rights reserved.
# +-------------------------------------------------------------------
# | Author: 黄文良
# +-------------------------------------------------------------------
import re, os, sys, time ,base64 ,json ,re ,public, db, crontab
sys.path.append("class/")
from panelAuth import panelAuth
from BTPanel import session

class rsync_main():
__bin = '/usr/bin/rsync'
rsyn_file = "/etc/rsyncd.conf"
lsync_file = "/etc/lsyncd.conf"
rsyn_path = '/www/server/panel/plugin/rsync'

def __init__(self):
s_dir = self.rsyn_path + '/sclient';
if not os.path.exists(s_dir): public.ExecShell("mkdir -p " + s_dir);
s_dir = self.rsyn_path + '/secrets';
if not os.path.exists(s_dir): public.ExecShell("mkdir -p " + s_dir);
s_file = self.rsyn_path + '/lsyncd.log'
if os.path.exists(s_file):
if os.path.getsize(s_file) * 1024 * 1024 > 1024: public.writeFile(s_file,public.GetNumLines(s_file,2000))

def get_logs(self,get):
import page
page = page.Page();
count = public.M('logs').where('type=?',(u'数据同步工具',)).count();
limit = 12;
info = {}
info['count'] = count
info['row'] = limit
info['p'] = 1
if hasattr(get,'p'):
info['p'] = int(get['p'])
info['uri'] = get
info['return_js'] = ''
if hasattr(get,'tojs'):
info['return_js'] = get.tojs
data = {}

data['page'] = page.GetPage(info,'1,2,3,4,5,8');
data['data'] = public.M('logs').where('type=?',(u'数据同步工具',)).order('id desc').limit(str(page.SHIFT)+','+str(page.ROW)).field('log,addtime').select();
return data;

def get_rsync_conf(self,get):
data = json.loads(public.readFile(self.rsyn_path + '/config.json'))
return data

def get_global_conf(self,get):
data = self.get_rsync_conf(None);
result = {}
result['modules'] = data['modules']
result['global'] = data['global']
result['open'] = (len(public.ExecShell("/etc/init.d/rsynd status|grep 'already running'")[0]) > 1) | False
return result;

def modify_global_conf(self,get):
data = self.get_rsync_conf(None);
if 'port' in get: data['global']['port'] = int(get.port)
if 'hosts_allow' in get: data['global']['hosts allow'] = " ".join(get.hosts_allow.split());
if 'timeout' in get: data['global']['timeout'] = int(get.timeout);
if 'max_connections' in get: data['global']['max connections'] = int(get.max_connections)
if 'dont_compress' in get: data['global']['dont compress'] = get.dont_compress
self.__write_conf(data);
self.__write_logs('修改rsync服务器全局配置');
return public.returnMsg(True,'设置成功!');

def get_secretkey(self,get):
module = self.get_module(get)
secretkey = self.__EncodeKey(module['name'], module['password'], module['port'])
return secretkey

def add_module(self,get):
if self.__check_path(get.path): return public.returnMsg(False,'不能同步系统关键目录');
if self.__check_module_name(get.mName): return public.returnMsg(False,'您输入的用户名已存在');
data = self.get_rsync_conf(None);
auth_pass = self.rsyn_path + '/secrets/' + get.mName + '.db';
module = {'name':get.mName,
'path':get.path,
'password':get.password,
'comment':get.comment,
'read only':'false',
'ignore errors':True,
'auth users':get.mName,
'secrets file':auth_pass,
'addtime':int(time.time())
}
data['modules'].insert(0,module)
self.__write_conf(data);
self.__write_logs('添加rsync接收帐户[' + get.mName + ']');
return public.returnMsg(True,'添加成功!');

def modify_module(self,get):
if self.__check_path(get.path): return public.returnMsg(False,'不能同步系统关键目录');
data = self.get_rsync_conf(None);
for i in range(len(data['modules'])):
if data['modules'][i]['name'] == get.mName:
data['modules'][i]['password'] = get.password;
data['modules'][i]['path'] = get.path;
data['modules'][i]['comment'] = get.comment;
self.__write_passwd(data['modules'][i]['name'], data['modules'][i]['auth users'], data['modules'][i]['password'],False)
self.__write_conf(data);
self.__write_logs('修改rsync接收帐户[' + get.mName + ']');
return public.returnMsg(True,'编辑成功!');
return public.returnMsg(False,'指定模块不存在!');

def remove_module(self,get):
data = self.get_rsync_conf(None);
for i in range(len(data['modules'])):
if data['modules'][i]['name'] == get.mName:
del(data['modules'][i])
self.__write_conf(data);
auth_pass = self.rsyn_path + '/secrets/' + get.mName + '.db';
if os.path.exists(auth_pass): os.remove(auth_pass);
self.__write_logs('删除rsync接收帐户[' + get.mName + ']');
return public.returnMsg(True,'删除成功!');
return public.returnMsg(False,'指定模块不存在!');

def get_module(self,get,name = None):
if get: name = get.mName;
data = self.get_rsync_conf(None);
for i in range(len(data['modules'])):
if data['modules'][i]['name'] == name:
data['modules'][i]['port'] = data['global']['port'];
return data['modules'][i]
return public.returnMsg(False,'指定模块不存在!');

def get_send_conf(self,get):
modc = self.__get_mod(get)
if not 'rsync' in session: return modc;
data = self.get_rsync_conf(None);
return data['client'];

def get_send_byname(self,get):
data = self.get_rsync_conf(None);
for i in range(len(data['client'])):
if data['client'][i]['name'] == get['mName']:
tmp = data['client'][i];
tmp['secret_key'] = self.__EncodeKey(tmp['name'], tmp['password'], tmp['rsync']['port'])
return tmp;
return public.returnMsg(False,'指定任务不存在!');

def __get_mod(self,get):
#filename = 'plugin/rsync/rsync_init.py';
#if os.path.exists(filename): os.remove(filename);
if 'rsync' in session: return public.returnMsg(True,'OK!');
params = {}
params['pid'] = '100000005';
result = panelAuth().send_cloud('check_plugin_status',params)
#try:
# if not result['status']:
# if 'rsync' in session: del(session['rsync'])
# return result;
# except: pass;
session['rsync'] = True
return result

def __EncodeKey(self, name, passwd, port):
data = json.dumps({'A': re.sub("(\d+\.){3,3}\d+_",'',name), 'B': passwd, 'C': port})
if sys.version_info[0] == 2:
return base64.b64encode(data)
result = base64.b64encode(data.encode('utf-8'))
if type(result) == bytes: result = result.decode('utf-8')
return str(result)

def __check_dst_port(self,ip,port,timeout = 3):
import socket
ok = True;
try:
s = socket.socket()
s.settimeout(timeout)
s.connect((ip,port))
s.close()
except:
ok = False;
return ok;

def add_ormodify_send(self,get):
if self.__check_path(get.path): return public.returnMsg(False,'不能同步系统关键目录');
get.delay = getattr(get,'delay','3');
get.model = getattr(get,'model','default.rsync');
get.to = getattr(get,'to','');
get.ip = getattr(get,'ip','');
get.delete = getattr(get,'delete','true');
get.realtime = getattr(get,'realtime',True);
get.ps = getattr(get,'ps','');
get.bwlimit = getattr(get,'bwlimit','1024');
get.compress = getattr(get,'compress','true');
get.archive = getattr(get,'archive','true');
get.verbose = getattr(get,'verbose','true');
get.index = getattr(get,'index','-1');

if int(get.delay) < 0: get.delay = '0';
if int(get.bwlimit) < 0: get.bwlimit = '0';

if type(get.realtime) != bool:
get.realtime = (get.realtime == 'true') | False;

if get.model == 'default.rsync':
try:
if sys.version_info[0] == 3:
server_conf = json.loads(base64.b64decode(get['secret_key']).decode('utf-8'))
else:
server_conf = json.loads(base64.b64decode(get['secret_key']))
except:
return public.returnMsg(False,'错误的接收密钥');

if not re.match("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", get.ip): return public.returnMsg(False,'请填写正确的IP地址!');
cron = json.loads(get.cron)
if not self.__check_dst_port(get.ip,int(server_conf['C'])):
return public.returnMsg(False,'无法连接['+get.ip+':'+ str(server_conf['C']) + '],请检查IP地址是否正确,若正确无误,请检查远程服务器的安全组及防火墙是否正确放行['+str(server_conf['C'])+']端口!');
else:
if get.path == get.to: return public.returnMsg(False,'不能同步两个相同的目录');
if not os.path.exists(get.to): public.ExecShell('mkdir -p ' + get.to);
server_conf = {'A':get.mName,'B':'','C':'873'}
cron = {}

if get.index == '-1':
if self.__check_client_name(server_conf['A']): return public.returnMsg(False,'已存在同名任务!');

if not os.path.exists(get.path): public.ExecShell('mkdir -p ' + get.path);
sclient = {
'model':get.model,
'name': server_conf['A'],
'ip':get.ip,
'password':server_conf['B'],
'path':get.path,
'to':get.to,
'exclude':[],
'delete':get.delete,
'realtime': get.realtime | False,
'delay':str(int(get.delay)),
'rsync':{
'bwlimit':str(int(get.bwlimit)),
'port': str(server_conf['C']),
'compress':get.compress,
'archive':get.archive,
'verbose':get.verbose
},
'ps':get.ps,
'cron':cron,
'update':time.time()
}

if get.model == 'default.rsync':
ef = self.rsyn_path + '/sclient/' + sclient['name'] + '_exclude'
if not os.path.exists(ef): public.writeFile(ef,'');
self.__write_lsync_pass(sclient['name'],sclient['password'],False)
self.__create_crond(sclient,get);

cmd_file = self.rsyn_path + '/sclient/' + sclient['name'] + '_cmd'
public.writeFile(cmd_file,self.__get_send_cmd(sclient))

data = self.get_rsync_conf(None);
n = True;
if get.index != '-1':
sclient['exclude'] = data['client'][int(get.index)]['exclude']
data['client'][int(get.index)] = sclient;
n = False;
if n: data['client'].insert(0,sclient)
self.__write_conf(data,True)
if n:
public.writeFile(self.rsyn_path + '/sclient/' + sclient['name'] + '_exec.log','');
self.__write_logs('添加同步任务[' + sclient['name'] + ']');
public.ExecShell("nohup bash " + cmd_file + " >> " + self.rsyn_path + "/sclient/"+sclient['name']+"_exec.log 2>&1 &");
return public.returnMsg(True,'添加成功!');
self.__write_logs('修改同步任务[' + sclient['name'] + ']');
return public.returnMsg(True,'修改成功!')

def get_rsync_logs(self,get):
if get.mName == 'lsyncd_logs':
path = self.rsyn_path + '/lsyncd.log';
else:
path = self.rsyn_path + '/sclient/' + get.mName + '_exec.log';
if not os.path.exists(path): public.writeFile(path,'');
return public.returnMsg(True,public.GetNumLines(path,2000));

def remove_rsync_logs(self,get):
if get.mName == 'lsyncd_logs':
path = self.rsyn_path + '/lsyncd.log';
self.__write_logs('清空实时同步日志');
else:
path = self.rsyn_path + '/sclient/' + get.mName + '_exec.log';
self.__write_logs('清空发送日志[' + get.mName + ']');
public.writeFile(path,'');

return public.returnMsg(True,'清除成功!');

def exec_cmd(self,get):
cmd_file = self.rsyn_path + '/sclient/' + get['mName'] + '_cmd'
sclient = self.get_send_byname(get)
public.writeFile(cmd_file,self.__get_send_cmd(sclient))

os.system('echo "【'+public.getDate()+'】" >> ' + self.rsyn_path + "/sclient/"+get.mName+"_exec.log")
public.ExecShell("nohup bash " + cmd_file + " >> " + self.rsyn_path + "/sclient/"+get.mName+"_exec.log 2>&1 &")
self.__write_logs('手动执行同步任务['+get['mName']+']');
return public.returnMsg(True,'同步指令已发送!');

def remove_send(self,get):
data = self.get_rsync_conf(None);
for i in range(len(data['client'])):
if data['client'][i]['name'] != get.mName: continue;
data['client'][i]['realtime'] = True
self.__create_crond(data['client'][i],get)
del(data['client'][i])
public.ExecShell("rm -f " + self.rsyn_path + '/sclient/' + get.mName + '_*')
self.__write_conf(data,True)
self.__write_logs('删除发送配置['+get['mName']+']');
break;
return public.returnMsg(True,'删除成功!');

def get_exclude(self,get):
data = self.get_rsync_conf(None);
for i in range(len(data['client'])):
if data['client'][i]['name'] == get['mName']: return data['client'][i]['exclude'];
return public.returnMsg(False,'指定任务不存在!');

def add_exclude(self,get):
data = self.get_rsync_conf(None);
for i in range(len(data['client'])):
if data['client'][i]['name'] != get['mName']: continue;
data['client'][i]['exclude'].insert(0, get.exclude)
self.__write_conf(data,True)
self.__write_logs('添加排除规则['+get.exclude+']到['+get['mName']+']');
break;
return public.returnMsg(True,'添加成功!');

def remove_exclude(self,get):
data = self.get_rsync_conf(None);
for i in range(len(data['client'])):
if data['client'][i]['name'] != get['mName']: continue;
data['client'][i]['exclude'].remove(get.exclude)
self.__write_conf(data,True)
self.__write_logs('从['+get['mName']+']删除排除规则['+get.exclude+']');
break;
return public.returnMsg(True,'删除成功!');

def rsync_service(self,get):
s_cmd = "/etc/init.d/rsynd " + get.state
public.ExecShell(s_cmd);
self.__check_port_appect(get);
self.__write_logs(s_cmd + '已执行');
return public.returnMsg(True,'操作成功!');

def __write_lsyncd(self,data):
lsyncd_conf = "settings {\n"
for k in data['settings'].keys():
if re.search("^\d+$",data['settings'][k]) or data['settings'][k] in ['true','false']:
lsyncd_conf += "\t" + k + ' = ' + data['settings'][k] + ',' + "\n"
else:
lsyncd_conf += "\t" + k + ' = "' + data['settings'][k] + '",' + "\n"
lsyncd_conf = lsyncd_conf[:-2] + "\n}\n";

for sclient in data['client']:
if sclient['model'] == 'default.rsync':
lsyncd_conf += self.__format_rsync(sclient);
self.__write_lsync_pass(sclient['name'],sclient['password'])
else:
lsyncd_conf += self.__format_local(sclient);
public.writeFile(self.lsync_file,lsyncd_conf)
if os.path.exists('/etc/init.d/lsyncd'):
public.ExecShell("/etc/init.d/lsyncd restart");
else:
public.ExecShell("systemctl restart lsyncd");
return True

def __format_local(self,sclient):
excludes = self.__format_exclude(sclient['exclude'])
sync = '''
sync {
default.direct,
source = "%s",
target = "%s",
delay = 1,
maxProcesses = 2,
exclude = {%s}
}
''' % (sclient['path'],sclient['to'],excludes)
return sync

def __format_exclude(self,exclude):
excludes = '"' + '","'.join(exclude) + '"';
if excludes == '""':
excludes = '".user.ini"';
else:
excludes += ',".user.ini"';
return excludes

def __format_rsync(self,sclient):
password_file = self.rsyn_path + '/sclient/' + sclient['name'] + '_pass'
excludes = self.__format_exclude(sclient['exclude'])
sync = '''
sync {
%s,
source = "%s",
target = "%s@%s::%s",
delete = %s,
exclude = {%s},
delay = %s,
init = false,
rsync = {
binary = "%s",
archive = %s,
compress = %s,
verbose = %s,
password_file = "%s",
_extra = {"--bwlimit=%s","--port=%s"}
}
}''' % (sclient['model'],
sclient['path'],
sclient['name'],
sclient['ip'],
sclient['name'],
sclient['delete'],
excludes,
sclient['delay'],
self.__bin,
sclient['rsync']["archive"],
sclient['rsync']["compress"],
sclient['rsync']["verbose"],
password_file,
sclient['rsync']["bwlimit"],
sclient['rsync']["port"]
)
return sync;

def __create_crond(self,sclient,get={}):
name = '%s_%s' % (sclient['ip'], sclient['name'])
cron_info = public.M('crontab').where("name=?", ('R'+name,)).field('id').find()
if cron_info:
get['id'] = cron_info['id']
self.__delCronExec(get)

cron_info = public.M('crontab').where("name=?", ('定时数据同步任务【' + sclient['name'] + '】',)).field('id').find()
if cron_info:
get['id'] = cron_info['id']
self.__delCronExec(get)

if sclient['realtime']: return True
sdate = '`date +\"%Y-%m-%d %H:%M:%S\"`';
self.__get_send_cmd(sclient)
cmd = '''
rname="%s"
plugin_path="%s"
logs_file=$plugin_path/sclient/${rname}_exec.log
echo "★【%s】 STSRT" >> $logs_file
echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file
bash $plugin_path/sclient/${rname}_cmd >> $logs_file 2>&1
echo "【%s】 END★" >> $logs_file
echo "

回复 ·

madlifer 作者

我试了一下还是不行啊, 可以github pull一下代码吗

回复 ·

回忆

快乐哈哈,请问你的破解方法如何使用?

回复 ·

madlifer 作者

安装宝塔6.x版本后 运行破解脚本即可

回复 ·

Umasou

经测试 网站监控报表功能无法使用 提示未购买或已过期

回复 ·

temp

issues里有解决

回复 ·

笔趣

请问5.9X能用这个破解吗

回复 ·

madlifer 作者

5.9x是不能用的

回复 ·

6.8.8已失效

回复 ·

madlifer 作者

6.89已修复,目前完美破解

回复 ·

昨天宝塔官方更新了
现在玩不了了

回复 ·

添加新评论