mirror of
https://github.com/flucont/btcloud.git
synced 2025-10-14 22:47:11 +00:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9a63bc921b | ||
![]() |
5d305b47de | ||
![]() |
45decd43f6 | ||
![]() |
0db95c4f00 | ||
![]() |
eb5deaeda0 | ||
![]() |
aa704d86ac | ||
![]() |
3eb66a20bc | ||
![]() |
53a878def3 | ||
![]() |
b6350dbed8 | ||
![]() |
2c9f84c121 | ||
![]() |
ab81af3b94 | ||
![]() |
98f9ca0e5b | ||
![]() |
50cfdaa06f | ||
![]() |
ae4ed95573 | ||
![]() |
e98206ce0c | ||
![]() |
8946b4fd11 | ||
![]() |
5bd1670955 |
@@ -5,7 +5,7 @@
|
||||
|
||||
网站后台管理可一键同步宝塔官方的插件列表与增量更新插件包,还有云端使用记录、IP黑白名单、操作日志、定时任务等功能。
|
||||
|
||||
本项目自带的宝塔安装包和更新包是7.9.3最新版,已修改适配此第三方云端,并且全开源,无so等加密文件。
|
||||
本项目自带的宝塔安装包和更新包是7.9.8最新版,已修改适配此第三方云端,并且全开源,无so等加密文件。
|
||||
|
||||
觉得该项目不错的可以给个Star~
|
||||
|
||||
|
115
app/command/DecryptFile.php
Normal file
115
app/command/DecryptFile.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\command;
|
||||
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Argument;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
use think\facade\Db;
|
||||
use think\facade\Config;
|
||||
use app\lib\Plugins;
|
||||
|
||||
class DecryptFile extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('decrypt')
|
||||
->addArgument('type', Argument::REQUIRED, '文件类型,plugin:插件文件,module:模块文件,classdir:宝塔class目录,all:所有py文件')
|
||||
->addArgument('file', Argument::REQUIRED, '文件路径')
|
||||
->addArgument('os', Argument::OPTIONAL, '操作系统:Windows/Linux')
|
||||
->setDescription('解密宝塔面板python文件');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$type = trim($input->getArgument('type'));
|
||||
$file = trim($input->getArgument('file'));
|
||||
|
||||
if(!file_exists($file)){
|
||||
$output->writeln('文件不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
if($type == 'plugin'){
|
||||
$os = trim($input->getArgument('os'));
|
||||
try{
|
||||
if(Plugins::decode_plugin_main_local($file, $os)){
|
||||
$output->writeln('文件解密成功!');
|
||||
}else{
|
||||
$output->writeln('文件解密失败!');
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
$output->writeln($e->getMessage());
|
||||
}
|
||||
}elseif($type == 'module'){
|
||||
try{
|
||||
$res = Plugins::decode_module_file($file);
|
||||
if($res == 2){
|
||||
$output->writeln('文件解密失败!');
|
||||
}elseif($res == 1){
|
||||
$output->writeln('文件解密成功!');
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
$output->writeln($e->getMessage());
|
||||
}
|
||||
}elseif($type == 'classdir'){
|
||||
$file = rtrim($file, '/');
|
||||
if(!file_exists($file.'/common.py')){
|
||||
$output->writeln('当前路径非宝塔面板class目录');
|
||||
return;
|
||||
}
|
||||
$dirs = glob($file.'/*Model');
|
||||
foreach($dirs as $dir){
|
||||
if(!is_dir($dir))continue;
|
||||
$files = glob($dir.'/*Model.py');
|
||||
foreach($files as $file){
|
||||
try{
|
||||
$res = Plugins::decode_module_file($file);
|
||||
if($res == 2){
|
||||
$output->writeln('文件解密失败:'.$file);
|
||||
}elseif($res == 1){
|
||||
$output->writeln('文件解密成功:'.$file);
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
$output->writeln($e->getMessage().':'.$file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}elseif($type == 'all'){
|
||||
$file = rtrim($file, '/');
|
||||
$this->scan_all_file($input, $output, $file);
|
||||
}else{
|
||||
$output->writeln('未知文件类型');
|
||||
}
|
||||
}
|
||||
|
||||
private function scan_all_file(Input $input, Output $output, $path) {
|
||||
$dir = opendir($path);
|
||||
while(false !== ( $file = readdir($dir)) ) {
|
||||
if (( $file != '.' ) && ( $file != '..' )) {
|
||||
$filepath = $path . '/' . $file;
|
||||
if ( is_dir($filepath) ) {
|
||||
$this->scan_all_file($input, $output, $filepath);
|
||||
}
|
||||
elseif(substr($filepath, -3) == '.py') {
|
||||
try{
|
||||
$res = Plugins::decode_module_file($filepath);
|
||||
if($res == 2){
|
||||
$output->writeln('文件解密失败:'.$filepath);
|
||||
}elseif($res == 1){
|
||||
$output->writeln('文件解密成功:'.$filepath);
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
$output->writeln($e->getMessage().':'.$filepath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($dir);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -197,6 +197,28 @@ class Api extends BaseController
|
||||
return json($data);
|
||||
}
|
||||
|
||||
//宝塔云监控获取最新版本
|
||||
public function btm_latest_version(){
|
||||
$data = [
|
||||
'version' => config_get('new_version_btm'),
|
||||
'description' => config_get('update_msg_btm'),
|
||||
'create_time' => config_get('update_date_btm')
|
||||
];
|
||||
return json($data);
|
||||
}
|
||||
|
||||
//宝塔云监控更新日志
|
||||
public function btm_update_history(){
|
||||
$data = [
|
||||
[
|
||||
'version' => config_get('new_version_btm'),
|
||||
'description' => config_get('update_msg_btm'),
|
||||
'create_time' => config_get('update_date_btm')
|
||||
]
|
||||
];
|
||||
return json($data);
|
||||
}
|
||||
|
||||
//获取内测版更新日志
|
||||
public function get_beta_logs(){
|
||||
return json(['beta_ps'=>'当前暂无内测版', 'list'=>[]]);
|
||||
@@ -259,11 +281,37 @@ class Api extends BaseController
|
||||
|
||||
//绑定账号
|
||||
public function get_auth_token(){
|
||||
$userinfo = ['uid'=>1, 'username'=>'Administrator', 'address'=>'127.0.0.1', 'serverid'=>'1', 'access_key'=>random(32), 'secret_key'=>random(48), 'ukey'=>md5(time()), 'state'=>1];
|
||||
if(!$_POST['data']) return json(['status'=>false, 'msg'=>'参数不能为空']);
|
||||
$reqData = hex2bin($_POST['data']);
|
||||
parse_str($reqData, $arr);
|
||||
$serverid = $arr['serverid'];
|
||||
$userinfo = ['uid'=>1, 'username'=>'Administrator', 'address'=>'127.0.0.1', 'serverid'=>$serverid, 'access_key'=>random(32), 'secret_key'=>random(48), 'ukey'=>md5(time()), 'state'=>1];
|
||||
$data = bin2hex(urlencode(json_encode($userinfo)));
|
||||
return json(['status'=>true, 'msg'=>'登录成功!', 'data'=>$data]);
|
||||
}
|
||||
|
||||
//绑定账号新
|
||||
public function authorization_login(){
|
||||
if(!$_POST['data']) return json(['status'=>false, 'msg'=>'参数不能为空']);
|
||||
$reqData = hex2bin($_POST['data']);
|
||||
parse_str($reqData, $arr);
|
||||
$serverid = $arr['serverid'];
|
||||
$userinfo = ['uid'=>1, 'username'=>'Administrator', 'ip'=>'127.0.0.1', 'server_id'=>$serverid, 'access_key'=>random(32), 'secret_key'=>random(48)];
|
||||
$data = bin2hex(urlencode(json_encode($userinfo)));
|
||||
return json(['status'=>true, 'msg'=>'登录成功!', 'data'=>$data]);
|
||||
}
|
||||
|
||||
//刷新授权信息
|
||||
public function authorization_info(){
|
||||
if(!$_POST['data']) return json(['status'=>false, 'msg'=>'参数不能为空']);
|
||||
$reqData = hex2bin($_POST['data']);
|
||||
parse_str($reqData, $arr);
|
||||
$id = isset($arr['id'])&&$arr['id']>0?$arr['id']:1;
|
||||
$userinfo = ['id'=>$id, 'product'=>$arr['product'], 'status'=>2, 'clients'=>9999, 'durations'=>0, 'end_time'=>strtotime('+10 year')];
|
||||
$data = bin2hex(urlencode(json_encode($userinfo)));
|
||||
return json(['status'=>true, 'data'=>$data]);
|
||||
}
|
||||
|
||||
//一键部署列表
|
||||
public function get_deplist(){
|
||||
$os = input('post.os');
|
||||
@@ -272,6 +320,12 @@ class Api extends BaseController
|
||||
return json($json_arr);
|
||||
}
|
||||
|
||||
//获取宝塔SSL列表
|
||||
public function get_ssl_list(){
|
||||
$data = bin2hex('[]');
|
||||
return json(['status'=>true, 'msg'=>'', 'data'=>$data]);
|
||||
}
|
||||
|
||||
public function return_success(){
|
||||
return json(['status'=>true, 'msg'=>1, 'data'=>(object)[]]);
|
||||
}
|
||||
|
@@ -52,6 +52,8 @@ class Install extends BaseController
|
||||
$sqls=file_get_contents(app()->getRootPath().'install.sql');
|
||||
$sqls=explode(';', $sqls);
|
||||
$sqls[]="REPLACE INTO `".$mysql_prefix."config` VALUES ('syskey', '".random(16)."')";
|
||||
$sqls[]="REPLACE INTO `".$mysql_prefix."config` VALUES ('admin_username', '".addslashes($admin_username)."')";
|
||||
$sqls[]="REPLACE INTO `".$mysql_prefix."config` VALUES ('admin_password', '".addslashes($admin_password)."')";
|
||||
$success=0;$error=0;$errorMsg=null;
|
||||
foreach ($sqls as $value) {
|
||||
$value=trim($value);
|
||||
|
@@ -187,6 +187,8 @@ class Plugins
|
||||
$userinfo = $btapi->get_user_info();
|
||||
if(isset($userinfo['uid'])){
|
||||
$src = file_get_contents($main_filepath);
|
||||
if($src===false)throw new Exception('文件打开失败');
|
||||
if(!$src || strpos($src, 'import ')!==false)return true;
|
||||
$uid = $userinfo['uid'];
|
||||
$serverid = $userinfo['serverid'];
|
||||
$key = md5(substr($serverid, 10, 16).$uid.$serverid);
|
||||
@@ -202,7 +204,7 @@ class Plugins
|
||||
if($tmp) $de_text .= $tmp;
|
||||
}
|
||||
}
|
||||
if(!empty($de_text)){
|
||||
if(!empty($de_text) && strpos($de_text, 'import ')!==false){
|
||||
file_put_contents($main_filepath, $de_text);
|
||||
return true;
|
||||
}
|
||||
@@ -212,6 +214,28 @@ class Plugins
|
||||
}
|
||||
}
|
||||
|
||||
public static function decode_module_file($filepath){
|
||||
$src = file_get_contents($filepath);
|
||||
if($src===false)throw new Exception('文件打开失败');
|
||||
if(!$src || strpos($src, 'import ')!==false)return 0;
|
||||
$key = 'Z2B87NEAS2BkxTrh';
|
||||
$iv = 'WwadH66EGWpeeTT6';
|
||||
$data_arr = explode("\n", $src);
|
||||
$de_text = '';
|
||||
foreach($data_arr as $data){
|
||||
$data = trim($data);
|
||||
if(!empty($data)){
|
||||
$tmp = openssl_decrypt($data, 'aes-128-cbc', $key, 0, $iv);
|
||||
if($tmp) $de_text .= $tmp;
|
||||
}
|
||||
}
|
||||
if(!empty($de_text) && strpos($de_text, 'import ')!==false){
|
||||
file_put_contents($filepath, $de_text);
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
//去除插件主程序文件授权校验
|
||||
public static function noauth_plugin_main($main_filepath){
|
||||
$data = file_get_contents($main_filepath);
|
||||
|
@@ -1,7 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
Linux_Version="7.9.3"
|
||||
Windows_Version="7.6.0"
|
||||
Linux_Version="7.9.9"
|
||||
Windows_Version="7.8.0"
|
||||
Btm_Version="2.1.1"
|
||||
|
||||
FILES=(
|
||||
public/install/src/panel6.zip
|
||||
@@ -13,6 +14,9 @@ public/win/install/panel_update.py
|
||||
public/win/panel/panel_${Windows_Version}.zip
|
||||
public/win/panel/data/api.py
|
||||
public/win/panel/data/setup.py
|
||||
public/install/src/bt-monitor-${Btm_Version}.zip
|
||||
public/install/install_btmonitor.sh
|
||||
public/install/update_btmonitor.sh
|
||||
)
|
||||
|
||||
DIR=$1
|
||||
|
@@ -2,6 +2,7 @@
|
||||
{block name="title"}宝塔第三方云端管理中心{/block}
|
||||
{block name="main"}
|
||||
<style>
|
||||
.table>tbody>tr>td{white-space: normal;}
|
||||
.query-title {
|
||||
background-color:#f5fafe;
|
||||
word-break: keep-all;
|
||||
|
@@ -70,12 +70,14 @@ function submitlogin(){
|
||||
var pass = $("input[name='pass']").val();
|
||||
var code = $("input[name='code']").val();
|
||||
if(user=='' || pass==''){layer.alert('用户名或密码不能为空!');return false;}
|
||||
$.ajax({
|
||||
var ii = layer.load(2);
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '{:request()->url()}',
|
||||
data: {username:user, password:pass, code:code},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.msg('登录成功,正在跳转', {icon: 1,shade: 0.01,time: 15000});
|
||||
window.location.href='/admin';
|
||||
@@ -87,6 +89,7 @@ function submitlogin(){
|
||||
}
|
||||
},
|
||||
error:function(data){
|
||||
layer.close(ii);
|
||||
layer.msg('服务器错误');
|
||||
}
|
||||
});
|
||||
|
@@ -47,6 +47,19 @@
|
||||
<label>宝塔Windows面板更新日期:</label>
|
||||
<input type="date" name="update_date_win" value="{:config_get('update_date_win')}" class="form-control"/>
|
||||
<font color="green">用于检测更新接口返回</font>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>宝塔云监控最新版本号:</label>
|
||||
<input type="text" name="new_version_btm" value="{:config_get('new_version_btm')}" class="form-control"/>
|
||||
<font color="green">用于一键更新脚本获取最新版本号,以及检测更新接口。并确保已在/public/install/src/放置对应版本更新包</font>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>宝塔云监控更新日志:</label>
|
||||
<textarea class="form-control" name="update_msg_btm" rows="3" placeholder="支持HTML代码">{:config_get('update_msg_btm')}</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>宝塔云监控更新日期:</label>
|
||||
<input type="date" name="update_date_btm" value="{:config_get('update_date_btm')}" class="form-control"/>
|
||||
</div>
|
||||
<div class="form-group text-center">
|
||||
<input type="submit" name="submit" value="保存" class="btn btn-success btn-block"/>
|
||||
|
@@ -50,7 +50,7 @@
|
||||
<div class="cont">
|
||||
<div class="top">
|
||||
<div class="title">Windows面板 {:config_get('new_version_win')}</div>
|
||||
<div class="desc">支持Windows Server 2008 R2/2012/2016/2019,64位系统</div>
|
||||
<div class="desc">支持Windows Server 2008 R2/2012/2016/2019/2022,64位系统</div>
|
||||
<div class="mark">
|
||||
<span>操作简单</span>
|
||||
<span>使用方便</span>
|
||||
@@ -62,6 +62,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{if config_get('new_version_btm')}<div class="disflex flex_lrcenter mt_30 install-list">
|
||||
<div class="install-box monitor">
|
||||
<div class="img">
|
||||
<img src="/static/images/bt_monitor.png" />
|
||||
</div>
|
||||
<div class="cont">
|
||||
<div class="top">
|
||||
<div class="title">堡塔云监控</div>
|
||||
<div class="desc">多服务监控和异常告警通知</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<a class="btn" href="javascript:;" id="goInstallMonitor">查看安装脚本</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -105,7 +121,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d4" id="instal-windows">
|
||||
<div class="d4" id="instal-windows" style="background-color: #edf6ef;">
|
||||
<div class="wrap">
|
||||
<div class="wrap-title">
|
||||
<div class="text">Windows面板{:config_get('new_version_win')}安装方法</div>
|
||||
@@ -121,10 +137,40 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tips" style="color: orangered; font-weight: 700">
|
||||
<p>注意:仅支持Windows Server 2008 R2/2012/2016/2019,64位系统(中文简体),且未安装其它环境</p>
|
||||
<p>注意:仅支持Windows Server 2008 R2/2012/2016/2019/2022,64位系统(中文简体),且未安装其它环境</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{if config_get('new_version_btm')}
|
||||
<div class="d4" id="instal-monitor">
|
||||
<div class="wrap">
|
||||
<div class="wrap-title">
|
||||
<div class="text" style="margin-right: 12px;">堡塔云监控{:config_get('new_version_btm')}安装脚本</div>
|
||||
</div>
|
||||
<div class="desc">
|
||||
使用 SSH 连接工具,如
|
||||
<a class="link" href="https://www.putty.org/" target="_blank" rel="noreferrer">PUTTY</a>
|
||||
连接到您的 Linux 服务器后,根据系统执行相应命令开始安装:
|
||||
</div>
|
||||
<div class="install-code">
|
||||
<span class="osname">堡塔云监控安装脚本</span>
|
||||
<div class="code-cont">
|
||||
<div class="command" title="点击复制安装脚本">curl -sS {$siteurl}/install/install_btmonitor.sh -o /tmp/install_btmonitor.sh && bash /tmp/install_btmonitor.sh</div>
|
||||
<span class="ico-copy" title="点击复制安装脚本" data-clipboard-text="curl -sS {$siteurl}/install/install_btmonitor.sh -o /tmp/install_btmonitor.sh && bash /tmp/install_btmonitor.sh">复制</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="install-code">
|
||||
<span class="osname">堡塔云监控更新脚本</span>
|
||||
<div class="code-cont">
|
||||
<div class="command" title="点击复制更新脚本">curl {$siteurl}/install/update_btmonitor.sh|bash</div>
|
||||
<span class="ico-copy" title="点击复制更新脚本" data-clipboard-text="curl {$siteurl}/install/update_btmonitor.sh|bash">复制</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tips" style="color: orangered; font-weight: 700">
|
||||
<p>注意:推荐使用Chrome、火狐、edge浏览器,国产浏览器(极速模式)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>{/if}
|
||||
<div class="animate-bg"></div>
|
||||
</div>
|
||||
|
||||
@@ -140,7 +186,7 @@
|
||||
</div>
|
||||
<div class="fb2 mt_15">
|
||||
<p>
|
||||
Copyright © 2022 宝塔面板安装脚本
|
||||
Copyright © {:date('Y')} 宝塔面板安装脚本
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -186,6 +232,10 @@
|
||||
scrollTop('#instal-cloud');
|
||||
});
|
||||
|
||||
$('#goInstallMonitor').click(function () {
|
||||
scrollTop('#instal-monitor');
|
||||
});
|
||||
|
||||
function GetRequest() {
|
||||
var url = location.search;
|
||||
//获取url中"?"符后的字串
|
||||
|
@@ -6,5 +6,6 @@ return [
|
||||
// 指令定义
|
||||
'commands' => [
|
||||
'updateall' => 'app\command\UpdateAll',
|
||||
'decrypt' => 'app\command\DecryptFile',
|
||||
],
|
||||
];
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
0
data/plugins/folder/.gitkeep
Normal file
0
data/plugins/folder/.gitkeep
Normal file
0
data/plugins/main/.gitkeep
Normal file
0
data/plugins/main/.gitkeep
Normal file
0
data/plugins/other/other/.gitkeep
Normal file
0
data/plugins/other/other/.gitkeep
Normal file
0
data/plugins/package/.gitkeep
Normal file
0
data/plugins/package/.gitkeep
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
0
data/win/plugins/folder/.gitkeep
Normal file
0
data/win/plugins/folder/.gitkeep
Normal file
0
data/win/plugins/main/.gitkeep
Normal file
0
data/win/plugins/main/.gitkeep
Normal file
0
data/win/plugins/package/.gitkeep
Normal file
0
data/win/plugins/package/.gitkeep
Normal file
11
install.sql
11
install.sql
@@ -12,12 +12,15 @@ INSERT INTO `cloud_config` (`key`, `value`) VALUES
|
||||
('bt_key', ''),
|
||||
('whitelist', '0'),
|
||||
('download_page', '1'),
|
||||
('new_version', '7.9.3'),
|
||||
('new_version', '7.9.9'),
|
||||
('update_msg', '暂无更新日志'),
|
||||
('update_date', '2022-07-13'),
|
||||
('new_version_win', '7.6.0'),
|
||||
('update_date', '2023-04-07'),
|
||||
('new_version_win', '7.8.0'),
|
||||
('update_msg_win', '暂无更新日志'),
|
||||
('update_date_win', '2022-06-01'),
|
||||
('update_date_win', '2022-12-08'),
|
||||
('new_version_btm', '2.1.1'),
|
||||
('update_msg_btm', '暂无更新日志'),
|
||||
('update_date_btm', '2023-03-31'),
|
||||
('updateall_type', '0'),
|
||||
('syskey', 'UqP94LtI8eWAIgCP');
|
||||
|
||||
|
@@ -36,9 +36,9 @@ setup_path="/www"
|
||||
python_bin=$setup_path/server/panel/pyenv/bin/python
|
||||
cpu_cpunt=$(cat /proc/cpuinfo|grep processor|wc -l)
|
||||
|
||||
if [ "$1" ];then
|
||||
IDC_CODE=$1
|
||||
fi
|
||||
# if [ "$1" ];then
|
||||
# IDC_CODE=$1
|
||||
# fi
|
||||
|
||||
GetSysInfo(){
|
||||
if [ -s "/etc/redhat-release" ];then
|
||||
@@ -54,6 +54,27 @@ GetSysInfo(){
|
||||
echo -e ${SYS_VERSION}
|
||||
echo -e Bit:${SYS_BIT} Mem:${MEM_TOTAL}M Core:${CPU_INFO}
|
||||
echo -e ${SYS_INFO}
|
||||
|
||||
if [ -z "${os_version}" ];then
|
||||
echo -e "============================================"
|
||||
echo -e "检测到为非常用系统安装,建议更换至Centos-7或Debian-10+或Ubuntu-20+系统安装宝塔面板"
|
||||
echo -e "详情请查看系统兼容表:https://docs.qq.com/sheet/DUm54VUtyTVNlc21H?tab=BB08J2"
|
||||
echo -e "特殊情况可通过以下联系方式寻求安装协助情况"
|
||||
fi
|
||||
|
||||
is64bit=$(getconf LONG_BIT)
|
||||
if [ "${is64bit}" == '32' ];then
|
||||
echo -e "宝塔面板不支持32位系统进行安装,请使用64位系统/服务器架构进行安装宝塔"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
S390X_CHECK=$(uname -a|grep s390x)
|
||||
if [ "${S390X_CHECK}" ];then
|
||||
echo -e "宝塔面板不支持s390x架构进行安装,请使用64位系统/服务器架构进行安装宝塔"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "============================================"
|
||||
echo -e "请截图以上报错信息发帖至论坛www.bt.cn/bbs求助"
|
||||
}
|
||||
Red_Error(){
|
||||
@@ -97,6 +118,33 @@ System_Check(){
|
||||
Install_Check
|
||||
fi
|
||||
}
|
||||
Set_Ssl(){
|
||||
echo -e ""
|
||||
echo -e "----------------------------------------------------------------------"
|
||||
echo -e "为了您的面板使用安全,建议您开启面板SSL,开启后请使用https访问宝塔面板"
|
||||
echo -e "输入y回车即开启面板SSL并进行下一步安装"
|
||||
echo -e "输入n回车跳过面板SSL配置,直接进行安装"
|
||||
echo -e "10秒后将跳过SSL配置,直接进行面板安装"
|
||||
echo -e "----------------------------------------------------------------------"
|
||||
echo -e ""
|
||||
read -t 10 -p "是否确定开启面板SSL ? (y/n): " yes
|
||||
|
||||
if [ $? != 0 ];then
|
||||
SET_SSL=false
|
||||
else
|
||||
case "$yes" in
|
||||
y)
|
||||
SET_SSL=true
|
||||
;;
|
||||
n)
|
||||
SET_SSL=false
|
||||
rm -f /www/server/panel/data/ssl.pl
|
||||
;;
|
||||
*)
|
||||
Set_Ssl
|
||||
esac
|
||||
fi
|
||||
}
|
||||
Get_Pack_Manager(){
|
||||
if [ -f "/usr/bin/yum" ] && [ -d "/etc/yum.repos.d" ]; then
|
||||
PM="yum"
|
||||
@@ -183,7 +231,7 @@ get_node_url(){
|
||||
|
||||
echo '---------------------------------------------';
|
||||
echo "Selected download node...";
|
||||
nodes=(http://dg2.bt.cn http://dg1.bt.cn http://125.90.93.52:5880 http://36.133.1.8:5880 http://123.129.198.197 http://38.34.185.130 http://116.213.43.206:5880 http://128.1.164.196);
|
||||
nodes=(https://dg2.bt.cn https://download.bt.cn https://ctcc1-node.bt.cn https://cmcc1-node.bt.cn https://ctcc2-node.bt.cn https://hk1-node.bt.cn https://na1-node.bt.cn https://jp1-node.bt.cn);
|
||||
|
||||
if [ "$1" ];then
|
||||
nodes=($(echo ${nodes[*]}|sed "s#${1}##"))
|
||||
@@ -225,7 +273,7 @@ get_node_url(){
|
||||
if [ -z "$NODE_URL" ];then
|
||||
NODE_URL=$(cat $tmp_file2|sort -g -t " " -k 1|head -n 1|awk '{print $2}')
|
||||
if [ -z "$NODE_URL" ];then
|
||||
NODE_URL='http://download.bt.cn';
|
||||
NODE_URL='https://download.bt.cn';
|
||||
fi
|
||||
fi
|
||||
rm -f $tmp_file1
|
||||
@@ -287,7 +335,7 @@ Install_RPM_Pack(){
|
||||
|
||||
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
|
||||
#yum remove -y python-requests python3-requests python-greenlet python3-greenlet
|
||||
yumPacks="libcurl-devel wget tar gcc make zip unzip openssl openssl-devel gcc libxml2 libxml2-devel libxslt* zlib zlib-devel libjpeg-devel libpng-devel libwebp libwebp-devel freetype freetype-devel lsof pcre pcre-devel vixie-cron crontabs icu libicu-devel c-ares libffi-devel bzip2-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel"
|
||||
yumPacks="libcurl-devel wget tar gcc make zip unzip openssl openssl-devel gcc libxml2 libxml2-devel libxslt* zlib zlib-devel libjpeg-devel libpng-devel libwebp libwebp-devel freetype freetype-devel lsof pcre pcre-devel vixie-cron crontabs icu libicu-devel c-ares libffi-devel bzip2-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel qrencode"
|
||||
yum install -y ${yumPacks}
|
||||
|
||||
for yumPack in ${yumPacks}
|
||||
@@ -313,7 +361,15 @@ Install_Deb_Pack(){
|
||||
if [ "${UBUNTU_22}" ];then
|
||||
apt-get remove needrestart -y
|
||||
fi
|
||||
ALIYUN_CHECK=$(cat /etc/motd|grep "Alibaba Cloud ")
|
||||
if [ "${ALIYUN_CHECK}" ] && [ "${UBUNTU_22}" ];then
|
||||
apt-get remove libicu70 -y
|
||||
fi
|
||||
apt-get update -y
|
||||
apt-get install bash -y
|
||||
if [ -f "/usr/bin/bash" ];then
|
||||
ln -sf /usr/bin/bash /bin/sh
|
||||
fi
|
||||
apt-get install ruby -y
|
||||
apt-get install lsb-release -y
|
||||
#apt-get install ntp ntpdate -y
|
||||
@@ -333,7 +389,7 @@ Install_Deb_Pack(){
|
||||
apt-get install curl -y
|
||||
fi
|
||||
|
||||
debPacks="wget curl libcurl4-openssl-dev gcc make zip unzip tar openssl libssl-dev gcc libxml2 libxml2-dev zlib1g zlib1g-dev libjpeg-dev libpng-dev lsof libpcre3 libpcre3-dev cron net-tools swig build-essential libffi-dev libbz2-dev libncurses-dev libsqlite3-dev libreadline-dev tk-dev libgdbm-dev libdb-dev libdb++-dev libpcap-dev xz-utils git";
|
||||
debPacks="wget curl libcurl4-openssl-dev gcc make zip unzip tar openssl libssl-dev gcc libxml2 libxml2-dev zlib1g zlib1g-dev libjpeg-dev libpng-dev lsof libpcre3 libpcre3-dev cron net-tools swig build-essential libffi-dev libbz2-dev libncurses-dev libsqlite3-dev libreadline-dev tk-dev libgdbm-dev libdb-dev libdb++-dev libpcap-dev xz-utils git qrencode";
|
||||
apt-get install -y $debPacks --force-yes
|
||||
|
||||
for debPack in ${debPacks}
|
||||
@@ -418,7 +474,7 @@ Install_Python_Lib(){
|
||||
if [ "$is_package" = "" ];then
|
||||
wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip.txt -T 5
|
||||
$pyenv_path/pyenv/bin/pip install -U pip
|
||||
$pyenv_path/pyenv/bin/pip install -U setuptools
|
||||
$pyenv_path/pyenv/bin/pip install -U setuptools==65.5.0
|
||||
$pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
|
||||
fi
|
||||
source $pyenv_path/pyenv/bin/activate
|
||||
@@ -552,7 +608,7 @@ Install_Python_Lib(){
|
||||
ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btpython
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
$pyenv_path/pyenv/bin/pip install -U pip
|
||||
$pyenv_path/pyenv/bin/pip install -U setuptools
|
||||
$pyenv_path/pyenv/bin/pip install -U setuptools==65.5.0
|
||||
$pyenv_path/pyenv/bin/pip install -U wheel==0.34.2
|
||||
$pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
|
||||
source $pyenv_path/pyenv/bin/activate
|
||||
@@ -568,10 +624,10 @@ Install_Bt(){
|
||||
if [ -f ${setup_path}/server/panel/data/port.pl ];then
|
||||
panelPort=$(cat ${setup_path}/server/panel/data/port.pl)
|
||||
else
|
||||
RE_NUM=$(expr $RANDOM % 5)
|
||||
if [ "${RE_NUM}" == "1" ];then
|
||||
panelPort=$(expr $RANDOM % 55535 + 10000)
|
||||
fi
|
||||
panelPort=$(expr $RANDOM % 55535 + 10000)
|
||||
fi
|
||||
if [ "${PANEL_PORT}" ];then
|
||||
panelPort=$PANEL_PORT
|
||||
fi
|
||||
mkdir -p ${setup_path}/server/panel/logs
|
||||
mkdir -p ${setup_path}/server/panel/vhost/apache
|
||||
@@ -666,21 +722,39 @@ Set_Bt_Panel(){
|
||||
fi
|
||||
|
||||
password=$(cat /dev/urandom | head -n 16 | md5sum | head -c 8)
|
||||
if [ "$PANEL_PASSWORD" ];then
|
||||
password=$PANEL_PASSWORD
|
||||
fi
|
||||
sleep 1
|
||||
admin_auth="/www/server/panel/data/admin_path.pl"
|
||||
if [ "${SAFE_PATH}" ];then
|
||||
auth_path=$SAFE_PATH
|
||||
echo "/${auth_path}" > ${admin_auth}
|
||||
fi
|
||||
if [ ! -f ${admin_auth} ];then
|
||||
auth_path=$(cat /dev/urandom | head -n 16 | md5sum | head -c 8)
|
||||
echo "/${auth_path}" > ${admin_auth}
|
||||
fi
|
||||
auth_path=$(cat /dev/urandom | head -n 16 | md5sum | head -c 8)
|
||||
echo "/${auth_path}" > ${admin_auth}
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
/www/server/panel/pyenv/bin/pip3 install pymongo
|
||||
/www/server/panel/pyenv/bin/pip3 install psycopg2-binary
|
||||
/www/server/panel/pyenv/bin/pip3 install flask -U
|
||||
/www/server/panel/pyenv/bin/pip3 install flask-sock
|
||||
auth_path=$(cat ${admin_auth})
|
||||
cd ${setup_path}/server/panel/
|
||||
if [ "$SET_SSL" == true ]; then
|
||||
btpip install -I pyOpenSSl
|
||||
btpython /www/server/panel/tools.py ssl
|
||||
fi
|
||||
/etc/init.d/bt start
|
||||
$python_bin -m py_compile tools.py
|
||||
$python_bin tools.py username
|
||||
username=$($python_bin tools.py panel ${password})
|
||||
if [ "$PANEL_USER" ];then
|
||||
username=$PANEL_USER
|
||||
fi
|
||||
cd ~
|
||||
echo "${password}" > ${setup_path}/server/panel/default.pl
|
||||
chmod 600 ${setup_path}/server/panel/default.pl
|
||||
@@ -688,7 +762,7 @@ Set_Bt_Panel(){
|
||||
/etc/init.d/bt restart
|
||||
sleep 3
|
||||
isStart=$(ps aux |grep 'BT-Panel'|grep -v grep|awk '{print $2}')
|
||||
LOCAL_CURL=$(curl 127.0.0.1:8888/login 2>&1 |grep -i html)
|
||||
LOCAL_CURL=$(curl 127.0.0.1:${panelPort}/login 2>&1 |grep -i html)
|
||||
if [ -z "${isStart}" ] && [ -z "${LOCAL_CURL}" ];then
|
||||
/etc/init.d/bt 22
|
||||
cd /www/server/panel/pyenv/bin
|
||||
@@ -697,6 +771,12 @@ Set_Bt_Panel(){
|
||||
lsattr python3.7 python
|
||||
Red_Error "ERROR: The BT-Panel service startup failed." "ERROR: 宝塔启动失败"
|
||||
fi
|
||||
|
||||
if [ "$PANEL_USER" ];then
|
||||
cd ${setup_path}/server/panel/
|
||||
btpython -c 'import tools;tools.set_panel_username("'$PANEL_USER'")'
|
||||
cd ~
|
||||
fi
|
||||
}
|
||||
Set_Firewall(){
|
||||
sshPort=$(cat /etc/ssh/sshd_config | grep 'Port '|awk '{print $2}')
|
||||
@@ -766,7 +846,6 @@ Get_Ip_Address(){
|
||||
isHosts=$(cat /etc/hosts|grep 'www.bt.cn')
|
||||
if [ -z "${isHosts}" ];then
|
||||
echo "" >> /etc/hosts
|
||||
echo "116.213.43.206 www.bt.cn" >> /etc/hosts
|
||||
getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress)
|
||||
if [ -z "${getIpAddress}" ];then
|
||||
sed -i "/bt.cn/d" /etc/hosts
|
||||
@@ -802,6 +881,7 @@ Setup_Count(){
|
||||
echo /www > /var/bt_setupPath.conf
|
||||
}
|
||||
Install_Main(){
|
||||
#Set_Ssl
|
||||
startTime=`date +%s`
|
||||
Lock_Clear
|
||||
System_Check
|
||||
@@ -839,7 +919,38 @@ echo "
|
||||
+----------------------------------------------------------------------
|
||||
| The WebPanel URL will be http://SERVER_IP:8888 when installed.
|
||||
+----------------------------------------------------------------------
|
||||
| 为了您的正常使用,请确保使用全新或纯净的系统安装宝塔面板,不支持已部署项目/环境的系统安装
|
||||
+----------------------------------------------------------------------
|
||||
"
|
||||
|
||||
while [ ${#} -gt 0 ]; do
|
||||
case $1 in
|
||||
-u|--user)
|
||||
PANEL_USER=$2
|
||||
shift 1
|
||||
;;
|
||||
-p|--password)
|
||||
PANEL_PASSWORD=$2
|
||||
shift 1
|
||||
;;
|
||||
-P|--port)
|
||||
PANEL_PORT=$2
|
||||
shift 1
|
||||
;;
|
||||
--safe-path)
|
||||
SAFE_PATH=$2
|
||||
shift 1
|
||||
;;
|
||||
-y)
|
||||
go="y"
|
||||
;;
|
||||
*)
|
||||
IDC_CODE=$1
|
||||
;;
|
||||
esac
|
||||
shift 1
|
||||
done
|
||||
|
||||
while [ "$go" != 'y' ] && [ "$go" != 'n' ]
|
||||
do
|
||||
read -p "Do you want to install Bt-Panel to the $setup_path directory now?(y/n): " go;
|
||||
@@ -852,22 +963,33 @@ fi
|
||||
ARCH_LINUX=$(cat /etc/os-release |grep "Arch Linux")
|
||||
if [ "${ARCH_LINUX}" ] && [ -f "/usr/bin/pacman" ];then
|
||||
pacman -Sy
|
||||
pacman -S curl wget unzip firewalld openssl pkg-config make gcc cmake libxml2 libxslt libvpx gd libsodium oniguruma sqlite libzip autoconf inetutils sudo --noconfirm
|
||||
pacman -S curl wget unzip firewalld openssl pkg-config make gcc cmake libxml2 libxslt libvpx gd libsodium oniguruma sqlite libzip autoconf inetutils sudo --noconfirm
|
||||
fi
|
||||
|
||||
Install_Main
|
||||
|
||||
PANEL_SSL=$(cat /www/server/panel/data/ssl.pl 2> /dev/null)
|
||||
if [ "${PANEL_SSL}" == "True" ];then
|
||||
HTTP_S="https"
|
||||
else
|
||||
HTTP_S="http"
|
||||
fi
|
||||
|
||||
echo > /www/server/panel/data/bind.pl
|
||||
echo -e "=================================================================="
|
||||
echo -e "\033[32mCongratulations! Installed successfully!\033[0m"
|
||||
echo -e "=================================================================="
|
||||
echo "外网面板地址: http://${getIpAddress}:${panelPort}${auth_path}"
|
||||
echo "内网面板地址: http://${LOCAL_IP}:${panelPort}${auth_path}"
|
||||
echo "外网面板地址: ${HTTP_S}://${getIpAddress}:${panelPort}${auth_path}"
|
||||
echo "内网面板地址: ${HTTP_S}://${LOCAL_IP}:${panelPort}${auth_path}"
|
||||
echo -e "username: $username"
|
||||
echo -e "password: $password"
|
||||
echo -e "\033[33mIf you cannot access the panel,\033[0m"
|
||||
echo -e "\033[33mrelease the following panel port [${panelPort}] in the security group\033[0m"
|
||||
echo -e "\033[33m若无法访问面板,请检查防火墙/安全组是否有放行面板[${panelPort}]端口\033[0m"
|
||||
if [ "${HTTP_S}" == "https" ];then
|
||||
echo -e "\033[33m因已开启面板自签证书,访问面板会提示不匹配证书,请参考以下链接配置证书\033[0m"
|
||||
echo -e "\033[33mhttps://www.bt.cn/bbs/thread-105443-1-1.html\033[0m"
|
||||
fi
|
||||
echo -e "=================================================================="
|
||||
|
||||
endTime=`date +%s`
|
||||
|
874
public/install/install_btmonitor.sh
Normal file
874
public/install/install_btmonitor.sh
Normal file
@@ -0,0 +1,874 @@
|
||||
#!/bin/bash
|
||||
#########################
|
||||
|
||||
# 广东堡塔安全技术有限公司
|
||||
# author: 赤井秀一
|
||||
# mail: 1021266737@qq.com
|
||||
|
||||
#########################
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
LANG=en_US.UTF-8
|
||||
|
||||
Btapi_Url='http://www.example.com'
|
||||
|
||||
is64bit=$(getconf LONG_BIT)
|
||||
if [ "${is64bit}" != '64' ];then
|
||||
echo -e "\033[31m 抱歉, 堡塔云监控系统不支持32位系统, 请使用64位系统! \033[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
S390X_CHECK=$(uname -a|grep s390x)
|
||||
if [ "${S390X_CHECK}" ];then
|
||||
echo -e "\033[31m 抱歉, 堡塔云监控系统不支持s390x架构进行安装,请使用x86_64服务器架构 \033[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
is_aarch64=$(uname -a|grep aarch64)
|
||||
if [ "${is_aarch64}" != "" ];then
|
||||
echo -e "\033[31m 抱歉, 堡塔云监控系统暂不支持aarch64架构进行安装,请使用x86_64服务器架构 \033[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Command_Exists() {
|
||||
command -v "$@" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
|
||||
GetSysInfo(){
|
||||
if [ -s "/etc/redhat-release" ];then
|
||||
SYS_VERSION=$(cat /etc/redhat-release)
|
||||
elif [ -s "/etc/issue" ]; then
|
||||
SYS_VERSION=$(cat /etc/issue)
|
||||
fi
|
||||
SYS_INFO=$(uname -a)
|
||||
SYS_BIT=$(getconf LONG_BIT)
|
||||
MEM_TOTAL=$(free -m|grep Mem|awk '{print $2}')
|
||||
CPU_INFO=$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
echo -e ${SYS_VERSION}
|
||||
echo -e Bit:${SYS_BIT} Mem:${MEM_TOTAL}M Core:${CPU_INFO}
|
||||
echo -e ${SYS_INFO}
|
||||
echo -e "请截图以上报错信息发帖至论坛www.bt.cn/bbs求助"
|
||||
|
||||
}
|
||||
|
||||
Red_Error(){
|
||||
echo '=================================================';
|
||||
printf '\033[1;31;40m%b\033[0m\n' "$@";
|
||||
GetSysInfo
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
monitor_path="/www/server/bt-monitor"
|
||||
run_bin="/www/server/bt-monitor/BT-MONITOR"
|
||||
if [ ! -d "/www/server" ];then
|
||||
mkdir -p /www/server
|
||||
fi
|
||||
old_dir="/www/server/old_btmonitor"
|
||||
|
||||
cd ~
|
||||
setup_path="/www"
|
||||
python_bin=$setup_path/server/bt-monitor/pyenv/bin/python
|
||||
cpu_cpunt=$(cat /proc/cpuinfo|grep processor|wc -l)
|
||||
|
||||
get_node_url(){
|
||||
if [ ! -f /bin/curl ];then
|
||||
if [ "${PM}" = "yum" ]; then
|
||||
yum install curl -y
|
||||
elif [ "${PM}" = "apt-get" ]; then
|
||||
apt-get install curl -y
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "/www/node.pl" ];then
|
||||
download_Url=$(cat /www/node.pl)
|
||||
echo "Download node: $download_Url";
|
||||
echo '---------------------------------------------';
|
||||
return
|
||||
fi
|
||||
|
||||
echo '---------------------------------------------';
|
||||
echo "Selected download node...";
|
||||
# nodes=(http://dg2.bt.cn http://dg1.bt.cn http://125.90.93.52:5880 http://36.133.1.8:5880 http://123.129.198.197 http://38.34.185.130 http://116.213.43.206:5880 http://128.1.164.196);
|
||||
#nodes=(http://dg2.bt.cn http://dg1.bt.cn http://125.90.93.52:5880 http://36.133.1.8:5880 http://123.129.198.197 http://116.213.43.206:5880 http://128.1.164.196);
|
||||
nodes=(https://dg2.bt.cn https://dg1.bt.cn https://download.bt.cn);
|
||||
tmp_file1=/dev/shm/net_test1.pl
|
||||
tmp_file2=/dev/shm/net_test2.pl
|
||||
[ -f "${tmp_file1}" ] && rm -f ${tmp_file1}
|
||||
[ -f "${tmp_file2}" ] && rm -f ${tmp_file2}
|
||||
touch $tmp_file1
|
||||
touch $tmp_file2
|
||||
for node in ${nodes[@]};
|
||||
do
|
||||
NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/net_test|xargs)
|
||||
RES=$(echo ${NODE_CHECK}|awk '{print $1}')
|
||||
NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $2}')
|
||||
TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $3 * 1000 - 500 }'|cut -d '.' -f 1)
|
||||
if [ "${NODE_STATUS}" == "200" ];then
|
||||
if [ $TIME_TOTAL -lt 100 ];then
|
||||
if [ $RES -ge 1500 ];then
|
||||
echo "$RES $node" >> $tmp_file1
|
||||
fi
|
||||
else
|
||||
if [ $RES -ge 1500 ];then
|
||||
echo "$TIME_TOTAL $node" >> $tmp_file2
|
||||
fi
|
||||
fi
|
||||
|
||||
i=$(($i+1))
|
||||
if [ $TIME_TOTAL -lt 100 ];then
|
||||
if [ $RES -ge 3000 ];then
|
||||
break;
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
NODE_URL=$(cat $tmp_file1|sort -r -g -t " " -k 1|head -n 1|awk '{print $2}')
|
||||
if [ -z "$NODE_URL" ];then
|
||||
NODE_URL=$(cat $tmp_file2|sort -g -t " " -k 1|head -n 1|awk '{print $2}')
|
||||
if [ -z "$NODE_URL" ];then
|
||||
NODE_URL='https://download.bt.cn';
|
||||
fi
|
||||
fi
|
||||
rm -f $tmp_file1
|
||||
rm -f $tmp_file2
|
||||
download_Url=$NODE_URL
|
||||
echo "Download node: $download_Url";
|
||||
echo '---------------------------------------------';
|
||||
}
|
||||
|
||||
Get_Versions(){
|
||||
redhat_version_file="/etc/redhat-release"
|
||||
deb_version_file="/etc/issue"
|
||||
if [ -f $redhat_version_file ];then
|
||||
os_type='el'
|
||||
is_aliyunos=$(cat $redhat_version_file|grep Aliyun)
|
||||
if [ "$is_aliyunos" != "" ];then
|
||||
return
|
||||
fi
|
||||
os_version=$(cat $redhat_version_file|grep CentOS|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '^[0-9]')
|
||||
if [ "${os_version}" = "5" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ -z "${os_version}" ];then
|
||||
os_version=$(cat /etc/redhat-release |grep Stream|grep -oE 8)
|
||||
fi
|
||||
else
|
||||
os_type='ubuntu'
|
||||
os_version=$(cat $deb_version_file|grep Ubuntu|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '^[0-9]+')
|
||||
if [ "${os_version}" = "" ];then
|
||||
os_type='debian'
|
||||
os_version=$(cat $deb_version_file|grep Debian|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '[0-9]+')
|
||||
if [ "${os_version}" = "" ];then
|
||||
os_version=$(cat $deb_version_file|grep Debian|grep -Eo '[0-9]+')
|
||||
fi
|
||||
if [ "${os_version}" = "8" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "${is64bit}" = '32' ];then
|
||||
os_version=""
|
||||
fi
|
||||
else
|
||||
if [ "$os_version" = "14" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "$os_version" = "12" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "$os_version" = "19" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "$os_version" = "21" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "$os_version" = "20" ];then
|
||||
os_version2004=$(cat /etc/issue|grep 20.04)
|
||||
if [ -z "${os_version2004}" ];then
|
||||
os_version=""
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
Install_Python_Lib(){
|
||||
curl -Ss --connect-timeout 3 -m 60 $download_Url/install/pip_select.sh|bash
|
||||
pyenv_path="/www/server/bt-monitor"
|
||||
if [ -f $pyenv_path/pyenv/bin/python ];then
|
||||
is_ssl=$($python_bin -c "import ssl" 2>&1|grep cannot)
|
||||
$pyenv_path/pyenv/bin/python3.7 -V
|
||||
if [ $? -eq 0 ] && [ -z "${is_ssl}" ];then
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
is_package=$($python_bin -m psutil 2>&1|grep package)
|
||||
if [ "$is_package" = "" ];then
|
||||
wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip.txt -t 5 -T 10
|
||||
$pyenv_path/pyenv/bin/pip install -U pip
|
||||
$pyenv_path/pyenv/bin/pip install -U setuptools
|
||||
$pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
|
||||
$pyenv_path/pyenv/bin/pip install -U flask==2.2.0
|
||||
$pyenv_path/pyenv/bin/pip install flask_sock
|
||||
$pyenv_path/pyenv/bin/pip install cachelib
|
||||
$pyenv_path/pyenv/bin/pip install py7zr
|
||||
$pyenv_path/pyenv/bin/pip install backports.lzma
|
||||
fi
|
||||
source $pyenv_path/pyenv/bin/activate
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
return
|
||||
else
|
||||
rm -rf $pyenv_path/pyenv
|
||||
fi
|
||||
fi
|
||||
|
||||
py_version="3.7.9"
|
||||
if [ ! -d "$pyenv_path" ]; then
|
||||
mkdir -p $pyenv_path
|
||||
fi
|
||||
echo "True" > /www/disk.pl
|
||||
if [ ! -w /www/disk.pl ];then
|
||||
Red_Error "ERROR: Install python env fielded." "ERROR: /www目录无法写入,请检查目录/用户/磁盘权限!"
|
||||
fi
|
||||
os_type='el'
|
||||
os_version='7'
|
||||
is_export_openssl=0
|
||||
Get_Versions
|
||||
|
||||
echo "OS: $os_type - $os_version"
|
||||
is_aarch64=$(uname -a|grep aarch64)
|
||||
if [ "$is_aarch64" != "" ];then
|
||||
is64bit="aarch64"
|
||||
fi
|
||||
|
||||
if [ -f "/www/server/bt-monitor/pymake.pl" ];then
|
||||
os_version=""
|
||||
rm -f /www/server/bt-monitor/pymake.pl
|
||||
fi
|
||||
|
||||
if [[ $os_type =~ "debian" ]] || [[ $os_type =~ "ubuntu" ]]; then
|
||||
isbtm="-btm"
|
||||
fi
|
||||
|
||||
if [ "${os_version}" != "" ];then
|
||||
pyenv_file="/www/pyenv.tar.gz"
|
||||
wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}${isbtm}.tar.gz -t 5 -T 10
|
||||
|
||||
tmp_size=$(du -b $pyenv_file|awk '{print $1}')
|
||||
if [ $tmp_size -lt 703460 ];then
|
||||
rm -f $pyenv_file
|
||||
echo "ERROR: Download python env fielded."
|
||||
else
|
||||
echo "Install python env..."
|
||||
tar zxvf $pyenv_file -C $pyenv_path/ > /dev/null
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
rm -rf $pyenv_path/pyenv/bin/python
|
||||
ln -sf $pyenv_path/pyenv/bin/python3.7 $pyenv_path/pyenv/bin/python
|
||||
$pyenv_path/pyenv/bin/python -m pip install --upgrade --force-reinstall pip
|
||||
$pyenv_path/pyenv/bin/pip install -U flask==2.2.0
|
||||
$pyenv_path/pyenv/bin/pip install flask_sock
|
||||
$pyenv_path/pyenv/bin/pip install cachelib
|
||||
$pyenv_path/pyenv/bin/pip install py7zr
|
||||
$pyenv_path/pyenv/bin/pip install backports.lzma
|
||||
if [ ! -f $pyenv_path/pyenv/bin/python ];then
|
||||
rm -f $pyenv_file
|
||||
Red_Error "ERROR: Install python env fielded." "ERROR: 下载堡塔云监控主控端运行环境失败,请尝试重新安装!"
|
||||
fi
|
||||
$pyenv_path/pyenv/bin/python3.7 -V
|
||||
if [ $? -eq 0 ];then
|
||||
rm -f $pyenv_file
|
||||
ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btmpip
|
||||
ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btmpython
|
||||
source $pyenv_path/pyenv/bin/activate
|
||||
return
|
||||
else
|
||||
rm -f $pyenv_file
|
||||
rm -rf $pyenv_path/pyenv
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
cd /www
|
||||
python_src='/www/python_src.tar.xz'
|
||||
python_src_path="/www/Python-${py_version}"
|
||||
wget -O $python_src $download_Url/src/Python-${py_version}.tar.xz -t 5 -T 10
|
||||
tmp_size=$(du -b $python_src|awk '{print $1}')
|
||||
if [ $tmp_size -lt 10703460 ];then
|
||||
rm -f $python_src
|
||||
Red_Error "ERROR: Download python source code fielded." "ERROR: 下载堡塔云监控主控端运行环境失败,请尝试重新安装!"
|
||||
fi
|
||||
tar xvf $python_src
|
||||
rm -f $python_src
|
||||
cd $python_src_path
|
||||
./configure --prefix=$pyenv_path/pyenv
|
||||
make -j$cpu_cpunt
|
||||
make install
|
||||
if [ ! -f $pyenv_path/pyenv/bin/python3.7 ];then
|
||||
rm -rf $python_src_path
|
||||
Red_Error "ERROR: Make python env fielded." "ERROR: 编译堡塔云监控主控端运行环境失败!"
|
||||
fi
|
||||
cd ~
|
||||
rm -rf $python_src_path
|
||||
wget -O $pyenv_path/pyenv/bin/activate $download_Url/install/pyenv/activate.panel -t 5 -T 10
|
||||
wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip-3.7.8.txt -t 5 -T 10
|
||||
ln -sf $pyenv_path/pyenv/bin/pip3.7 $pyenv_path/pyenv/bin/pip
|
||||
ln -sf $pyenv_path/pyenv/bin/python3.7 $pyenv_path/pyenv/bin/python
|
||||
ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btmpip
|
||||
ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btmpython
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
$pyenv_path/pyenv/bin/pip install -U pip
|
||||
$pyenv_path/pyenv/bin/pip install -U setuptools
|
||||
$pyenv_path/pyenv/bin/pip install -U wheel==0.34.2
|
||||
$pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
|
||||
$pyenv_path/pyenv/bin/pip install -U flask==2.2.0
|
||||
$pyenv_path/pyenv/bin/pip install flask_sock
|
||||
$pyenv_path/pyenv/bin/pip install cachelib
|
||||
$pyenv_path/pyenv/bin/pip install py7zr
|
||||
$pyenv_path/pyenv/bin/pip install backports.lzma
|
||||
source $pyenv_path/pyenv/bin/activate
|
||||
|
||||
is_gevent=$($python_bin -m gevent 2>&1|grep -oE package)
|
||||
is_psutil=$($python_bin -m psutil 2>&1|grep -oE package)
|
||||
if [ "${is_gevent}" != "${is_psutil}" ];then
|
||||
Red_Error "ERROR: psutil/gevent install failed!"
|
||||
fi
|
||||
}
|
||||
|
||||
Install_Monitor(){
|
||||
ulimit -n 1000001
|
||||
tee -a /etc/security/limits.conf << EOF
|
||||
* hard nofile 1000001
|
||||
* soft nofile 1000001
|
||||
root hard nofile 1000001
|
||||
root soft nofile 1000001
|
||||
EOF
|
||||
sysctl -p
|
||||
panelPort="806"
|
||||
|
||||
if [ ! -d "/etc/init.d" ];then
|
||||
mkdir -p /etc/init.d
|
||||
fi
|
||||
|
||||
if [ -f "/etc/init.d/btm" ]; then
|
||||
/etc/init.d/btm stop
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
if [ -f "/www/server/bt-monitor/sqlite-server.sh" ]; then
|
||||
chmod +x /www/server/bt-monitor/sqlite-server.sh
|
||||
/www/server/bt-monitor/sqlite-server.sh stop
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
version="2.0.8"
|
||||
file_name="bt-monitor"
|
||||
agent_src="bt-monitor.zip"
|
||||
|
||||
cd ~
|
||||
version=`curl -sf ${Btapi_Url}/bt_monitor/latest_version |awk -F '\"version\"' '{print $2}'|awk -F ':' '{print $2}'|awk -F '"' '{print $2}'`
|
||||
if [ -z $version ]; then
|
||||
version="2.0.6"
|
||||
fi
|
||||
if [ "$re_install" == "1" ]; then
|
||||
new_dir="/www/server/new_btmonitor"
|
||||
if [ ! -d "$new_dir" ];then
|
||||
mkdir -p $new_dir
|
||||
fi
|
||||
wget -O $agent_src ${Btapi_Url}/install/src/$file_name-$version.zip -t 5 -T 10
|
||||
unzip -o $agent_src -d $new_dir/ > /dev/null
|
||||
if [ ! -f $new_dir/BT-MONITOR ];then
|
||||
ls -lh $agent_src
|
||||
Red_Error "ERROR: Failed to download, please try install again!" "ERROR: 下载堡塔云监控主控端失败,请尝试重新安装!"
|
||||
fi
|
||||
|
||||
rm -rf $new_dir/config
|
||||
rm -rf $new_dir/data
|
||||
rm -rf $new_dir/ssl
|
||||
\cp -r $new_dir/* $monitor_path/
|
||||
rm -rf $new_dir
|
||||
else
|
||||
wget -O $agent_src ${Btapi_Url}/install/src/$file_name-$version.zip -t 5 -T 10
|
||||
if [ ! -d "$monitor_path" ]; then
|
||||
mkdir -p $monitor_path
|
||||
fi
|
||||
unzip -o $agent_src -d $monitor_path/ > /dev/null
|
||||
if [ ! -f $run_bin ];then
|
||||
ls -lh $agent_src
|
||||
Red_Error "ERROR: Failed to download, please try install again!" "ERROR: 下载堡塔云监控主控端失败,请尝试重新安装!"
|
||||
fi
|
||||
fi
|
||||
rm -rf $agent_src
|
||||
chmod +x $monitor_path/BT-MONITOR
|
||||
chmod +x $monitor_path/tools.py
|
||||
wget -O /etc/init.d/btm ${download_Url}/init/btmonitor.init -t 5 -T 10
|
||||
# \cp -r $monitor_path/init.sh /etc/init.d/btm
|
||||
|
||||
chmod +x /etc/init.d/btm
|
||||
ln -sf /etc/init.d/btm /usr/bin/btm
|
||||
|
||||
if [ ! -f $monitor_path/data/user.json ]; then
|
||||
echo "{\"uid\":1,\"username\":\"Administrator\",\"ip\":\"127.0.0.1\",\"server_id\":\"1\",\"access_key\":\"test\",\"secret_key\":\"123456\"}" > $monitor_path/data/user.json
|
||||
fi
|
||||
if [ -f $monitor_path/core/include/c_loader/PluginLoader.so ]; then
|
||||
rm -f $monitor_path/core/include/c_loader/PluginLoader.so
|
||||
fi
|
||||
}
|
||||
|
||||
Start_Monitor(){
|
||||
/etc/init.d/btm start
|
||||
if [ "$?" != "0" ]; then
|
||||
#echo "堡塔云监控主控端启动失败!"
|
||||
tail $monitor_path/logs/error.log
|
||||
Red_Error "堡塔云监控主控端启动失败!"
|
||||
fi
|
||||
|
||||
echo "正在初始化云监控主控端..."
|
||||
if [ "$re_install" == "1" ] || [ "$re_install" == "2" ]; then
|
||||
user_pass=`$setup_path/server/bt-monitor/tools.py reset_pwd`
|
||||
password=`echo $user_pass |awk '{print $3}'`
|
||||
else
|
||||
user_pass=`$monitor_path/tools.py create_admin`
|
||||
password=`echo $user_pass |awk -F " " '{print $5}'`
|
||||
for ((i=1; i<=5; i++));do
|
||||
if [ -z "$password" ]; then
|
||||
sleep 7
|
||||
user_pass=`$monitor_path/tools.py create_admin`
|
||||
password=`echo $user_pass |awk -F " " '{print $5}'`
|
||||
else
|
||||
i=5
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [[ "$password" == "" ]];then
|
||||
Red_Error "ERROR: 初始化云监控主控端失败,请尝试重新安装!"
|
||||
fi
|
||||
|
||||
c_path=$(cat /www/server/bt-monitor/config/config.json |awk -F '\"admin_path\"' '{print $2}'|awk -F ":" '{print $2}'|awk -F '"' '{print $2}')
|
||||
adminpath=$(echo $c_path|awk -F ',' '{print $1}')
|
||||
|
||||
if [ -d "/usr/bin/btmonitoragent" ];then
|
||||
rm -rf /usr/bin/btmonitoragent
|
||||
fi
|
||||
|
||||
date_f=`date '+%Y%m%d_%H%M%S'`
|
||||
md5_pl=`echo $date_f | md5sum | head -c 32`
|
||||
token_pl=`cat $monitor_path/config/token.pl 2>&1`
|
||||
if [ "$token_pl" == ' ' ] || [ ! -f $monitor_path/config/token.pl ]; then
|
||||
echo "$md5_pl" > $monitor_path/config/token.pl
|
||||
fi
|
||||
|
||||
echo "正在给本机安装云监控被控端,请等待..."
|
||||
sleep 15
|
||||
curl -sSO ${download_Url}/install/btmonitoragent.sh && bash btmonitoragent.sh https://127.0.0.1:806 $md5_pl
|
||||
target_dir="/usr/local/btmonitoragent"
|
||||
if [ ! -f "$target_dir/BT-MonitorAgent" ];then
|
||||
tail -n 10 ${monitor_path}/logs/error.log
|
||||
echo ""
|
||||
ps aux|grep -v grep|grep ${monitor_path}
|
||||
netstat -tulnp|grep ${panelPort}
|
||||
/etc/init.d/btm restart
|
||||
if [ "$?" -eq 0 ]; then
|
||||
echo -e "\033[31m安装云监控被控端失败,正在尝试重新安装!\033[0m"
|
||||
sleep 15
|
||||
curl -sSO ${download_Url}/install/btmonitoragent.sh && bash btmonitoragent.sh https://127.0.0.1:806 $md5_pl
|
||||
if [ ! -f "$target_dir/BT-MonitorAgent" ];then
|
||||
Red_Error "ERROR: 安装云监控被控端失败,请尝试重新安装!"
|
||||
fi
|
||||
else
|
||||
Red_Error "ERROR: 安装云监控被控端失败,请尝试重新安装!"
|
||||
fi
|
||||
fi
|
||||
/etc/init.d/btm restart > /dev/null 2>&1
|
||||
|
||||
}
|
||||
|
||||
Set_Firewall(){
|
||||
sshPort=$(cat /etc/ssh/sshd_config | grep 'Port '|awk '{print $2}')
|
||||
if [ "${PM}" = "apt-get" ]; then
|
||||
apt-get install -y ufw
|
||||
if [ -f "/usr/sbin/ufw" ];then
|
||||
ufw allow 22/tcp
|
||||
ufw allow ${panelPort}/tcp
|
||||
ufw allow ${sshPort}/tcp
|
||||
ufw_status=`ufw status`
|
||||
echo y|ufw enable
|
||||
ufw default deny
|
||||
ufw reload
|
||||
fi
|
||||
else
|
||||
if [ -f "/etc/init.d/iptables" ];then
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ${panelPort} -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ${sshPort} -j ACCEPT
|
||||
iptables -A INPUT -p icmp --icmp-type any -j ACCEPT
|
||||
iptables -A INPUT -s localhost -d localhost -j ACCEPT
|
||||
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
iptables -P INPUT DROP
|
||||
service iptables save
|
||||
sed -i "s#IPTABLES_MODULES=\"\"#IPTABLES_MODULES=\"ip_conntrack_netbios_ns ip_conntrack_ftp ip_nat_ftp\"#" /etc/sysconfig/iptables-config
|
||||
iptables_status=$(service iptables status | grep 'not running')
|
||||
if [ "${iptables_status}" == '' ];then
|
||||
service iptables restart
|
||||
fi
|
||||
else
|
||||
AliyunCheck=$(cat /etc/redhat-release|grep "Aliyun Linux")
|
||||
[ "${AliyunCheck}" ] && return
|
||||
yum install firewalld -y
|
||||
[ "${Centos8Check}" ] && yum reinstall python3-six -y
|
||||
systemctl enable firewalld
|
||||
systemctl start firewalld
|
||||
firewall-cmd --set-default-zone=public > /dev/null 2>&1
|
||||
firewall-cmd --permanent --zone=public --add-port=22/tcp > /dev/null 2>&1
|
||||
firewall-cmd --permanent --zone=public --add-port=${panelPort}/tcp > /dev/null 2>&1
|
||||
firewall-cmd --permanent --zone=public --add-port=${sshPort}/tcp > /dev/null 2>&1
|
||||
firewall-cmd --reload
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
Service_Add(){
|
||||
if [ $Command_Exists systemctl ]; then
|
||||
wget -O /usr/lib/systemd/system/btm.service ${download_Url}/init/systemd/btmonitor.service -t 5 -T 10
|
||||
systemctl daemon-reload
|
||||
systemctl enable btm
|
||||
else
|
||||
if [ "${PM}" == "yum" ] || [ "${PM}" == "dnf" ]; then
|
||||
chkconfig --add btm
|
||||
chkconfig --level 2345 btm on
|
||||
elif [ "${PM}" == "apt-get" ]; then
|
||||
update-rc.d btm defaults
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
Service_Del(){
|
||||
if [ $Command_Exists systemctl ]; then
|
||||
rm -rf /usr/lib/systemd/system/btm.service
|
||||
systemctl disable btm
|
||||
else
|
||||
if [ "${PM}" == "yum" ] || [ "${PM}" == "dnf" ]; then
|
||||
chkconfig --del btm
|
||||
chkconfig --level 2345 btm off
|
||||
elif [ "${PM}" == "apt-get" ]; then
|
||||
update-rc.d btm remove
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
Get_Ip_Address(){
|
||||
getIpAddress=""
|
||||
getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress)
|
||||
if [ -z "${getIpAddress}" ] || [ "${getIpAddress}" = "0.0.0.0" ]; then
|
||||
isHosts=$(cat /etc/hosts|grep 'www.bt.cn')
|
||||
if [ -z "${isHosts}" ];then
|
||||
echo "" >> /etc/hosts
|
||||
echo "116.213.43.206 www.bt.cn" >> /etc/hosts
|
||||
getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress)
|
||||
if [ -z "${getIpAddress}" ];then
|
||||
sed -i "/bt.cn/d" /etc/hosts
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
ipv4Check=$($python_bin -c "import re; print(re.match('^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$','${getIpAddress}'))")
|
||||
if [ "${ipv4Check}" == "None" ];then
|
||||
ipv6Address=$(echo ${getIpAddress}|tr -d "[]")
|
||||
ipv6Check=$($python_bin -c "import re; print(re.match('^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$','${ipv6Address}'))")
|
||||
if [ "${ipv6Check}" == "None" ]; then
|
||||
getIpAddress="SERVER_IP"
|
||||
else
|
||||
echo "True" > ${setup_path}/server/bt-monitor/data/ipv6.pl
|
||||
sleep 1
|
||||
/etc/init.d/btm restart
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${getIpAddress}" != "SERVER_IP" ];then
|
||||
echo "${getIpAddress}" > ${setup_path}/server/bt-monitor/data/iplist.txt
|
||||
fi
|
||||
LOCAL_IP=$(ip addr | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -E -v "^127\.|^255\.|^0\." | head -n 1)
|
||||
}
|
||||
|
||||
System_Check(){
|
||||
if [ -f "$monitor_path/BT-MONITOR" ] || [ -f "$monitor_path/tools.py" ] || [ -f "/etc/init.d/btm" ];then
|
||||
Install_Check
|
||||
elif [ -d "$old_dir" ];then
|
||||
Rev_Install_Check
|
||||
fi
|
||||
}
|
||||
|
||||
Install_Check(){
|
||||
echo -e "----------------------------------------------------"
|
||||
echo -e "检测到已存在堡塔云监控系统,请按照选项选择安装方式!"
|
||||
echo -e "1) 覆盖安装:保存原有监控配置及数据并安装堡塔云监控"
|
||||
echo -e "\033[33m2) 全新安装:清空原有监控配置及数据并安装堡塔云监控\033[0m"
|
||||
echo -e "----------------------------------------------------"
|
||||
read -p "请输入对应选项[1|2]进行安装或输入任意内容退出安装: " yes;
|
||||
if [ "$yes" == "1" ]; then
|
||||
re_install="1"
|
||||
echo "即将卸载并重装本机的堡塔云监控被控端..."
|
||||
Uninstall_agent
|
||||
elif [ "$yes" == "2" ]; then
|
||||
Backup_Monitor
|
||||
echo "即将卸载并重装本机的堡塔云监控被控端..."
|
||||
Uninstall_agent
|
||||
else
|
||||
echo -e "------------"
|
||||
echo "取消安装"
|
||||
exit;
|
||||
fi
|
||||
}
|
||||
|
||||
Rev_Install_Check(){
|
||||
echo -e "----------------------------------------------------"
|
||||
echo -e "\033[33m检测到上一次卸载云监控时保留的旧数据,请按照选项选择安装方式!\033[0m"
|
||||
echo -e "1) 还原以前的备份并安装堡塔云监控系统!"
|
||||
echo -e "2) 不使用原有备份,全新安装堡塔云监控系统!"
|
||||
echo -e "----------------------------------------------------"
|
||||
read -p "请输入对应选项[1|2]进行安装或输入任意内容退出安装: " yes;
|
||||
if [ "$yes" == "1" ]; then
|
||||
re_install="2"
|
||||
echo "开始安装堡塔云监控系统并还原数据..."
|
||||
elif [ "$yes" == "2" ]; then
|
||||
echo "开始全新安装堡塔云监控系统..."
|
||||
else
|
||||
echo -e "------------"
|
||||
echo "取消安装"
|
||||
exit;
|
||||
fi
|
||||
}
|
||||
|
||||
Backup_Monitor(){
|
||||
if [ -f "/etc/init.d/btm" ]; then
|
||||
/etc/init.d/btm stop
|
||||
sleep 1
|
||||
fi
|
||||
if [ ! -d "${old_dir}" ];then
|
||||
mkdir -p ${old_dir}
|
||||
else
|
||||
mv ${old_dir} ${old_dir}_$(date +%Y_%m_%d_%H_%M_%S)
|
||||
mkdir -p ${old_dir}
|
||||
fi
|
||||
|
||||
mv ${monitor_path}/data ${old_dir}/data
|
||||
mv ${monitor_path}/config ${old_dir}/config
|
||||
mv ${monitor_path}/ssl ${old_dir}/ssl
|
||||
}
|
||||
|
||||
Reinstall_Monitor(){
|
||||
rm -rf $monitor_path/data
|
||||
rm -rf $monitor_path/config
|
||||
rm -rf $monitor_path/ssl
|
||||
mv $old_dir/data $monitor_path/data
|
||||
mv $old_dir/config $monitor_path/config
|
||||
mv $old_dir/ssl $monitor_path/ssl
|
||||
rm -rf $old_dir
|
||||
}
|
||||
|
||||
Get_Pack_Manager(){
|
||||
if [ -f "/usr/bin/yum" ] && [ -d "/etc/yum.repos.d" ]; then
|
||||
PM="yum"
|
||||
elif [ -f "/usr/bin/apt-get" ] && [ -f "/usr/bin/dpkg" ]; then
|
||||
PM="apt-get"
|
||||
fi
|
||||
}
|
||||
|
||||
Install_RPM_Pack(){
|
||||
yumPacks="wget curl unzip gcc gcc-c++ make libcurl-devel openssl-devel xz-devel python-backports-lzma xz crontabs zlib zlib-devel sqlite-devel libffi-devel bzip2-devel lsof net-tools"
|
||||
yum install -y ${yumPacks}
|
||||
|
||||
for yumPack in ${yumPacks}
|
||||
do
|
||||
rpmPack=$(rpm -q ${yumPack})
|
||||
packCheck=$(echo ${rpmPack}|grep not)
|
||||
if [ "${packCheck}" ]; then
|
||||
yum install ${yumPack} -y
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
Install_Deb_Pack(){
|
||||
debPacks="wget curl unzip gcc g++ make cron libcurl4-openssl-dev libssl-dev liblzma-dev xz-utils libffi-dev libbz2-dev libsqlite3-dev libreadline-dev libgdbm-dev python3-bsddb3 tk-dev ncurses-dev uuid-dev zlib1g zlib1g-dev lsof net-tools";
|
||||
apt-get update -y
|
||||
apt-get install -y $debPacks --force-yes
|
||||
|
||||
for debPack in ${debPacks}
|
||||
do
|
||||
packCheck=$(dpkg -l ${debPack})
|
||||
if [ "$?" -ne "0" ] ;then
|
||||
apt-get install -y $debPack
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
Check_Sys_Write(){
|
||||
echo "正在检测系统关键目录是否可写"
|
||||
if [ ! -d "/etc/init.d" ];then
|
||||
mkdir -p /etc/init.d
|
||||
fi
|
||||
if [ -f /usr/bin/which ];then
|
||||
Get_Pack_Manager
|
||||
if [ "$PM" == "yum" ]; then
|
||||
read_dir="/usr/lib/systemd/system/ /etc/init.d/ /var/spool/cron/"
|
||||
else
|
||||
read_dir="/usr/lib/systemd/system/ /etc/init.d/ /var/spool/cron/crontabs/"
|
||||
fi
|
||||
|
||||
for dir in ${read_dir[@]}
|
||||
do
|
||||
if [[ -d "$dir" ]]; then
|
||||
touch $dir/btm_install_test_111.pl
|
||||
state=$(echo $?)
|
||||
if [[ "$state" != "0" ]];then
|
||||
echo -e "\033[31m错误:检测到系统关键目录不可写! $read_dir \033[0m"
|
||||
echo "1、如果安装了[宝塔系统加固],请先临时关闭"
|
||||
echo "2、如果安装了云锁,请临时关闭[系统加固]功能"
|
||||
echo "3、如果安装了安全狗,请临时关闭[系统防护]功能"
|
||||
echo "4、如果使用了其它安全软件,请先卸载 "
|
||||
echo -e "5、如果使用了禁止写入命令,请执行命令取消禁止写入:\n chattr -iaR $read_dir "
|
||||
echo ""
|
||||
echo -e "\033[31m解决以上问题后,请尝试重新安装! \033[0m"
|
||||
echo -e "如果无法解决请截图以上报错信息发帖至论坛www.bt.cn/bbs求助"
|
||||
exit 1
|
||||
else
|
||||
rm -f $dir/btm_install_test_111.pl
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
Check_Sys_Packs(){
|
||||
echo "正在检查系统中是否存在必备的依赖包"
|
||||
Packs="wget curl unzip gcc make"
|
||||
for pack in ${Packs[@]}
|
||||
do
|
||||
check_pack=$(which $pack)
|
||||
#echo $check_pack
|
||||
if [[ "$check_pack" == "" ]]; then
|
||||
echo -e "\033[31mERROR: $pack 命令不存在,尝试以下解决方法:\033[0m"
|
||||
if [ "$PM" == "yum" ]; then
|
||||
echo 1、使用命令重新安装依赖包:yum reinstall -y ${Packs}
|
||||
else
|
||||
echo 1、使用命令重新安装依赖包:apt-get reinstall -y ${Packs}
|
||||
fi
|
||||
echo -e "2、检查系统源是否可用?尝试更换可用的源参考教程:\n https://www.bt.cn/bbs/thread-58005-1-1.html "
|
||||
echo ""
|
||||
echo -e "\033[31m解决以上问题后,请尝试重新安装! \033[0m"
|
||||
echo -e "如果无法解决请截图以上报错信息发帖至论坛www.bt.cn/bbs求助"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
Install_Main(){
|
||||
startTime=`date +%s`
|
||||
Check_Sys_Write
|
||||
System_Check
|
||||
Get_Pack_Manager
|
||||
get_node_url
|
||||
|
||||
if [ "$PM" == "yum" ]; then
|
||||
Install_RPM_Pack
|
||||
else
|
||||
Install_Deb_Pack
|
||||
fi
|
||||
Check_Sys_Packs
|
||||
Install_Python_Lib
|
||||
Install_Monitor
|
||||
Set_Firewall
|
||||
Get_Ip_Address
|
||||
Service_Add
|
||||
if [ "$re_install" == "2" ]; then
|
||||
Reinstall_Monitor
|
||||
fi
|
||||
Start_Monitor
|
||||
}
|
||||
|
||||
Uninstall_Monitor(){
|
||||
pkill BT-MONITOR
|
||||
/etc/init.d/btm stop
|
||||
|
||||
if [ -f "/www/server/bt-monitor/sqlite-server.sh" ]; then
|
||||
chmod +x /www/server/bt-monitor/sqlite-server.sh
|
||||
/www/server/bt-monitor/sqlite-server.sh stop
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
Service_Del
|
||||
|
||||
rm -rf $monitor_path
|
||||
rm -rf /usr/bin/btm
|
||||
rm -rf /etc/init.d/btm
|
||||
|
||||
echo -e "堡塔云监控主控端卸载成功!"
|
||||
}
|
||||
|
||||
Uninstall_agent(){
|
||||
get_node_url
|
||||
if [ -f "/tmp/btmonitoragent.sh" ];then
|
||||
rm -rf /tmp/btmonitoragent.sh
|
||||
fi
|
||||
curl -o /tmp/btmonitoragent.sh -sSO ${download_Url}/install/btmonitoragent.sh && bash /tmp/btmonitoragent.sh uninstall
|
||||
}
|
||||
|
||||
action="${1}"
|
||||
if [ "$action" == "uninstall" ];then
|
||||
echo -e "----------------------------------------------------"
|
||||
echo -e "\033[33m检测到您正在卸载堡塔云监控系统,请按照选项选择卸载方式!\033[0m"
|
||||
echo -e "1) 备份数据后卸载:保存原有监控配置及数据并卸载堡塔云监控系统"
|
||||
echo -e "2) 完全卸载:清空原有监控配置及数据并卸载堡塔云监控系统"
|
||||
echo -e "----------------------------------------------------"
|
||||
read -p "请输入对应选项[1|2]进行卸载或输入任意内容退出卸载: " yes;
|
||||
if [ "$yes" == "1" ]; then
|
||||
Backup_Monitor
|
||||
echo -e "----------------------------------------------------"
|
||||
echo -e "\033[33m已备份原有监控数据至: ${old_dir}\033[0m"
|
||||
elif [ "$yes" == "2" ]; then
|
||||
echo "正在清空堡塔云监控系统数据..."
|
||||
else
|
||||
echo -e "------------"
|
||||
echo "取消卸载"
|
||||
exit;
|
||||
fi
|
||||
Uninstall_agent
|
||||
Uninstall_Monitor
|
||||
exit 0
|
||||
else
|
||||
echo "
|
||||
+----------------------------------------------------------------------
|
||||
| Bt-Monitor FOR CentOS/Ubuntu/Debian
|
||||
+----------------------------------------------------------------------
|
||||
| Copyright © 2015-2099 BT-SOFT(https://www.bt.cn) All rights reserved.
|
||||
+----------------------------------------------------------------------
|
||||
| The Monitor URL will be https://SERVER_IP:806 when installed.
|
||||
+----------------------------------------------------------------------
|
||||
"
|
||||
while [ "$go" != 'y' ] && [ "$go" != 'n' ]
|
||||
do
|
||||
read -p "Do you want to install Bt-Monitor to the $setup_path directory now?(y/n): " go;
|
||||
done
|
||||
|
||||
if [ "$go" == 'n' ];then
|
||||
exit;
|
||||
fi
|
||||
Install_Main
|
||||
#curl -o /dev/null -fsSL --connect-time 10 "https://api.bt.cn/bt_monitor/setup_count?cloud_type=1&token=$md5_pl&src_code=$1"
|
||||
#curl -o /dev/null -fsSL --connect-time 10 "https://api.bt.cn/bt_monitor/setup_count?cloud_type=1&token=$md5_pl&src_code=$1&status=1"
|
||||
|
||||
fi
|
||||
echo -e "=================================================================="
|
||||
echo -e "\033[32m堡塔云监控主控端安装完成! Installed successfully!\033[0m"
|
||||
echo -e "=================================================================="
|
||||
echo "外网访问地址: https://${getIpAddress}:${panelPort}${adminpath}"
|
||||
echo "内网访问地址: https://${LOCAL_IP}:${panelPort}${adminpath}"
|
||||
echo -e "username: admin"
|
||||
echo -e "password: $password"
|
||||
echo -e "\033[33mIf you cannot access the Monitor,\033[0m"
|
||||
echo -e "\033[33mrelease the following Monitor port [${panelPort}] in the security group\033[0m"
|
||||
echo -e "\033[33m若无法访问堡塔云监控主控端,请检查防火墙/安全组是否有放行[${panelPort}]端口\033[0m"
|
||||
echo -e "=================================================================="
|
||||
|
||||
endTime=`date +%s`
|
||||
((outTime=($endTime-$startTime)/60))
|
||||
echo -e "Time consumed:\033[32m $outTime \033[0mMinute!"
|
@@ -10,7 +10,7 @@ export LANG=en_US.UTF-8
|
||||
export LANGUAGE=en_US:en
|
||||
|
||||
get_node_url(){
|
||||
nodes=(http://dg2.bt.cn http://dg1.bt.cn http://36.133.1.8:5880 http://123.129.198.197 http://38.34.185.130 http://116.213.43.206:5880 http://128.1.164.196);
|
||||
nodes=(https://dg2.bt.cn https://download.bt.cn https://ctcc1-node.bt.cn https://cmcc1-node.bt.cn https://ctcc2-node.bt.cn https://hk1-node.bt.cn https://na1-node.bt.cn https://jp1-node.bt.cn);
|
||||
|
||||
if [ "$1" ];then
|
||||
nodes=($(echo ${nodes[*]}|sed "s#${1}##"))
|
||||
@@ -29,7 +29,7 @@ get_node_url(){
|
||||
NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $2}')
|
||||
TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $3 * 1000 - 500 }'|cut -d '.' -f 1)
|
||||
if [ "${NODE_STATUS}" == "200" ];then
|
||||
if [ $TIME_TOTAL -lt 100 ];then
|
||||
if [ $TIME_TOTAL -lt 300 ];then
|
||||
if [ $RES -ge 1500 ];then
|
||||
echo "$RES $node" >> $tmp_file1
|
||||
fi
|
||||
@@ -40,7 +40,7 @@ get_node_url(){
|
||||
fi
|
||||
|
||||
i=$(($i+1))
|
||||
if [ $TIME_TOTAL -lt 100 ];then
|
||||
if [ $TIME_TOTAL -lt 200 ];then
|
||||
if [ $RES -ge 3000 ];then
|
||||
break;
|
||||
fi
|
||||
@@ -52,7 +52,7 @@ get_node_url(){
|
||||
if [ -z "$NODE_URL" ];then
|
||||
NODE_URL=$(cat $tmp_file2|sort -g -t " " -k 1|head -n 1|awk '{print $2}')
|
||||
if [ -z "$NODE_URL" ];then
|
||||
NODE_URL='http://download.bt.cn';
|
||||
NODE_URL='https://download.bt.cn';
|
||||
fi
|
||||
fi
|
||||
rm -f $tmp_file1
|
||||
@@ -108,7 +108,7 @@ send_check(){
|
||||
chmod +x /etc/init.d/bt
|
||||
p_path2=/www/server/panel/class/common.py
|
||||
p_version=$(cat $p_path2|grep "version = "|awk '{print $3}'|tr -cd [0-9.])
|
||||
curl -sS --connect-timeout 3 -m 60 http://www.bt.cn/api/panel/notpro?version=$p_version
|
||||
curl -sS --connect-timeout 3 -m 60 https://www.bt.cn/api/panel/notpro?version=$p_version
|
||||
NODE_URL=""
|
||||
exit 0;
|
||||
}
|
||||
@@ -147,3 +147,4 @@ if [ ! $NODE_URL ];then
|
||||
get_node_url
|
||||
fi
|
||||
|
||||
|
||||
|
BIN
public/install/src/bt-monitor-2.1.1.zip
Normal file
BIN
public/install/src/bt-monitor-2.1.1.zip
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -12,16 +12,16 @@ if [ ! -d /www/server/panel/BTPanel ];then
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
if [ ! -f "/www/server/panel/pyenv/bin/python3" ];then
|
||||
echo "============================================="
|
||||
echo "错误, 当前面板过旧/py-2.7/无pyenv环境,无法升级至最新版面板"
|
||||
echo "请截图发帖至论坛www.bt.cn/bbs求助"
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
public_file=/www/server/panel/install/public.sh
|
||||
publicFileMd5=$(md5sum ${public_file} 2>/dev/null|awk '{print $1}')
|
||||
md5check="f6ccaaec227577b87a22bf162004667b"
|
||||
if [ "${publicFileMd5}" != "${md5check}" ]; then
|
||||
if [ ! -f $public_file ];then
|
||||
wget -O Tpublic.sh $Btapi_Url/install/public.sh -T 20;
|
||||
publicFileMd5=$(md5sum Tpublic.sh 2>/dev/null|awk '{print $1}')
|
||||
if [ "${publicFileMd5}" == "${md5check}" ]; then
|
||||
\cp -rpa Tpublic.sh $public_file
|
||||
fi
|
||||
rm -f Tpublic.sh
|
||||
fi
|
||||
. $public_file
|
||||
|
||||
@@ -42,7 +42,7 @@ download_Url=$NODE_URL
|
||||
setup_path=/www
|
||||
version=$(curl -Ss --connect-timeout 5 -m 2 $Btapi_Url/api/panel/get_version)
|
||||
if [ "$version" = '' ];then
|
||||
version='7.9.3'
|
||||
version='7.9.9'
|
||||
fi
|
||||
armCheck=$(uname -m|grep arm)
|
||||
if [ "${armCheck}" ];then
|
||||
|
446
public/install/update_btmonitor.sh
Normal file
446
public/install/update_btmonitor.sh
Normal file
@@ -0,0 +1,446 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
LANG=en_US.UTF-8
|
||||
|
||||
Btapi_Url='http://www.example.com'
|
||||
|
||||
monitor_path="/www/server/bt-monitor"
|
||||
run_bin="/www/server/bt-monitor/BT-MONITOR"
|
||||
is64bit=$(getconf LONG_BIT)
|
||||
|
||||
if [ ! -d $monitor_path ]; then
|
||||
echo "没有安装云监控,请执行下面的命令安装堡塔云监控!"
|
||||
echo "curl -sSO ${Btapi_Url}/install/install_btmonitor.sh && bash install_btmonitor.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd ~
|
||||
setup_path="/www"
|
||||
|
||||
if [ -f "/etc/init.d/btm" ]; then
|
||||
/etc/init.d/btm stop
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
if [ -f "/www/server/bt-monitor/sqlite-server.sh" ]; then
|
||||
chmod +x /www/server/bt-monitor/sqlite-server.sh
|
||||
/www/server/bt-monitor/sqlite-server.sh stop
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
get_node_url(){
|
||||
if [ ! -f /bin/curl ];then
|
||||
if [ "${PM}" = "yum" ]; then
|
||||
yum install curl -y
|
||||
elif [ "${PM}" = "apt-get" ]; then
|
||||
apt-get install curl -y
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "/www/node.pl" ];then
|
||||
download_Url=$(cat /www/node.pl)
|
||||
echo "Download node: $download_Url";
|
||||
echo '---------------------------------------------';
|
||||
return
|
||||
fi
|
||||
|
||||
echo '---------------------------------------------';
|
||||
echo "Selected download node...";
|
||||
# nodes=(http://dg2.bt.cn http://dg1.bt.cn http://125.90.93.52:5880 http://36.133.1.8:5880 http://123.129.198.197 http://38.34.185.130 http://116.213.43.206:5880 http://128.1.164.196);
|
||||
#nodes=(http://dg2.bt.cn http://dg1.bt.cn http://125.90.93.52:5880 http://36.133.1.8:5880 http://123.129.198.197 http://116.213.43.206:5880);
|
||||
nodes=(https://dg2.bt.cn https://dg1.bt.cn https://download.bt.cn);
|
||||
tmp_file1=/dev/shm/net_test1.pl
|
||||
tmp_file2=/dev/shm/net_test2.pl
|
||||
[ -f "${tmp_file1}" ] && rm -f ${tmp_file1}
|
||||
[ -f "${tmp_file2}" ] && rm -f ${tmp_file2}
|
||||
touch $tmp_file1
|
||||
touch $tmp_file2
|
||||
for node in ${nodes[@]};
|
||||
do
|
||||
NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/net_test|xargs)
|
||||
RES=$(echo ${NODE_CHECK}|awk '{print $1}')
|
||||
NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $2}')
|
||||
TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $3 * 1000 - 500 }'|cut -d '.' -f 1)
|
||||
if [ "${NODE_STATUS}" == "200" ];then
|
||||
if [ $TIME_TOTAL -lt 100 ];then
|
||||
if [ $RES -ge 1500 ];then
|
||||
echo "$RES $node" >> $tmp_file1
|
||||
fi
|
||||
else
|
||||
if [ $RES -ge 1500 ];then
|
||||
echo "$TIME_TOTAL $node" >> $tmp_file2
|
||||
fi
|
||||
fi
|
||||
|
||||
i=$(($i+1))
|
||||
if [ $TIME_TOTAL -lt 100 ];then
|
||||
if [ $RES -ge 3000 ];then
|
||||
break;
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
NODE_URL=$(cat $tmp_file1|sort -r -g -t " " -k 1|head -n 1|awk '{print $2}')
|
||||
if [ -z "$NODE_URL" ];then
|
||||
NODE_URL=$(cat $tmp_file2|sort -g -t " " -k 1|head -n 1|awk '{print $2}')
|
||||
if [ -z "$NODE_URL" ];then
|
||||
NODE_URL='https://download.bt.cn';
|
||||
fi
|
||||
fi
|
||||
rm -f $tmp_file1
|
||||
rm -f $tmp_file2
|
||||
download_Url=$NODE_URL
|
||||
echo "Download node: $download_Url";
|
||||
echo '---------------------------------------------';
|
||||
}
|
||||
|
||||
Get_Versions(){
|
||||
redhat_version_file="/etc/redhat-release"
|
||||
deb_version_file="/etc/issue"
|
||||
if [ -f $redhat_version_file ];then
|
||||
os_type='el'
|
||||
is_aliyunos=$(cat $redhat_version_file|grep Aliyun)
|
||||
if [ "$is_aliyunos" != "" ];then
|
||||
return
|
||||
fi
|
||||
os_version=$(cat $redhat_version_file|grep CentOS|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '^[0-9]')
|
||||
if [ "${os_version}" = "5" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ -z "${os_version}" ];then
|
||||
os_version=$(cat /etc/redhat-release |grep Stream|grep -oE 8)
|
||||
fi
|
||||
else
|
||||
os_type='ubuntu'
|
||||
os_version=$(cat $deb_version_file|grep Ubuntu|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '^[0-9]+')
|
||||
if [ "${os_version}" = "" ];then
|
||||
os_type='debian'
|
||||
os_version=$(cat $deb_version_file|grep Debian|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '[0-9]+')
|
||||
if [ "${os_version}" = "" ];then
|
||||
os_version=$(cat $deb_version_file|grep Debian|grep -Eo '[0-9]+')
|
||||
fi
|
||||
if [ "${os_version}" = "8" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "${is64bit}" = '32' ];then
|
||||
os_version=""
|
||||
fi
|
||||
else
|
||||
if [ "$os_version" = "14" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "$os_version" = "12" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "$os_version" = "19" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "$os_version" = "21" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "$os_version" = "20" ];then
|
||||
os_version2004=$(cat /etc/issue|grep 20.04)
|
||||
if [ -z "${os_version2004}" ];then
|
||||
os_version=""
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
Install_Python_Lib(){
|
||||
curl -Ss --connect-timeout 3 -m 60 $download_Url/install/pip_select.sh|bash
|
||||
pyenv_path="/www/server/bt-monitor"
|
||||
if [ -f $pyenv_path/pyenv/bin/python ];then
|
||||
is_ssl=$($python_bin -c "import ssl" 2>&1|grep cannot)
|
||||
$pyenv_path/pyenv/bin/python3.7 -V
|
||||
if [ $? -eq 0 ] && [ -z "${is_ssl}" ];then
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
is_package=$($python_bin -m psutil 2>&1|grep package)
|
||||
if [ "$is_package" = "" ];then
|
||||
wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip.txt -t 5 -T 10
|
||||
$pyenv_path/pyenv/bin/pip install -U pip
|
||||
$pyenv_path/pyenv/bin/pip install -U setuptools
|
||||
$pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
|
||||
$pyenv_path/pyenv/bin/pip install -U flask==2.2.0
|
||||
$pyenv_path/pyenv/bin/pip install flask_sock
|
||||
$pyenv_path/pyenv/bin/pip install cachelib
|
||||
$pyenv_path/pyenv/bin/pip install py7zr
|
||||
$pyenv_path/pyenv/bin/pip install backports.lzma
|
||||
fi
|
||||
source $pyenv_path/pyenv/bin/activate
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
return
|
||||
else
|
||||
rm -rf $pyenv_path/pyenv
|
||||
fi
|
||||
fi
|
||||
|
||||
py_version="3.7.9"
|
||||
if [ ! -d "$pyenv_path" ]; then
|
||||
mkdir -p $pyenv_path
|
||||
fi
|
||||
echo "True" > /www/disk.pl
|
||||
if [ ! -w /www/disk.pl ];then
|
||||
Red_Error "ERROR: Install python env fielded." "ERROR: /www目录无法写入,请检查目录/用户/磁盘权限!"
|
||||
fi
|
||||
os_type='el'
|
||||
os_version='7'
|
||||
is_export_openssl=0
|
||||
Get_Versions
|
||||
|
||||
echo "OS: $os_type - $os_version"
|
||||
is_aarch64=$(uname -a|grep aarch64)
|
||||
if [ "$is_aarch64" != "" ];then
|
||||
is64bit="aarch64"
|
||||
fi
|
||||
|
||||
if [ -f "/www/server/bt-monitor/pymake.pl" ];then
|
||||
os_version=""
|
||||
rm -f /www/server/bt-monitor/pymake.pl
|
||||
fi
|
||||
|
||||
if [[ $os_type =~ "debian" ]] || [[ $os_type =~ "ubuntu" ]]; then
|
||||
isbtm="-btm"
|
||||
fi
|
||||
|
||||
if [ "${os_version}" != "" ];then
|
||||
pyenv_file="/www/pyenv.tar.gz"
|
||||
wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}${isbtm}.tar.gz -t 5 -T 10
|
||||
tmp_size=$(du -b $pyenv_file|awk '{print $1}')
|
||||
if [ $tmp_size -lt 703460 ];then
|
||||
rm -f $pyenv_file
|
||||
echo "ERROR: Download python env fielded."
|
||||
else
|
||||
echo "Install python env..."
|
||||
tar zxvf $pyenv_file -C $pyenv_path/ > /dev/null
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
rm -rf $pyenv_path/pyenv/bin/python
|
||||
ln -sf $pyenv_path/pyenv/bin/python3.7 $pyenv_path/pyenv/bin/python
|
||||
$pyenv_path/pyenv/bin/python -m pip install --upgrade --force-reinstall pip
|
||||
$pyenv_path/pyenv/bin/pip install -U flask==2.2.0
|
||||
$pyenv_path/pyenv/bin/pip install flask_sock
|
||||
$pyenv_path/pyenv/bin/pip install cachelib
|
||||
$pyenv_path/pyenv/bin/pip install py7zr
|
||||
$pyenv_path/pyenv/bin/pip install backports.lzma
|
||||
if [ ! -f $pyenv_path/pyenv/bin/python ];then
|
||||
rm -f $pyenv_file
|
||||
Red_Error "ERROR: Install python env fielded." "ERROR: 下载堡塔云监控运行环境失败,请尝试重新安装!"
|
||||
fi
|
||||
$pyenv_path/pyenv/bin/python3.7 -V
|
||||
if [ $? -eq 0 ];then
|
||||
rm -f $pyenv_file
|
||||
ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btmpip
|
||||
ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btmpython
|
||||
source $pyenv_path/pyenv/bin/activate
|
||||
return
|
||||
else
|
||||
rm -f $pyenv_file
|
||||
rm -rf $pyenv_path/pyenv
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
cd /www
|
||||
python_src='/www/python_src.tar.xz'
|
||||
python_src_path="/www/Python-${py_version}"
|
||||
wget -O $python_src $download_Url/src/Python-${py_version}.tar.xz -t 5 -T 10
|
||||
tmp_size=$(du -b $python_src|awk '{print $1}')
|
||||
if [ $tmp_size -lt 10703460 ];then
|
||||
rm -f $python_src
|
||||
Red_Error "ERROR: Download python source code fielded." "ERROR: 下载堡塔云监控运行环境失败,请尝试重新安装!"
|
||||
fi
|
||||
tar xvf $python_src
|
||||
rm -f $python_src
|
||||
cd $python_src_path
|
||||
./configure --prefix=$pyenv_path/pyenv
|
||||
make -j$cpu_cpunt
|
||||
make install
|
||||
if [ ! -f $pyenv_path/pyenv/bin/python3.7 ];then
|
||||
rm -rf $python_src_path
|
||||
Red_Error "ERROR: Make python env fielded." "ERROR: 编译堡塔云监控运行环境失败!"
|
||||
fi
|
||||
cd ~
|
||||
rm -rf $python_src_path
|
||||
wget -O $pyenv_path/pyenv/bin/activate $download_Url/install/pyenv/activate.panel -t 5 -T 10
|
||||
wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip-3.7.8.txt -t 5 -T 10
|
||||
ln -sf $pyenv_path/pyenv/bin/pip3.7 $pyenv_path/pyenv/bin/pip
|
||||
ln -sf $pyenv_path/pyenv/bin/python3.7 $pyenv_path/pyenv/bin/python
|
||||
ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btmpip
|
||||
ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btmpython
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
$pyenv_path/pyenv/bin/pip install -U pip
|
||||
$pyenv_path/pyenv/bin/pip install -U setuptools
|
||||
$pyenv_path/pyenv/bin/pip install -U wheel==0.34.2
|
||||
$pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
|
||||
$pyenv_path/pyenv/bin/pip install -U flask==2.2.0
|
||||
$pyenv_path/pyenv/bin/pip install flask_sock
|
||||
$pyenv_path/pyenv/bin/pip install cachelib
|
||||
$pyenv_path/pyenv/bin/pip install py7zr
|
||||
$pyenv_path/pyenv/bin/pip install backports.lzma
|
||||
source $pyenv_path/pyenv/bin/activate
|
||||
|
||||
is_gevent=$($python_bin -m gevent 2>&1|grep -oE package)
|
||||
is_psutil=$($python_bin -m psutil 2>&1|grep -oE package)
|
||||
if [ "${is_gevent}" != "${is_psutil}" ];then
|
||||
Red_Error "ERROR: psutil/gevent install failed!"
|
||||
fi
|
||||
}
|
||||
|
||||
Install_Monitor(){
|
||||
version="1.0.2"
|
||||
file_name="bt-monitor"
|
||||
agent_src="bt-monitor.zip"
|
||||
|
||||
cd ~
|
||||
version=`curl -sf ${Btapi_Url}/bt_monitor/latest_version |awk -F '\"version\"' '{print $2}'|awk -F ':' '{print $2}'|awk -F '"' '{print $2}'`
|
||||
if [ -z $version ]; then
|
||||
version="1.0.2"
|
||||
fi
|
||||
new_dir="/www/server/new_btmonitor"
|
||||
if [ ! -d "$new_dir" ];then
|
||||
mkdir -p $new_dir
|
||||
fi
|
||||
if [ ! -z "$action" ]; then
|
||||
# 例如:sh update_btmonitor.sh /root/demo.zip
|
||||
if [[ "$action" =~ "zip" ]]; then
|
||||
version="指定版本"
|
||||
unzip -o $action -d $new_dir/
|
||||
else
|
||||
wget -O $agent_src ${Btapi_Url}/install/src/$file_name-$version.zip -t 5 -T 10
|
||||
unzip -o $agent_src -d $new_dir/ > /dev/null
|
||||
fi
|
||||
else
|
||||
wget -O $agent_src ${Btapi_Url}/install/src/$file_name-$version.zip -t 5 -T 10
|
||||
unzip -o $agent_src -d $new_dir/ > /dev/null
|
||||
fi
|
||||
if [ ! -f $new_dir/BT-MONITOR ];then
|
||||
ls -lh $agent_src
|
||||
Red_Error "ERROR: Failed to download, please try install again!" "ERROR: 下载堡塔云监控失败,请尝试重新安装!"
|
||||
fi
|
||||
|
||||
rm -rf $new_dir/config
|
||||
rm -rf $new_dir/data
|
||||
rm -rf $new_dir/ssl
|
||||
\cp -r $new_dir/* $monitor_path/
|
||||
rm -rf $agent_src
|
||||
rm -rf $new_dir
|
||||
chmod +x $monitor_path/BT-MONITOR
|
||||
chmod +x $monitor_path/tools.py
|
||||
wget -O /etc/init.d/btm ${download_Url}/init/btmonitor.init -t 5 -T 10
|
||||
chmod +x /etc/init.d/btm
|
||||
ln -sf /etc/init.d/btm /usr/bin/btm
|
||||
|
||||
if [ ! -f $monitor_path/data/user.json ]; then
|
||||
echo "{\"uid\":1,\"username\":\"Administrator\",\"ip\":\"127.0.0.1\",\"server_id\":\"1\",\"access_key\":\"test\",\"secret_key\":\"123456\"}" > $monitor_path/data/user.json
|
||||
fi
|
||||
if [ -f $monitor_path/core/include/c_loader/PluginLoader.so ]; then
|
||||
rm -f $monitor_path/core/include/c_loader/PluginLoader.so
|
||||
fi
|
||||
}
|
||||
|
||||
Service_Add(){
|
||||
if [ $Command_Exists systemctl ]; then
|
||||
wget -O /usr/lib/systemd/system/btm.service ${download_Url}/init/systemd/btmonitor.service -t 5 -T 10
|
||||
systemctl daemon-reload
|
||||
systemctl enable btm
|
||||
else
|
||||
if [ "${PM}" == "yum" ] || [ "${PM}" == "dnf" ]; then
|
||||
chkconfig --add btm
|
||||
chkconfig --level 2345 btm on
|
||||
elif [ "${PM}" == "apt-get" ]; then
|
||||
update-rc.d btm defaults
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
Start_Monitor(){
|
||||
/etc/init.d/btm start
|
||||
if [ "$?" != "0" ]; then
|
||||
echo "堡塔云监控启动失败!"
|
||||
tail $monitor_path/logs/error.log
|
||||
exit 1
|
||||
fi
|
||||
echo "已成功升级到[$version]${Ver}";
|
||||
}
|
||||
|
||||
GetSysInfo(){
|
||||
if [ -s "/etc/redhat-release" ];then
|
||||
SYS_VERSION=$(cat /etc/redhat-release)
|
||||
elif [ -s "/etc/issue" ]; then
|
||||
SYS_VERSION=$(cat /etc/issue)
|
||||
fi
|
||||
SYS_INFO=$(uname -a)
|
||||
SYS_BIT=$(getconf LONG_BIT)
|
||||
MEM_TOTAL=$(free -m|grep Mem|awk '{print $2}')
|
||||
CPU_INFO=$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
echo -e ${SYS_VERSION}
|
||||
echo -e Bit:${SYS_BIT} Mem:${MEM_TOTAL}M Core:${CPU_INFO}
|
||||
echo -e ${SYS_INFO}
|
||||
echo -e "请截图以上报错信息发帖至论坛www.bt.cn/bbs求助"
|
||||
}
|
||||
|
||||
Red_Error(){
|
||||
echo '=================================================';
|
||||
printf '\033[1;31;40m%b\033[0m\n' "$@";
|
||||
GetSysInfo
|
||||
exit 1;
|
||||
}
|
||||
|
||||
Install_RPM_Pack(){
|
||||
yumPacks="wget curl unzip gcc gcc-c++ make libcurl-devel openssl-devel xz-devel python-backports-lzma xz"
|
||||
yum install -y ${yumPacks}
|
||||
|
||||
for yumPack in ${yumPacks}
|
||||
do
|
||||
rpmPack=$(rpm -q ${yumPack})
|
||||
packCheck=$(echo ${rpmPack}|grep not)
|
||||
if [ "${packCheck}" ]; then
|
||||
yum install ${yumPack} -y
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
Install_Deb_Pack(){
|
||||
apt-get update -y
|
||||
debPacks="wget curl unzip gcc g++ make libcurl4-openssl-dev libssl-dev liblzma-dev xz-utils libffi-dev libbz2-dev libsqlite3-dev libreadline-dev libgdbm-dev python3-bsddb3 tk-dev ncurses-dev uuid-dev";
|
||||
apt-get install -y $debPacks --force-yes
|
||||
|
||||
for debPack in ${debPacks}
|
||||
do
|
||||
packCheck=$(dpkg -l ${debPack})
|
||||
if [ "$?" -ne "0" ] ;then
|
||||
apt-get install -y $debPack
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
Get_Pack_Manager(){
|
||||
if [ -f "/usr/bin/yum" ] && [ -d "/etc/yum.repos.d" ]; then
|
||||
PM="yum"
|
||||
elif [ -f "/usr/bin/apt-get" ] && [ -f "/usr/bin/dpkg" ]; then
|
||||
PM="apt-get"
|
||||
fi
|
||||
}
|
||||
|
||||
Update_Monitor(){
|
||||
Get_Pack_Manager
|
||||
get_node_url
|
||||
if [ $PM = "yum" ]; then
|
||||
Install_RPM_Pack
|
||||
else
|
||||
Install_Deb_Pack
|
||||
fi
|
||||
if [ "$action" == "update_py" ]; then
|
||||
Install_Python_Lib
|
||||
fi
|
||||
Install_Monitor
|
||||
Service_Add
|
||||
Start_Monitor
|
||||
}
|
||||
|
||||
action=${1}
|
||||
Update_Monitor
|
@@ -70,7 +70,7 @@ select_node(){
|
||||
get_version(){
|
||||
version=$(curl -Ss --connect-timeout 5 -m 2 $Btapi_Url/api/panel/get_version)
|
||||
if [ "$version" = '' ];then
|
||||
version='7.9.3'
|
||||
version='7.9.9'
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -333,9 +333,9 @@ update_panel(){
|
||||
|
||||
chattr -i /etc/init.d/bt
|
||||
chmod +x /etc/init.d/bt
|
||||
if [ $up_plugin = 1 ];then
|
||||
$pyenv_bin/python /www/server/panel/tools.py update_to6
|
||||
fi
|
||||
# if [ $up_plugin = 1 ];then
|
||||
# $pyenv_bin/python /www/server/panel/tools.py update_to6
|
||||
# fi
|
||||
}
|
||||
|
||||
update_start(){
|
||||
|
@@ -331,10 +331,6 @@ canvas {
|
||||
color: #20a53a;
|
||||
}
|
||||
|
||||
.d4 {
|
||||
background-color: #edf6ef;
|
||||
}
|
||||
|
||||
.d4 .desc {
|
||||
margin-bottom: 16px;
|
||||
line-height: 30px;
|
||||
@@ -375,7 +371,7 @@ canvas {
|
||||
animation: flap-right 0.75s linear infinite;
|
||||
}
|
||||
|
||||
/* <20><>װ<EFBFBD>ű<EFBFBD> */
|
||||
/* <20><>װ<EFBFBD>ű<EFBFBD> */
|
||||
.layui-layer .install-code {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
Binary file not shown.
BIN
public/static/images/bt_monitor.png
Normal file
BIN
public/static/images/bt_monitor.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 194 KiB |
@@ -105,5 +105,8 @@ class panel_update:
|
||||
|
||||
os.system("echo f|xcopy /s /c /e /y /r {} {}".format(public.to_path(tmpPath),public.to_path(panelPath)))
|
||||
|
||||
return public.returnMsg(True,"升级面板成功,重启面板后生效.");
|
||||
if os.path.exists('C:/update.py'): os.remove('C:/update.py')
|
||||
os.system('bt restart')
|
||||
|
||||
return public.returnMsg(True,"升级面板成功.");
|
||||
|
||||
|
@@ -22,7 +22,7 @@ def readReg(path,key):
|
||||
return False
|
||||
|
||||
panelPath = readReg(r'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\宝塔面板','PanelPath')
|
||||
if not panelPath:
|
||||
if not panelPath:
|
||||
panelPath = os.getenv('BT_PANEL')
|
||||
if not panelPath: exit();
|
||||
|
||||
@@ -44,11 +44,11 @@ class Sql():
|
||||
__OPT_FIELD = "*" # field条件
|
||||
__OPT_PARAM = () # where值
|
||||
__LOCK = panelPath + '/data/sqlite_lock.pl'
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.__DB_FILE = panelPath + '/data/default.db'
|
||||
|
||||
def __GetConn(self):
|
||||
|
||||
def __GetConn(self):
|
||||
#取数据库对象
|
||||
try:
|
||||
if self.__DB_CONN == None:
|
||||
@@ -62,8 +62,8 @@ class Sql():
|
||||
#设置表名
|
||||
self.__DB_TABLE = table
|
||||
return self
|
||||
|
||||
|
||||
|
||||
|
||||
def where(self,where,param):
|
||||
#WHERE条件
|
||||
if where:
|
||||
@@ -73,7 +73,7 @@ class Sql():
|
||||
|
||||
def __to_tuple(self,param):
|
||||
#将参数转换为tuple
|
||||
if type(param) != tuple:
|
||||
if type(param) != tuple:
|
||||
if type(param) == list:
|
||||
param = tuple(param)
|
||||
else:
|
||||
@@ -85,7 +85,7 @@ class Sql():
|
||||
if not pdata: return False
|
||||
keys,param = self.__format_pdata(pdata)
|
||||
return self.save(keys,param)
|
||||
|
||||
|
||||
#构造数据
|
||||
def __format_pdata(self,pdata):
|
||||
keys = pdata.keys()
|
||||
@@ -98,17 +98,17 @@ class Sql():
|
||||
#FIELD条件
|
||||
if len(field):
|
||||
self.__OPT_FIELD = field
|
||||
return self
|
||||
return self
|
||||
|
||||
def getField(self,keyName):
|
||||
#取回指定字段
|
||||
|
||||
|
||||
result = self.field(keyName).select()
|
||||
print(result)
|
||||
if len(result) != 0:
|
||||
return result[0][keyName]
|
||||
return result
|
||||
|
||||
|
||||
def __format_field(self,field):
|
||||
import re
|
||||
fields = []
|
||||
@@ -159,16 +159,16 @@ class Sql():
|
||||
return data
|
||||
except Exception as ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
|
||||
def setField(self,keyName,keyValue):
|
||||
#更新指定字段
|
||||
return self.save(keyName,(keyValue,))
|
||||
return self.save(keyName,(keyValue,))
|
||||
|
||||
def commit(self):
|
||||
self.__close()
|
||||
self.__DB_CONN.commit()
|
||||
|
||||
|
||||
|
||||
|
||||
def save(self,keys,param):
|
||||
#更新数据
|
||||
self.write_lock()
|
||||
@@ -180,7 +180,7 @@ class Sql():
|
||||
opt += key + "=?,"
|
||||
opt = opt[0:len(opt)-1]
|
||||
sql = "UPDATE " + self.__DB_TABLE + " SET " + opt+self.__OPT_WHERE
|
||||
|
||||
|
||||
#处理拼接WHERE与UPDATE参数
|
||||
tmp = list(self.__to_tuple(param))
|
||||
for arg in self.__OPT_PARAM:
|
||||
@@ -193,8 +193,8 @@ class Sql():
|
||||
return result.rowcount
|
||||
except Exception as ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
|
||||
|
||||
|
||||
def execute(self,sql,param = ()):
|
||||
#执行SQL语句返回受影响行
|
||||
self.write_lock()
|
||||
@@ -225,7 +225,7 @@ class Sql():
|
||||
def rm_lock(self):
|
||||
if os.path.exists(self.__LOCK):
|
||||
os.remove(self.__LOCK)
|
||||
|
||||
|
||||
def query(self,sql,param = ()):
|
||||
#执行SQL语句返回数据集
|
||||
self.__GetConn()
|
||||
@@ -236,7 +236,7 @@ class Sql():
|
||||
return data
|
||||
except Exception as ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
|
||||
def __close(self):
|
||||
#清理条件属性
|
||||
self.__OPT_WHERE = ""
|
||||
@@ -244,8 +244,8 @@ class Sql():
|
||||
self.__OPT_ORDER = ""
|
||||
self.__OPT_LIMIT = ""
|
||||
self.__OPT_PARAM = ()
|
||||
|
||||
|
||||
|
||||
|
||||
def close(self):
|
||||
#释放资源
|
||||
try:
|
||||
@@ -254,7 +254,7 @@ class Sql():
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def GetLocalIp():
|
||||
"""
|
||||
取本地外网IP
|
||||
@@ -264,17 +264,16 @@ def GetLocalIp():
|
||||
filename = panelPath + '/data/iplist.txt'
|
||||
ipaddress = readFile(filename)
|
||||
if not ipaddress:
|
||||
|
||||
url = 'http://pv.sohu.com/cityjson?ie=utf-8'
|
||||
|
||||
url = 'http://www.example.com/api/getIpAddress';
|
||||
str = httpGet(url)
|
||||
ipaddress = re.search('\d+.\d+.\d+.\d+',str).group(0)
|
||||
writeFile(filename,ipaddress)
|
||||
|
||||
|
||||
ipaddress = re.search('\d+.\d+.\d+.\d+',ipaddress).group(0);
|
||||
return ipaddress
|
||||
except:
|
||||
try:
|
||||
url = 'http://www.example.com/api/getIpAddress';
|
||||
url = 'https://www.bt.cn/Api/getIpAddress';
|
||||
str = httpGet(url)
|
||||
writeFile(filename,ipaddress)
|
||||
return str
|
||||
@@ -302,12 +301,12 @@ def start_service(name):
|
||||
while get_server_status(name) == 0:
|
||||
try:
|
||||
win32serviceutil.StartService(name)
|
||||
time.sleep(1);
|
||||
except : time.sleep(1);
|
||||
time.sleep(1);
|
||||
except : time.sleep(1);
|
||||
timeout += 1
|
||||
if timeout > 10:break
|
||||
|
||||
if get_server_status(name) != 0:
|
||||
if get_server_status(name) != 0:
|
||||
return True,None
|
||||
return False,'操作失败,10秒内未完成启动服务【{}】'.format(name)
|
||||
except :
|
||||
@@ -319,12 +318,12 @@ def stop_service(name):
|
||||
while get_server_status(name) == 1:
|
||||
try:
|
||||
win32serviceutil.StopService(name)
|
||||
time.sleep(1);
|
||||
except : time.sleep(1);
|
||||
time.sleep(1);
|
||||
except : time.sleep(1);
|
||||
timeout += 1
|
||||
if timeout > 10:break
|
||||
|
||||
if get_server_status(name) != 1:
|
||||
if get_server_status(name) != 1:
|
||||
return True,None
|
||||
return False,'操作失败,10秒内未完成启动服务【{}】'.format(name)
|
||||
except :
|
||||
@@ -364,15 +363,15 @@ def downloadFileByWget(url,filename):
|
||||
if os.path.exists(logPath): os.remove(logPath)
|
||||
except : pass
|
||||
loacl_path = '{}/script/wget.exe'.format(panelPath)
|
||||
if not os.path.exists(loacl_path): downloadFile(get_url()+'/win/panel/data/wget.exe',loacl_path)
|
||||
if not os.path.exists(loacl_path): downloadFile(get_url()+'/win/panel/data/wget.exe',loacl_path)
|
||||
|
||||
if os.path.getsize(loacl_path) < 10:
|
||||
os.remove(loacl_path)
|
||||
downloadFile(url,filename)
|
||||
else:
|
||||
shell = "{} {} -O {} -t 5 -T 60 --no-check-certificate --auth-no-challenge --force-directorie > {} 2>&1".format(loacl_path,url,filename,logPath)
|
||||
shell = "{} {} -O {} -t 5 -T 60 --no-check-certificate --auth-no-challenge --force-directorie > {} 2>&1".format(loacl_path,url,filename,logPath)
|
||||
os.system(shell)
|
||||
|
||||
|
||||
num = 0
|
||||
re_size = 0
|
||||
while num <= 5:
|
||||
@@ -382,17 +381,17 @@ def downloadFileByWget(url,filename):
|
||||
break;
|
||||
else:
|
||||
re_size = cr_size
|
||||
time.sleep(0.5)
|
||||
time.sleep(0.5)
|
||||
num += 1
|
||||
|
||||
if os.path.exists(filename):
|
||||
if os.path.exists(filename):
|
||||
if os.path.getsize(filename) < 1:
|
||||
os.remove(filename)
|
||||
downloadFile(url,filename)
|
||||
else:
|
||||
downloadFile(url,filename)
|
||||
|
||||
def writeFile(filename,s_body,mode='w+',encoding = 'utf-8'):
|
||||
def writeFile(filename,s_body,mode='w+',encoding = 'utf-8'):
|
||||
try:
|
||||
fp = open(filename, mode,encoding = encoding);
|
||||
fp.write(s_body)
|
||||
@@ -402,7 +401,7 @@ def writeFile(filename,s_body,mode='w+',encoding = 'utf-8'):
|
||||
return False
|
||||
|
||||
def readFile(filename,mode = 'r'):
|
||||
|
||||
|
||||
import os,chardet
|
||||
if not os.path.exists(filename): return False
|
||||
if not os.path.isfile(filename): return False
|
||||
@@ -425,15 +424,15 @@ def readFile(filename,mode = 'r'):
|
||||
encoding = 'ansi'
|
||||
fp = open(filename, mode,encoding = encoding)
|
||||
f_body = fp.read()
|
||||
|
||||
|
||||
try:
|
||||
if f_body[0] == '\ufeff':
|
||||
if f_body[0] == '\ufeff':
|
||||
#处理带bom格式
|
||||
new_code = chardet.detect(f_body.encode(encoding))["encoding"]
|
||||
f_body = f_body.encode(encoding).decode(new_code);
|
||||
except : pass
|
||||
|
||||
fp.close()
|
||||
except : pass
|
||||
|
||||
fp.close()
|
||||
return f_body
|
||||
|
||||
def httpGet(url,timeout = 60,headers = {}):
|
||||
@@ -445,11 +444,11 @@ def httpGet(url,timeout = 60,headers = {}):
|
||||
req = urllib.request.Request(url,headers = headers)
|
||||
response = urllib.request.urlopen(req,timeout = timeout)
|
||||
result = response.read()
|
||||
if type(result) == bytes:
|
||||
if type(result) == bytes:
|
||||
try:
|
||||
result = result.decode('utf-8')
|
||||
except :
|
||||
result = result.decode('gb2312')
|
||||
result = result.decode('gb2312')
|
||||
return result
|
||||
except Exception as ex:
|
||||
if headers: return False
|
||||
@@ -470,9 +469,9 @@ def httpPost(url, data, timeout=60, headers={}):
|
||||
|
||||
return result
|
||||
except Exception as ex:
|
||||
|
||||
|
||||
return str(ex);
|
||||
|
||||
|
||||
|
||||
def get_timeout(url,timeout=3):
|
||||
|
||||
@@ -484,10 +483,10 @@ def get_timeout(url,timeout=3):
|
||||
|
||||
def get_url(timeout = 0.5):
|
||||
import json
|
||||
try:
|
||||
try:
|
||||
#
|
||||
node_list = [{"protocol":"http://","address":"dg1.bt.cn","port":"80","ping":500},{"protocol":"http://","address":"dg2.bt.cn","port":"80","ping":500},{"protocol":"http://","address":"node.aapanel.com","port":"80","ping":500},{"protocol":"http://","address":"download.bt.cn","port":"80","ping":500}]
|
||||
|
||||
node_list = [{"protocol":"http://","address":"dg2.bt.cn","port":"80","ping":500},{"protocol":"http://","address":"dg1.bt.cn","port":"80","ping":500},{"protocol":"http://","address":"download.bt.cn","port":"80","ping":500},{"protocol":"http://","address":"hk1-node.bt.cn","port":"80","ping":500},{"protocol":"http://","address":"na1-node.bt.cn","port":"80","ping":500},{"protocol":"http://","address":"jp1-node.bt.cn","port":"80","ping":500}]
|
||||
|
||||
mnode1 = []
|
||||
mnode2 = []
|
||||
mnode3 = []
|
||||
@@ -510,12 +509,12 @@ def get_url(timeout = 0.5):
|
||||
mnode = sorted(mnode3,key= lambda x:x['net'],reverse=True)
|
||||
else: #终选中等延迟,中等带宽
|
||||
mnode = sorted(mnode2,key= lambda x:x['ping'],reverse=False)
|
||||
|
||||
if not mnode: return 'http://download.bt.cn'
|
||||
|
||||
if not mnode: return 'https://download.bt.cn'
|
||||
#return mnode[0]['protocol'] + mnode[0]['address'] + ':' + mnode[0]['port']
|
||||
return "https://" + mnode[0]['address']
|
||||
except:
|
||||
return 'http://download.bt.cn'
|
||||
return 'https://download.bt.cn'
|
||||
|
||||
|
||||
|
||||
@@ -529,12 +528,12 @@ def del_file_access(filename,user):
|
||||
sd = win32security.GetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION)
|
||||
dacl = sd.GetSecurityDescriptorDacl()
|
||||
ace_count = dacl.GetAceCount()
|
||||
|
||||
for i in range(ace_count ,0 ,-1):
|
||||
|
||||
for i in range(ace_count ,0 ,-1):
|
||||
try:
|
||||
data = {}
|
||||
data['rev'], data['access'], usersid = dacl.GetAce(i-1)
|
||||
data['user'],data['group'], data['type'] = win32security.LookupAccountSid('', usersid)
|
||||
data['user'],data['group'], data['type'] = win32security.LookupAccountSid('', usersid)
|
||||
if data['user'].lower() == user.lower(): dacl.DeleteAce(i-1) #删除旧的dacl
|
||||
if data['user'].lower() == 'users': dacl.DeleteAce(i-1) #删除旧的dacl
|
||||
|
||||
@@ -542,35 +541,35 @@ def del_file_access(filename,user):
|
||||
try:
|
||||
#处理拒绝访问
|
||||
dacl.DeleteAce(i-1)
|
||||
except : pass
|
||||
except : pass
|
||||
sd.SetSecurityDescriptorDacl(1, dacl, 0)
|
||||
win32security.SetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION, sd)
|
||||
except :
|
||||
pass
|
||||
return True
|
||||
|
||||
def set_file_access(filename,user,access):
|
||||
def set_file_access(filename,user,access):
|
||||
try:
|
||||
sd = win32security.GetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION)
|
||||
dacl = sd.GetSecurityDescriptorDacl()
|
||||
ace_count = dacl.GetAceCount()
|
||||
|
||||
for i in range(ace_count, 0,-1):
|
||||
for i in range(ace_count, 0,-1):
|
||||
try:
|
||||
data = {}
|
||||
data['rev'], data['access'], usersid = dacl.GetAce(i-1)
|
||||
data['user'],data['group'], data['type'] = win32security.LookupAccountSid('', usersid)
|
||||
data['user'],data['group'], data['type'] = win32security.LookupAccountSid('', usersid)
|
||||
if data['user'].lower() == user.lower(): dacl.DeleteAce(i-1) #删除旧的dacl
|
||||
if data['user'].lower() == 'users': dacl.DeleteAce(i-1) #删除旧的dacl
|
||||
|
||||
|
||||
except :
|
||||
pass
|
||||
try:
|
||||
userx, domain, type = win32security.LookupAccountName("", user)
|
||||
except :
|
||||
userx, domain, type = win32security.LookupAccountName("", 'IIS APPPOOL\\' + user)
|
||||
userx, domain, type = win32security.LookupAccountName("", 'IIS APPPOOL\\' + user)
|
||||
if access > 0: dacl.AddAccessAllowedAceEx(win32security.ACL_REVISION, 3, access, userx)
|
||||
|
||||
|
||||
sd.SetSecurityDescriptorDacl(1, dacl, 0)
|
||||
win32security.SetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION, sd)
|
||||
return True,None
|
||||
@@ -582,24 +581,24 @@ def ExecShell(cmdstring, cwd=None, timeout=None, shell=True):
|
||||
cmdstring_list = cmdstring
|
||||
else:
|
||||
cmdstring_list = shlex.split(cmdstring)
|
||||
|
||||
|
||||
if timeout:
|
||||
end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout)
|
||||
|
||||
sub = subprocess.Popen(cmdstring_list, cwd=cwd, stdin=subprocess.PIPE,shell=shell,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
|
||||
sub = subprocess.Popen(cmdstring_list, cwd=cwd, stdin=subprocess.PIPE,shell=shell,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
while sub.poll() is None:
|
||||
time.sleep(0.1)
|
||||
if timeout:
|
||||
if end_time <= datetime.datetime.now():
|
||||
raise Exception("Timeout:%s"%cmdstring)
|
||||
a,e = sub.communicate()
|
||||
if type(a) == bytes:
|
||||
if type(a) == bytes:
|
||||
try:
|
||||
a = a.decode('utf-8')
|
||||
except :
|
||||
except :
|
||||
a = a.decode('gb2312','ignore')
|
||||
|
||||
if type(e) == bytes:
|
||||
if type(e) == bytes:
|
||||
try:
|
||||
e = e.decode('utf-8')
|
||||
except :
|
||||
@@ -626,7 +625,7 @@ def GetRandomString1(length):
|
||||
strings += chars[random.randint(0, chrlen)]
|
||||
return strings
|
||||
|
||||
def GetRandomString2(length):
|
||||
def GetRandomString2(length):
|
||||
from random import Random
|
||||
strings = ''
|
||||
chars = '!@#$%^&*()_+.,?[]-='
|
||||
@@ -637,7 +636,7 @@ def GetRandomString2(length):
|
||||
return strings
|
||||
|
||||
def chdck_salt():
|
||||
|
||||
|
||||
sql = Sql()
|
||||
sql.table('users').execute("ALTER TABLE 'users' ADD 'salt' TEXT",())
|
||||
|
||||
@@ -657,7 +656,7 @@ def md5(strings):
|
||||
"""
|
||||
import hashlib
|
||||
m = hashlib.md5()
|
||||
|
||||
|
||||
m.update(strings.encode('utf-8'))
|
||||
return m.hexdigest()
|
||||
|
||||
@@ -673,18 +672,18 @@ def password_salt(password,username=None,uid=None):
|
||||
salt = sql.table('users').where('id=?',(uid,)).getField('salt')
|
||||
return md5(md5(password+'_bt.cn')+salt)
|
||||
|
||||
def check_user(username):
|
||||
def check_user(username):
|
||||
resume = 0
|
||||
while True:
|
||||
data, total, resume = win32net.NetUserEnum(None, 3, win32netcon.FILTER_NORMAL_ACCOUNT, resume)
|
||||
for user in data:
|
||||
if user['name'] == username: return True
|
||||
if not resume: break
|
||||
return False
|
||||
return False
|
||||
|
||||
def add_user(username,password,ps):
|
||||
try:
|
||||
if not check_user(username):
|
||||
if not check_user(username):
|
||||
d = {}
|
||||
d['name'] = username
|
||||
d['password'] = password
|
||||
@@ -692,7 +691,7 @@ def add_user(username,password,ps):
|
||||
d['flags'] = win32netcon.UF_NORMAL_ACCOUNT | win32netcon.UF_SCRIPT
|
||||
d['priv'] = win32netcon.USER_PRIV_USER
|
||||
win32net.NetUserAdd(None, 1, d)
|
||||
|
||||
|
||||
#设置用户允许登录服务
|
||||
handle = win32security.LsaOpenPolicy(None, win32security.POLICY_ALL_ACCESS)
|
||||
sid_obj, domain, tmp = win32security.LookupAccountName(None, username)
|
||||
@@ -713,25 +712,25 @@ def add_user_bywww():
|
||||
|
||||
pwd = GetRandomString(64) + GetRandomString1(32) + GetRandomString2(32)
|
||||
status,error = add_user('www',pwd,'用于启动宝塔安装的程序,删除后会导致部分软件无法启动,请勿删除')
|
||||
if not status:
|
||||
if not status:
|
||||
writeFile(error_path,error)
|
||||
return False
|
||||
return True
|
||||
|
||||
def add_user_bymysql():
|
||||
|
||||
|
||||
pwd = GetRandomString(64) + GetRandomString1(32) + GetRandomString2(32)
|
||||
status,error = add_user('mysql',pwd,'用于启动宝塔安装的程序,删除后会导致部分软件无法启动,请勿删除')
|
||||
if not status:
|
||||
if not status:
|
||||
writeFile(error_path,error)
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def getIP(url):
|
||||
import socket,re
|
||||
|
||||
tmp = re.search('http://(.+)\:\d*',url)
|
||||
if tmp:
|
||||
if tmp:
|
||||
domain = tmp.groups()[0]
|
||||
myaddr = socket.getaddrinfo(domain, 'http')
|
||||
return myaddr[0][4][0]
|
||||
@@ -756,14 +755,14 @@ def add_panel_dir():
|
||||
]
|
||||
|
||||
is_break = False
|
||||
for sobj in slist:
|
||||
for sobj in slist:
|
||||
if not os.path.exists(sobj[0]):
|
||||
os.makedirs(sobj[0])
|
||||
os.makedirs(sobj[0])
|
||||
n = 0
|
||||
while n < 5:
|
||||
if os.path.exists(sobj[0]): break
|
||||
|
||||
os.makedirs(sobj[0])
|
||||
os.makedirs(sobj[0])
|
||||
time.sleep(0.5)
|
||||
n += 1
|
||||
|
||||
@@ -773,17 +772,17 @@ def add_panel_dir():
|
||||
|
||||
del_file_access(sobj[0],'users')
|
||||
|
||||
for user in sobj[1]:
|
||||
for user in sobj[1]:
|
||||
n = 0
|
||||
while n < 3:
|
||||
while n < 3:
|
||||
status,error = set_file_access(sobj[0],user,2032127)
|
||||
if status: break
|
||||
if status: break
|
||||
time.sleep(0.5)
|
||||
|
||||
if not status:
|
||||
writeFile(error_path,"目录{}设置{}权限设置错误 -> {}".format(sobj[0],user,error))
|
||||
break
|
||||
|
||||
|
||||
del_file_access(setupPath,'users')
|
||||
url = get_url()
|
||||
|
||||
@@ -793,18 +792,18 @@ def add_panel_dir():
|
||||
download_url = '{}/win/panel/data/{}'.format(url,f_name)
|
||||
|
||||
n = 0
|
||||
while n < 10:
|
||||
while n < 10:
|
||||
n += 1;
|
||||
|
||||
try:
|
||||
if os.path.exists(local_path) and os.path.getsize(local_path) < 10: os.remove(local_path)
|
||||
if not os.path.exists(local_path): downloadFileByWget(download_url,local_path)
|
||||
if os.path.getsize(local_path) and os.path.getsize(local_path) > 10: break;
|
||||
if os.path.exists(local_path) and os.path.getsize(local_path) < 10: os.remove(local_path)
|
||||
if not os.path.exists(local_path): downloadFileByWget(download_url,local_path)
|
||||
if os.path.getsize(local_path) and os.path.getsize(local_path) > 10: break;
|
||||
|
||||
writeFile(error_path,'download {} error ->> {} \r\n {}'.format(f_name,download_url,""))
|
||||
writeFile(error_path,'download {} error ->> {} \r\n {}'.format(f_name,download_url,""))
|
||||
except :
|
||||
ip = getIP(url)
|
||||
writeFile(error_path,'download {} error ->> {} \r\n connect {} \r\n {}'.format(ip,f_name,download_url,get_error_info()))
|
||||
writeFile(error_path,'download {} error ->> {} \r\n connect {} \r\n {}'.format(ip,f_name,download_url,get_error_info()))
|
||||
|
||||
if n > 5: return False
|
||||
time.sleep(0.2)
|
||||
@@ -816,9 +815,9 @@ def add_panel_dir():
|
||||
|
||||
def unzip(src_path,dst_path):
|
||||
import zipfile
|
||||
zip_file = zipfile.ZipFile(src_path)
|
||||
for names in zip_file.namelist():
|
||||
zip_file.extract(names,dst_path)
|
||||
zip_file = zipfile.ZipFile(src_path)
|
||||
for names in zip_file.namelist():
|
||||
zip_file.extract(names,dst_path)
|
||||
zip_file.close()
|
||||
return True
|
||||
|
||||
@@ -834,44 +833,44 @@ def download_panel(file_list = []):
|
||||
#下载面板
|
||||
loacl_path = setupPath + '/panel.zip'
|
||||
tmpPath = "{}/temp/panel".format(setupPath)
|
||||
if os.path.exists(loacl_path): os.remove(loacl_path)
|
||||
if os.path.exists(loacl_path): os.remove(loacl_path)
|
||||
if os.path.exists(tmpPath): shutil.rmtree(tmpPath,True)
|
||||
if not os.path.exists(tmpPath): os.makedirs(tmpPath)
|
||||
|
||||
|
||||
p_ver = sys.argv[2]
|
||||
downUrl = url + '/win/panel/panel_' + p_ver + '.zip';
|
||||
downloadFileByWget(downUrl,loacl_path);
|
||||
unzip(loacl_path,tmpPath)
|
||||
|
||||
downloadFileByWget(downUrl,loacl_path);
|
||||
unzip(loacl_path,tmpPath)
|
||||
|
||||
for ff_path in file_list:
|
||||
if os.path.exists(tmpPath + '/' + ff_path): os.remove(tmpPath + '/' + ff_path)
|
||||
if os.path.exists(tmpPath + '/' + ff_path): os.remove(tmpPath + '/' + ff_path)
|
||||
|
||||
tcPath = '{}\class'.format(tmpPath)
|
||||
for name in os.listdir(tcPath):
|
||||
try:
|
||||
for name in os.listdir(tcPath):
|
||||
try:
|
||||
if name.find('win_amd64.pyd') >=0:
|
||||
oldName = os.path.join(tcPath,name);
|
||||
lName = name.split('.')[0] + '.pyd'
|
||||
newName = os.path.join(tcPath,lName)
|
||||
lName = name.split('.')[0] + '.pyd'
|
||||
newName = os.path.join(tcPath,lName)
|
||||
if not os.path.exists(newName):os.rename(oldName,newName)
|
||||
except :pass
|
||||
|
||||
cPath = '{}/panel/class'.format(setupPath)
|
||||
|
||||
if os.path.exists(cPath):
|
||||
if os.path.exists(cPath):
|
||||
os.system("del /s {}\*.pyc".format(to_path(cPath)))
|
||||
os.system("del /s {}\*.pyt".format(to_path(cPath)))
|
||||
for name in os.listdir(cPath):
|
||||
try:
|
||||
if name.find('.pyd') >=0:
|
||||
if name.find('.pyd') >=0:
|
||||
oldName = os.path.join(cPath,name)
|
||||
newName = os.path.join(cPath,GetRandomString(8) + '.pyt')
|
||||
os.rename(oldName,newName)
|
||||
newName = os.path.join(cPath,GetRandomString(8) + '.pyt')
|
||||
os.rename(oldName,newName)
|
||||
except : pass
|
||||
os.system("del /s {}\*.pyc".format(to_path(cPath)))
|
||||
os.system("del /s {}\*.pyt".format(to_path(cPath)))
|
||||
|
||||
os.system("xcopy /s /c /e /y /r {} {}".format(to_path(tmpPath),to_path(panelPath)))
|
||||
os.system("xcopy /s /c /e /y /r {} {}".format(to_path(tmpPath),to_path(panelPath)))
|
||||
try:
|
||||
os.remove(loacl_path)
|
||||
except : pass
|
||||
@@ -880,7 +879,7 @@ def download_panel(file_list = []):
|
||||
shutil.rmtree(tmpPath,True)
|
||||
except : pass
|
||||
|
||||
s_ver = platform.platform()
|
||||
s_ver = platform.platform()
|
||||
net_v = '45'
|
||||
if s_ver.find('2008') >= 0: net_v = '20'
|
||||
writeFile('{}/data/net'.format(setupPath),net_v)
|
||||
@@ -910,7 +909,7 @@ def download_panel(file_list = []):
|
||||
try:
|
||||
from gevent import monkey
|
||||
except :
|
||||
os.system('"C:\Program Files\python\python.exe" -m pip install gevent')
|
||||
os.system('"C:\Program Files\python\python.exe" -m pip install gevent')
|
||||
except :
|
||||
writeFile(error_path,get_error_info())
|
||||
|
||||
@@ -918,7 +917,7 @@ def update_panel():
|
||||
|
||||
file_list = ['config/config.json','config/index.json','data/libList.conf','data/plugin.json']
|
||||
download_panel(file_list)
|
||||
|
||||
|
||||
py_path = 'C:/Program Files/python/python.exe'
|
||||
|
||||
ExecShell("\"{}\" {}/panel/runserver.py --startup auto install".format(py_path,setupPath))
|
||||
@@ -929,7 +928,7 @@ def update_panel():
|
||||
def init_panel_data():
|
||||
try:
|
||||
sql = Sql()
|
||||
username = sql.table('users').where('id=?',(1,)).getField('username')
|
||||
username = sql.table('users').where('id=?',(1,)).getField('username')
|
||||
if username == 'admin':
|
||||
username = GetRandomString(8)
|
||||
password = GetRandomString(8)
|
||||
@@ -937,12 +936,12 @@ def init_panel_data():
|
||||
|
||||
sql.table('users').where('id=?',(1,)).setField('username',username)
|
||||
pwd = password_salt(md5(password),uid=1)
|
||||
|
||||
|
||||
result = sql.table('users').where('id=?',(1,)).setField('password',pwd)
|
||||
|
||||
backup_path = panelPath[:2] + '/backup'
|
||||
www_path = panelPath[:2] + '/wwwroot'
|
||||
|
||||
|
||||
if not os.path.exists(backup_path): os.makedirs(backup_path)
|
||||
if not os.path.exists(www_path): os.makedirs(www_path)
|
||||
|
||||
@@ -953,11 +952,11 @@ def init_panel_data():
|
||||
if not os.path.exists(bind_path): writeFile(bind_path,'True')
|
||||
|
||||
admin_path = panelPath+ '/data/admin_path.pl'
|
||||
if not os.path.exists(admin_path): writeFile(admin_path,"/" + GetRandomString(8))
|
||||
if not os.path.exists(admin_path): writeFile(admin_path,"/" + GetRandomString(8))
|
||||
|
||||
port_path = panelPath+ '/data/port.pl'
|
||||
if not os.path.exists(port_path): writeFile(port_path,'8888')
|
||||
|
||||
|
||||
recycle_bin_db = panelPath+ '/data/recycle_bin_db.pl'
|
||||
if not os.path.exists(recycle_bin_db): writeFile(recycle_bin_db,'True')
|
||||
|
||||
@@ -975,26 +974,26 @@ def init_panel_data():
|
||||
except :
|
||||
writeFile(error_path,get_error_info())
|
||||
return False
|
||||
|
||||
|
||||
def add_panel_services(num = 0):
|
||||
try:
|
||||
py_path = 'C:/Program Files/python/python.exe'
|
||||
|
||||
delete_server('btPanel')
|
||||
delete_server('btPanel')
|
||||
ret = ExecShell("\"{}\" {}/panel/runserver.py --startup auto install".format(py_path,setupPath))
|
||||
|
||||
|
||||
delete_server('btTask')
|
||||
ExecShell("\"{}\" {}/panel/task.py --startup auto install".format(py_path,setupPath))
|
||||
|
||||
if get_server_status('btPanel') < 0 or get_server_status('btTask') < 0:
|
||||
ret1 = ExecShell("\"{}\" {}/panel/task.py --startup auto install".format(py_path,setupPath))
|
||||
|
||||
if get_server_status('btPanel') < 0 or get_server_status('btTask') < 0:
|
||||
if num <= 0 :
|
||||
localPath = setupPath + "/temp/Time_Zones.reg";
|
||||
downloadFileByWget(get_url() + '/win/panel/data/Time_Zones.reg',localPath)
|
||||
ExecShell("regedit /s " + localPath)
|
||||
|
||||
add_panel_services(1)
|
||||
add_panel_services(1)
|
||||
else:
|
||||
writeFile(error_path,ret[0] + ret[1])
|
||||
writeFile(error_path,ret[0] + ret[1] + ret1[0] + ret1[1])
|
||||
else:
|
||||
os.system('sc failure btPanel reset=1800 actions=restart/60000/restart/120000/restart/30000')
|
||||
os.system('sc failure btTask reset=1800 actions=restart/60000/restart/120000/restart/30000')
|
||||
@@ -1005,9 +1004,9 @@ def add_panel_services(num = 0):
|
||||
|
||||
|
||||
def add_firewall_byport():
|
||||
|
||||
|
||||
conf = ExecShell('netsh advfirewall firewall show rule "宝塔面板"')[0]
|
||||
if conf.lower().find('tcp') == -1:
|
||||
if conf.lower().find('tcp') == -1:
|
||||
ExecShell("netsh advfirewall firewall add rule name=宝塔面板 dir=in action=allow protocol=tcp localport=8888");
|
||||
ExecShell("netsh advfirewall firewall add rule name=网站访问端口 dir=in action=allow protocol=tcp localport=80");
|
||||
ExecShell("netsh advfirewall firewall add rule name=远程桌面 dir=in action=allow protocol=tcp localport=3389");
|
||||
@@ -1029,8 +1028,8 @@ def get_error_log():
|
||||
return error
|
||||
|
||||
if __name__ == "__main__":
|
||||
stype = sys.argv[1];
|
||||
if not stype in ['get_error_log']:
|
||||
stype = sys.argv[1];
|
||||
if not stype in ['get_error_log']:
|
||||
if os.path.exists(error_path): os.remove(error_path)
|
||||
result = eval('{}()'.format(stype))
|
||||
print(result)
|
||||
|
Binary file not shown.
@@ -15,6 +15,14 @@ Route::post('/panel/get_unbinding', 'api/return_success');
|
||||
Route::post('/bt_cert', 'api/return_error');
|
||||
Route::post('/Auth/GetAuthToken', 'api/get_auth_token');
|
||||
Route::post('/Auth/GetBindCode', 'api/return_error');
|
||||
Route::any('/bt_monitor/update_history', 'api/btm_update_history');
|
||||
Route::any('/bt_monitor/latest_version', 'api/btm_latest_version');
|
||||
|
||||
Route::group('authorization', function () {
|
||||
Route::post('/login', 'api/authorization_login');
|
||||
Route::post('/info', 'api/authorization_info');
|
||||
Route::miss('api/return_error');
|
||||
});
|
||||
|
||||
Route::group('api', function () {
|
||||
Route::any('/panel/get_soft_list', 'api/get_plugin_list');
|
||||
@@ -36,6 +44,9 @@ Route::group('api', function () {
|
||||
Route::get('/getIpAddress', 'api/get_ip_address');
|
||||
Route::post('/Auth/GetAuthToken', 'api/get_auth_token');
|
||||
Route::post('/Auth/GetBindCode', 'api/return_error');
|
||||
Route::post('/Auth/GetSSLList', 'api/get_ssl_list');
|
||||
Route::post('/Cert/get_order_list', 'api/return_empty_array');
|
||||
Route::post('/Cert/get_product_list', 'api/return_success');
|
||||
Route::get('/Pluginother/get_file', 'api/download_plugin_other');
|
||||
|
||||
Route::post('/Pluginother/create_order', 'api/return_error');
|
||||
|
44
wiki/btmonitor.md
Normal file
44
wiki/btmonitor.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# 宝塔云监控安装包修改记录
|
||||
|
||||
查询最新版本号:https://api.bt.cn/bt_monitor/latest_version
|
||||
|
||||
安装包下载链接:http://download.bt.cn/install/src/bt-monitor-版本号.zip
|
||||
|
||||
- 删除core/include/c_loader/PluginLoader.so,将btmonitor/PluginLoader.py复制到这个文件夹
|
||||
|
||||
- 批量解密源码:执行 php think decrypt all <源码根目录>
|
||||
|
||||
极少数文件解密失败是正常现象可无视
|
||||
|
||||
- 全局搜索替换 https://api.bt.cn => http://www.example.com
|
||||
|
||||
- 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/(需排除/panel/get_ip_info)
|
||||
|
||||
- core/include/public.py 在
|
||||
|
||||
```python
|
||||
def GetConfigValue(key):
|
||||
```
|
||||
|
||||
这一行下面加上
|
||||
|
||||
```python
|
||||
if key == 'home': return 'http://www.example.com'
|
||||
```
|
||||
|
||||
def write_request_log(reques = None): 这一行下面加上 return
|
||||
|
||||
- core/basic_monitor.py
|
||||
|
||||
在 def report_module_logs(self, force=False): 这一行下面加上 return
|
||||
|
||||
- modules/configModule/main.py
|
||||
|
||||
https://download.bt.cn => http://www.example.com
|
||||
|
||||
- update/update_btmonitor.sh 修改Install_Monitor方法内的download_Url变量
|
||||
|
||||
- init.sh https://download.bt.cn => http://www.example.com
|
||||
|
||||
- BT-MONITOR 取消第一个CreateSSL方法定义的注释,删除第二个CreateSSL方法定义
|
||||
|
199
wiki/files/bt.js
199
wiki/files/bt.js
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
*宝塔面板去除各种计算题与延时等待
|
||||
*/
|
||||
if("undefined" != typeof bt && bt.hasOwnProperty("show_confirm")){
|
||||
bt.show_confirm = function(title, msg, callback, error) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
area: "365px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
btn: [lan['public'].ok, lan['public'].cancel],
|
||||
content: "<div class='bt-form webDelete pd20'>\
|
||||
<p style='font-size:13px;word-break: break-all;margin-bottom: 5px;'>" + msg + "</p>" + (error || '') + "\
|
||||
</div>",
|
||||
yes: function (index, layero) {
|
||||
layer.close(index);
|
||||
if (callback) callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof bt && bt.hasOwnProperty("prompt_confirm")){
|
||||
bt.prompt_confirm = function (title, msg, callback) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
area: "350px",
|
||||
closeBtn: 2,
|
||||
btn: ['确认', '取消'],
|
||||
content: "<div class='bt-form promptDelete pd20'>\
|
||||
<p>" + msg + "</p>\
|
||||
</div>",
|
||||
yes: function (layers, index) {
|
||||
layer.close(layers)
|
||||
if (callback) callback()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof database && database.hasOwnProperty("del_database")){
|
||||
database.del_database = function (wid, dbname,obj, callback) {
|
||||
title = '',
|
||||
tips = '是否确认【删除数据库】,删除后可能会影响业务使用!';
|
||||
if(obj && obj.db_type > 0) tips = '远程数据库不支持数据库回收站,删除后将无法恢复,请谨慎操作';
|
||||
var title = typeof dbname === "function" ?'批量删除数据库':'删除数据库 [ '+ dbname +' ]';
|
||||
layer.open({
|
||||
type:1,
|
||||
title:title,
|
||||
icon:0,
|
||||
skin:'delete_site_layer',
|
||||
area: "530px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content:"<div class=\'bt-form webDelete pd30\' id=\'site_delete_form\'>" +
|
||||
"<i class=\'layui-layer-ico layui-layer-ico0\'></i>" +
|
||||
"<div class=\'f13 check_title\' style=\'margin-bottom: 20px;\'>"+tips+"</div>" +
|
||||
"<div style=\'color:red;margin:18px 0 18px 18px;font-size:14px;font-weight: bold;\'>注意:数据无价,请谨慎操作!!!"+(!recycle_bin_db_open?'<br>风险操作:当前数据库回收站未开启,删除数据库将永久消失!':'')+"</div>" +
|
||||
"</div>",
|
||||
btn:[lan.public.ok,lan.public.cancel],
|
||||
yes:function(indexs){
|
||||
var data = {id: wid,name: dbname};
|
||||
if(typeof dbname === "function"){
|
||||
delete data.id;
|
||||
delete data.name;
|
||||
}
|
||||
layer.close(indexs)
|
||||
if(typeof dbname === "function"){
|
||||
dbname(data)
|
||||
}else{
|
||||
bt.database.del_database(data, function (rdata) {
|
||||
layer.closeAll()
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof site && site.hasOwnProperty("del_site")){
|
||||
site.del_site = function(wid, wname, callback) {
|
||||
var title = typeof wname === "function" ?'批量删除站点':'删除站点 [ '+ wname +' ]';
|
||||
layer.open({
|
||||
type:1,
|
||||
title:title,
|
||||
icon:0,
|
||||
skin:'delete_site_layer',
|
||||
area: "440px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content:"<div class=\'bt-form webDelete pd30\' id=\'site_delete_form\'>" +
|
||||
'<i class="layui-layer-ico layui-layer-ico0"></i>' +
|
||||
"<div class=\'f13 check_title\'>是否要删除关联的FTP、数据库、站点目录!</div>" +
|
||||
"<div class=\"check_type_group\">" +
|
||||
"<label><input type=\"checkbox\" name=\"ftp\"><span>FTP</span></label>" +
|
||||
"<label><input type=\"checkbox\" name=\"database\"><span>数据库</span>"+ (!recycle_bin_db_open?'<span class="glyphicon glyphicon-info-sign" style="color: red"></span>':'') +"</label>" +
|
||||
"<label><input type=\"checkbox\" name=\"path\"><span>站点目录</span>"+ (!recycle_bin_open?'<span class="glyphicon glyphicon-info-sign" style="color: red"></span>':'') +"</label>" +
|
||||
"</div>"+
|
||||
"</div>",
|
||||
btn:[lan.public.ok,lan.public.cancel],
|
||||
success:function(layers,indexs){
|
||||
$(layers).find('.check_type_group label').hover(function(){
|
||||
var name = $(this).find('input').attr('name');
|
||||
if(name === 'data' && !recycle_bin_db_open){
|
||||
layer.tips('风险操作:当前数据库回收站未开启,删除数据库将永久消失!', this, {tips: [1, 'red'],time:0})
|
||||
}else if(name === 'path' && !recycle_bin_open){
|
||||
layer.tips('风险操作:当前文件回收站未开启,删除站点目录将永久消失!', this, {tips: [1, 'red'],time:0})
|
||||
}
|
||||
},function(){
|
||||
layer.closeAll('tips');
|
||||
})
|
||||
},
|
||||
yes:function(indexs){
|
||||
var data = {id: wid,webname: wname};
|
||||
$('#site_delete_form input[type=checkbox]').each(function (index, item) {
|
||||
if($(item).is(':checked')) data[$(item).attr('name')] = 1
|
||||
})
|
||||
var is_database = data.hasOwnProperty('database'),is_path = data.hasOwnProperty('path'),is_ftp = data.hasOwnProperty('ftp');
|
||||
if((!is_database && !is_path) && (!is_ftp || is_ftp)){
|
||||
if(typeof wname === "function"){
|
||||
wname(data)
|
||||
return false;
|
||||
}
|
||||
bt.site.del_site(data, function (rdata) {
|
||||
layer.close(indexs);
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
})
|
||||
return false
|
||||
}
|
||||
if(typeof wname === "function"){
|
||||
delete data.id;
|
||||
delete data.webname;
|
||||
}
|
||||
layer.close(indexs)
|
||||
if(typeof wname === "function"){
|
||||
console.log(data)
|
||||
wname(data)
|
||||
}else{
|
||||
bt.site.del_site(data, function (rdata) {
|
||||
layer.closeAll()
|
||||
if (rdata.status) site.get_list();
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof bt && bt.hasOwnProperty("firewall") && bt.firewall.hasOwnProperty("add_accept_port")){
|
||||
bt.firewall.add_accept_port = function(type, port, ps, callback) {
|
||||
var action = "AddDropAddress";
|
||||
if (type == 'port') {
|
||||
ports = port.split(':');
|
||||
if (port.indexOf('-') != -1) ports = port.split('-');
|
||||
for (var i = 0; i < ports.length; i++) {
|
||||
if (!bt.check_port(ports[i])) {
|
||||
layer.msg(lan.firewall.port_err, { icon: 5 });
|
||||
return;
|
||||
}
|
||||
}
|
||||
action = "AddAcceptPort";
|
||||
}
|
||||
|
||||
loading = bt.load();
|
||||
bt.send(action, 'firewall/' + action, { port: port, type: type, ps: ps }, function(rdata) {
|
||||
loading.close();
|
||||
if (callback) callback(rdata);
|
||||
})
|
||||
}
|
||||
}
|
||||
function SafeMessage(j, h, g, f) {
|
||||
if(f == undefined) {
|
||||
f = ""
|
||||
}
|
||||
var mess = layer.open({
|
||||
type: 1,
|
||||
title: j,
|
||||
area: "350px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content: "<div class='bt-form webDelete pd20 pb70'><p>" + h + "</p>" + f + "<div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm bt-cancel'>"+lan.public.cancel+"</button> <button type='button' id='toSubmit' class='btn btn-success btn-sm' >"+lan.public.ok+"</button></div></div>"
|
||||
});
|
||||
$(".bt-cancel").click(function(){
|
||||
layer.close(mess);
|
||||
});
|
||||
$("#toSubmit").click(function() {
|
||||
layer.close(mess);
|
||||
g();
|
||||
})
|
||||
}
|
||||
$(document).ready(function () {
|
||||
if($('#updata_pro_info').length>0){
|
||||
$('#updata_pro_info').html('');
|
||||
bt.set_cookie('productPurchase', 1);
|
||||
}
|
||||
})
|
64
wiki/files/btmonitor/PluginLoader.py
Normal file
64
wiki/files/btmonitor/PluginLoader.py
Normal file
@@ -0,0 +1,64 @@
|
||||
#coding: utf-8
|
||||
import os,sys,json
|
||||
import core.include.public as public
|
||||
|
||||
#执行模块方法(模块名,方法名,参数)
|
||||
def module_run(module_name, def_name, def_args):
|
||||
if not module_name or not def_name: return public.returnMsg(False,'模块名称和模块方法名称不能为空!')
|
||||
if not path_check(module_name) or not path_check(def_name): return public.returnMsg(False,'模块名或方法名不能包含特殊符号!')
|
||||
|
||||
panel_path = public.get_panel_path()
|
||||
filename = "{}/modules/{}Module/{}Module.py".format(panel_path,module_name,module_name)
|
||||
if not os.path.exists(filename):
|
||||
filename = "{}/modules/{}Module/main.py".format(panel_path,module_name)
|
||||
if not os.path.exists(filename):
|
||||
filename = "{}/plugin/{}/main.py".format(panel_path,module_name)
|
||||
if not os.path.exists(filename):
|
||||
filename = "{}/plugin/{}Module/{}Plugin.py".format(panel_path,module_name,module_name)
|
||||
if not os.path.exists(filename):
|
||||
return public.returnMsg(False,'指定模块或插件不存在')
|
||||
|
||||
_obj = public.get_script_object(filename)
|
||||
if not _obj: return public.returnMsg(False,'模块加载失败: %s' % module_name)
|
||||
if hasattr(_obj, "items") and hasattr(_obj, "setdefault"):
|
||||
return _obj
|
||||
|
||||
class_name = "main"
|
||||
if not hasattr(_obj, class_name):
|
||||
return public.returnMsg(False,'找不到入口类: %s' % class_name)
|
||||
|
||||
class_obj = getattr(_obj,class_name, None)
|
||||
if not class_obj:
|
||||
return public.returnMsg(False,'获取入口类失败' % module_name)
|
||||
|
||||
try:
|
||||
class_func = class_obj()
|
||||
except:
|
||||
return public.returnMsg(False,'模块入口实例化失败' % module_name)
|
||||
|
||||
if not hasattr(class_func, def_name):
|
||||
return public.returnMsg(False,'在[%s]模块中找不到[%s]方法' % (class_name,def_name))
|
||||
|
||||
def_func = getattr(class_func, def_name, None)
|
||||
if not def_func:
|
||||
return public.returnMsg(False,'获取方法失败')
|
||||
|
||||
if 'module_get_object' in def_args:
|
||||
return def_func
|
||||
|
||||
result = def_func(def_args)
|
||||
return result
|
||||
|
||||
#获取指定模块对象(文件全路径)
|
||||
def get_module(filename):
|
||||
if not filename: return public.returnMsg(False,'模块路径不能为空!')
|
||||
if "./" in filename: return public.returnMsg(False,'模块路径不能为相对路径')
|
||||
return public.get_script_object(filename)
|
||||
|
||||
#检查路径是否合法
|
||||
def path_check(path):
|
||||
list = ["./","..",",",";",":","?","'","\"","<",">","|","\\","\n","\r","\t","\b","\a","\f","\v","*","%","&","$","#","@","!","~","`","^","(",")","+","=","{","}","[","]"]
|
||||
for i in path:
|
||||
if i in list:
|
||||
return False
|
||||
return True
|
@@ -36,6 +36,7 @@ def get_auth_state():
|
||||
#执行插件方法(插件名,方法名,参数)
|
||||
def plugin_run(plugin_name, def_name, args):
|
||||
if not plugin_name or not def_name: return public.returnMsg(False,'插件名称和插件方法名称不能为空!')
|
||||
if not path_check(plugin_name) or not path_check(def_name): return public.returnMsg(False,'插件名或方法名不能包含特殊符号!')
|
||||
p_path = public.get_plugin_path(plugin_name)
|
||||
if not os.path.exists(p_path + '/index.php') and not os.path.exists(p_path + '/%s_main.py' % plugin_name): return public.returnMsg(False,'插件不存在!')
|
||||
|
||||
@@ -73,12 +74,21 @@ def plugin_run(plugin_name, def_name, args):
|
||||
#执行模块方法(模块名,方法名,参数)
|
||||
def module_run(mod_name, def_name, args):
|
||||
if not mod_name or not def_name: return public.returnMsg(False,'模块名称和模块方法名称不能为空!')
|
||||
if not path_check(mod_name) or not path_check(def_name): return public.returnMsg(False,'模块名或方法名不能包含特殊符号!')
|
||||
|
||||
if 'model_index' in args:
|
||||
if args.model_index:
|
||||
mod_file = "{}/{}Model/{}Model.py".format(public.get_class_path(),args.model_index,mod_name)
|
||||
else:
|
||||
mod_file = "{}/projectModel/{}Model.py".format(public.get_class_path(),mod_name)
|
||||
else:
|
||||
module_list = get_module_list()
|
||||
for module_dir in module_list:
|
||||
mod_file = "{}/{}/{}Model.py".format(public.get_class_path(),module_dir,mod_name)
|
||||
if os.path.exists(mod_file): break
|
||||
|
||||
mod_file = "{}/projectModel/{}Model.py".format(public.get_class_path(),mod_name)
|
||||
if not os.path.exists(mod_file):
|
||||
mod_file = "{}/databaseModel/{}Model.py".format(public.get_class_path(),mod_name)
|
||||
if not os.path.exists(mod_file):
|
||||
return public.returnMsg(False,'模块[%s]不存在' % mod_name)
|
||||
return public.returnMsg(False,'模块[%s]不存在' % mod_name)
|
||||
|
||||
def_object = public.get_script_object(mod_file)
|
||||
if not def_object: return public.returnMsg(False,'模块[%s]不存在!' % mod_name)
|
||||
@@ -92,3 +102,21 @@ def module_run(mod_name, def_name, args):
|
||||
result = run_object(args)
|
||||
return result
|
||||
|
||||
#获取模块文件夹列表
|
||||
def get_module_list():
|
||||
list = []
|
||||
class_path = public.get_class_path()
|
||||
f_list = os.listdir(class_path)
|
||||
for fname in f_list:
|
||||
f_path = class_path+'/'+fname
|
||||
if os.path.isdir(f_path) and len(fname) > 6 and fname.find('.') == -1 and fname.find('Model') != -1:
|
||||
list.append(fname)
|
||||
return list
|
||||
|
||||
#检查路径是否合法
|
||||
def path_check(path):
|
||||
list = ["./","..",",",";",":","?","'","\"","<",">","|","\\","\n","\r","\t","\b","\a","\f","\v","*","%","&","$","#","@","!","~","`","^","(",")","+","=","{","}","[","]"]
|
||||
for i in path:
|
||||
if i in list:
|
||||
return False
|
||||
return True
|
433
wiki/files/linux/bt.js
Normal file
433
wiki/files/linux/bt.js
Normal file
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
*宝塔面板去除各种计算题与延时等待
|
||||
*/
|
||||
if("undefined" != typeof bt && bt.hasOwnProperty("show_confirm")){
|
||||
bt.show_confirm = function(title, msg, callback, error) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
area: "365px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
btn: [lan['public'].ok, lan['public'].cancel],
|
||||
content: "<div class='bt-form webDelete pd20'>\
|
||||
<p style='font-size:13px;word-break: break-all;margin-bottom: 5px;'>" + msg + "</p>" + (error || '') + "\
|
||||
</div>",
|
||||
yes: function (index, layero) {
|
||||
layer.close(index);
|
||||
if (callback) callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof bt && bt.hasOwnProperty("prompt_confirm")){
|
||||
bt.prompt_confirm = function (title, msg, callback) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
area: "350px",
|
||||
closeBtn: 2,
|
||||
btn: ['确认', '取消'],
|
||||
content: "<div class='bt-form promptDelete pd20'>\
|
||||
<p>" + msg + "</p>\
|
||||
</div>",
|
||||
yes: function (layers, index) {
|
||||
layer.close(layers)
|
||||
if (callback) callback()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof database && database.hasOwnProperty("del_database")){
|
||||
database.del_database = function (wid, dbname, obj, callback) {
|
||||
var is_db_type = false, del_data = []
|
||||
if (typeof wid === 'object') {
|
||||
del_data = wid
|
||||
is_db_type = wid.some(function (item) {
|
||||
return item.db_type > 0
|
||||
})
|
||||
var ids = [];
|
||||
for (var i = 0; i < wid.length; i++) {
|
||||
ids.push(wid[i].id);
|
||||
}
|
||||
wid = ids
|
||||
}
|
||||
var type = $('.database-pos .tabs-item.active').data('type'),
|
||||
title = '',
|
||||
tips = '';
|
||||
title = typeof dbname === "function" ? '批量删除数据库' : '删除数据库 - [ ' + dbname + ' ]';
|
||||
tips = is_db_type || !recycle_bin_db_open || type !== 'mysql' ? '<span class="color-red">当前列表存在彻底删除后无法恢复的数据库</span>,请仔细查看列表,以防误删,是否继续操作?' : '当前列表数据库将迁移至数据库回收站,如需彻底删除请前往数据库回收站,是否继续操作?'
|
||||
var arrs = wid instanceof Array ? wid : [wid]
|
||||
var ids = JSON.stringify(arrs),
|
||||
countDown = 9;
|
||||
if (arrs.length == 1) countDown = 4
|
||||
var loadT = bt.load('正在检测数据库数据信息,请稍候...'),
|
||||
param = { url: 'database/' + bt.data.db_tab_name + '/check_del_data', data: { data: JSON.stringify({ ids: ids }) } }
|
||||
if (bt.data.db_tab_name == 'mysql') param = { url: 'database?action=check_del_data', data: { ids: ids } }
|
||||
bt_tools.send(param, function (res) {
|
||||
loadT.close()
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
area: '740px',
|
||||
skin: 'verify_site_layer_info',
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content: '<div class="check_delete_site_main hint_confirm pd30">' +
|
||||
"<div class='hint_title'>\
|
||||
<i class=\'hint-confirm-icon\'></i>\
|
||||
<div class=\'hint_con\'>"+ tips + "</div>\
|
||||
</div>"+
|
||||
'<div id="check_layer_content" class="ptb15">' +
|
||||
'</div>' +
|
||||
'<div class="check_layer_message">' +
|
||||
(is_db_type ? '<span class="color-red">注意:远程数据库暂不支持数据库回收站,选中的数据库将彻底删除</span><br>' : '') +
|
||||
(!recycle_bin_db_open ? '<span class="color-red">风险操作:当前数据库回收站未开启,删除数据库将永久消失</span><br>' : '')
|
||||
+ '<span class="color-red">请仔细阅读以上要删除信息,防止数据库被误删</span></div>' +
|
||||
'</div>',
|
||||
btn: ['下一步', lan.public.cancel],
|
||||
success: function (layers) {
|
||||
setTimeout(function () { $(layers).css('top', ($(window).height() - $(layers).height()) / 2); }, 50)
|
||||
var rdata = res.data,
|
||||
newTime = parseInt(new Date().getTime() / 1000),
|
||||
t_icon = ' <span class="glyphicon glyphicon-info-sign" style="color: red;width:15px;height: 15px;;vertical-align: middle;"></span>';
|
||||
for (var j = 0; j < rdata.length; j++) {
|
||||
for (var i = 0; i < del_data.length; i++) {
|
||||
if (rdata[j].id == del_data[i].id) {
|
||||
var is_time_rule = (newTime - rdata[j].st_time) > (86400 * 30) && (rdata[j].total > 1024 * 10),
|
||||
is_database_rule = res.db_size <= rdata[j].total,
|
||||
database_time = bt.format_data(rdata[j].st_time, 'yyyy-MM-dd'),
|
||||
database_size = bt.format_size(rdata[j].total);
|
||||
var f_size = database_size
|
||||
var t_size = '注意:此数据库较大,可能为重要数据,请谨慎操作.\n数据库:' + database_size;
|
||||
if (rdata[j].total < 2048) t_size = '注意事项:当前数据库不为空,可能为重要数据,请谨慎操作.\n数据库:' + database_size;
|
||||
if (rdata[j].total === 0) t_size = '';
|
||||
rdata[j]['t_size'] = t_size
|
||||
rdata[j]['f_size'] = f_size
|
||||
rdata[j]['database_time'] = database_time
|
||||
rdata[j]['is_time_rule'] = is_time_rule
|
||||
rdata[j]['is_database_rule'] = is_database_rule
|
||||
rdata[j]['db_type'] = del_data[i].db_type
|
||||
rdata[j]['conn_config'] = del_data[i].conn_config
|
||||
}
|
||||
}
|
||||
}
|
||||
var filterData = rdata.filter(function (el) {
|
||||
return ids.indexOf(el.id) != -1
|
||||
})
|
||||
bt_tools.table({
|
||||
el: '#check_layer_content',
|
||||
data: filterData,
|
||||
height: '300px',
|
||||
column: [
|
||||
{ fid: 'name', title: '数据库名称' },
|
||||
{
|
||||
title: '数据库大小', template: function (row) {
|
||||
return '<span class="' + (row.is_database_rule ? 'warning' : '') + '" style="width: 110px;" title="' + row.t_size + '">' + row.f_size + (row.is_database_rule ? t_icon : '') + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '数据库位置', template: function (row) {
|
||||
var type_column = '-'
|
||||
switch (row.db_type) {
|
||||
case 0:
|
||||
type_column = '本地数据库'
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
type_column = '远程数据库'
|
||||
break;
|
||||
}
|
||||
return '<span style="width: 110px;" title="' + type_column + '">' + type_column + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '创建时间', template: function (row) {
|
||||
return '<span ' + (is_time_rule && row.total != 0 ? 'class="warning"' : '') + ' title="' + (row.is_time_rule && row.total != 0 ? '重要:此数据库创建时间较早,可能为重要数据,请谨慎操作.' : '') + '时间:' + row.database_time + '">' + row.database_time + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '删除结果', align: 'right', template: function (row, index, ev, _that) {
|
||||
var _html = ''
|
||||
switch (row.db_type) {
|
||||
case 0:
|
||||
_html = type !== 'mysql' ? '彻底删除' : (!recycle_bin_db_open ? '彻底删除' : '移至回收站')
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
_html = '彻底删除'
|
||||
break;
|
||||
}
|
||||
return '<span style="width: 110px;" class="' + (_html === '彻底删除' ? 'warning' + (row.db_type > 0 ? ' remote_database' : '') : '') + '">' + _html + '</span>'
|
||||
}
|
||||
}
|
||||
],
|
||||
success: function () {
|
||||
$('#check_layer_content').find('.glyphicon-info-sign').click(function (e) {
|
||||
var msg = $(this).parent().prop('title')
|
||||
msg = msg.replace('数据库:','<br>数据库:')
|
||||
layer.tips(msg, $(this).parent(), { tips: [1, 'red'], time: 3000 })
|
||||
$(document).click(function (ev) {
|
||||
layer.closeAll('tips');
|
||||
$(this).unbind('click');
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
});
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
if ($('.remote_database').length) {
|
||||
$('.remote_database').each(function (index, el) {
|
||||
var id = $(el).parent().parent().parent().index()
|
||||
$('#check_layer_content tbody tr').eq(id).css('background-color', '#ff00000a')
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
yes: function (indes, layers) {
|
||||
title = typeof dbname === "function" ? '二次验证信息,批量删除数据库' : '二次验证信息,删除数据库 - [ ' + dbname + ' ]';
|
||||
if (type !== 'mysql') {
|
||||
tips = '<span class="color-red">当前数据库暂不支持数据库回收站,删除后将无法恢复</span>,此操作不可逆,是否继续操作?';
|
||||
} else {
|
||||
tips = is_db_type ? '<span class="color-red">远程数据库不支持数据库回收站,删除后将无法恢复</span>,此操作不可逆,是否继续操作?' : recycle_bin_db_open ? '删除后如需彻底删除请前往数据库回收站,是否继续操作?' : '删除后可能会影响业务使用,此操作不可逆,是否继续操作?'
|
||||
}
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
icon: 0,
|
||||
skin: 'delete_site_layer',
|
||||
area: "530px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content: "<div class=\'bt-form webDelete hint_confirm pd30\' id=\'site_delete_form\'>" +
|
||||
"<div class='hint_title'>\
|
||||
<i class=\'hint-confirm-icon\'></i>\
|
||||
<div class=\'hint_con\'>"+ tips + "</div>\
|
||||
</div>"+
|
||||
"<div style=\'color:red;margin:18px 0 18px 18px;font-size:14px;font-weight: bold;\'>注意:数据无价,请谨慎操作!!!" + (type === 'mysql' && !recycle_bin_db_open ? '<br>风险操作:当前数据库回收站未开启,删除数据库将永久消失!' : '') + "</div>"+
|
||||
"</div>",
|
||||
btn: ['确认删除', '取消删除'],
|
||||
yes: function (indexs) {
|
||||
var data = {
|
||||
id: wid,
|
||||
name: dbname
|
||||
};
|
||||
if (typeof dbname === "function") {
|
||||
delete data.id;
|
||||
delete data.name;
|
||||
}
|
||||
layer.close(indexs)
|
||||
layer.close(indes)
|
||||
if (typeof dbname === "function") {
|
||||
dbname(data)
|
||||
} else {
|
||||
data.id = data.id[0]
|
||||
bt.database.del_database(data, function (rdata) {
|
||||
layer.closeAll()
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof site && site.hasOwnProperty("del_site")){
|
||||
site.del_site = function (wid, wname, callback) {
|
||||
title = typeof wname === "function" ? '批量删除站点' : '删除站点 [ ' + wname + ' ]';
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
icon: 0,
|
||||
skin: 'delete_site_layer',
|
||||
area: "440px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content: "<div class=\'bt-form webDelete pd30\' id=\'site_delete_form\'>" +
|
||||
'<i class="layui-layer-ico layui-layer-ico0"></i>' +
|
||||
"<div class=\'f13 check_title\'>是否要删除关联的FTP、数据库、站点目录!</div>" +
|
||||
"<div class=\"check_type_group\">" +
|
||||
"<label><input type=\"checkbox\" name=\"ftp\"><span>FTP</span></label>" +
|
||||
"<label><input type=\"checkbox\" name=\"database\"><span>数据库</span>" + (!recycle_bin_db_open ? '<span class="glyphicon glyphicon-info-sign" style="color: red"></span>' : '') + "</label>" +
|
||||
"<label><input type=\"checkbox\" name=\"path\"><span>站点目录</span>" + (!recycle_bin_open ? '<span class="glyphicon glyphicon-info-sign" style="color: red"></span>' : '') + "</label>" +
|
||||
"</div>" +
|
||||
"</div>",
|
||||
btn: [lan.public.ok, lan.public.cancel],
|
||||
success: function (layers, indexs) {
|
||||
$(layers).find('.check_type_group label').hover(function () {
|
||||
var name = $(this).find('input').attr('name');
|
||||
if (name === 'database' && !recycle_bin_db_open) {
|
||||
layer.tips('风险操作:当前数据库回收站未开启,删除数据库将永久消失!', this, { tips: [1, 'red'], time: 0 })
|
||||
} else if (name === 'path' && !recycle_bin_open) {
|
||||
layer.tips('风险操作:当前文件回收站未开启,删除站点目录将永久消失!', this, { tips: [1, 'red'], time: 0 })
|
||||
}
|
||||
}, function () {
|
||||
layer.closeAll('tips');
|
||||
});
|
||||
},
|
||||
yes: function (indexs) {
|
||||
var data = { id: wid, webname: wname };
|
||||
$('#site_delete_form input[type=checkbox]').each(function (index, item) {
|
||||
if ($(item).is(':checked')) data[$(item).attr('name')] = 1
|
||||
})
|
||||
var is_database = data.hasOwnProperty('database'), is_path = data.hasOwnProperty('path'), is_ftp = data.hasOwnProperty('ftp');
|
||||
if ((!is_database && !is_path) && (!is_ftp || is_ftp)) {
|
||||
if (typeof wname === "function") {
|
||||
wname(data)
|
||||
return false;
|
||||
}
|
||||
bt.site.del_site(data, function (rdata) {
|
||||
layer.close(indexs);
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
})
|
||||
return false
|
||||
}
|
||||
if (typeof wname === "function") {
|
||||
delete data.id;
|
||||
delete data.webname;
|
||||
}
|
||||
layer.close(indexs)
|
||||
var ids = JSON.stringify(wid instanceof Array ? wid : [wid]), countDown = typeof wname === 'string' ? 4 : 9;
|
||||
title = typeof wname === "function" ? '二次验证信息,批量删除站点' : '二次验证信息,删除站点 [ ' + wname + ' ]';
|
||||
var loadT = bt.load('正在检测站点数据信息,请稍候...')
|
||||
bt.send('check_del_data', 'site/check_del_data', { ids: ids }, function (res) {
|
||||
loadT.close()
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
closeBtn: 2,
|
||||
skin: 'verify_site_layer_info',
|
||||
area: '740px',
|
||||
content: '<div class="check_delete_site_main pd30">' +
|
||||
'<i class="layui-layer-ico layui-layer-ico0"></i>' +
|
||||
'<div class="check_layer_title">堡塔温馨提示您,请冷静几秒钟,确认以下要删除的数据。</div>' +
|
||||
'<div class="check_layer_content">' +
|
||||
'<div class="check_layer_item">' +
|
||||
'<div class="check_layer_site"></div>' +
|
||||
'<div class="check_layer_database"></div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="check_layer_error ' + (is_database && data['database'] && !recycle_bin_db_open ? '' : 'hide') + '"><span class="glyphicon glyphicon-info-sign"></span>风险事项:当前未开启数据库回收站功能,删除数据库后,数据库将永久消失!</div>' +
|
||||
'<div class="check_layer_error ' + (is_path && data['path'] && !recycle_bin_open ? '' : 'hide') + '"><span class="glyphicon glyphicon-info-sign"></span>风险事项:当前未开启文件回收站功能,删除站点目录后,站点目录将永久消失!</div>' +
|
||||
'<div class="check_layer_message"><span style="color:red">注意:请仔细阅读以上要删除信息,防止网站数据被误删</span></div>' +
|
||||
'</div>',
|
||||
// recycle_bin_db_open &&
|
||||
// recycle_bin_open &&
|
||||
btn: ['确认删除', '取消删除'],
|
||||
success: function (layers) {
|
||||
var html = '', rdata = res.data;
|
||||
for (var i = 0; i < rdata.length; i++) {
|
||||
var item = rdata[i], newTime = parseInt(new Date().getTime() / 1000),
|
||||
t_icon = '<span class="glyphicon glyphicon-info-sign" style="color: red;width:15px;height: 15px;;vertical-align: middle;"></span>';
|
||||
|
||||
site_html = (function (item) {
|
||||
if (!is_path) return ''
|
||||
var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10),
|
||||
is_path_rule = res.file_size <= item.total,
|
||||
dir_time = bt.format_data(item.st_time, 'yyyy-MM-dd'),
|
||||
dir_size = bt.format_size(item.total);
|
||||
|
||||
var f_html = '<i ' + (is_path_rule ? 'class="warning"' : '') + ' style = "vertical-align: middle;" > ' + (item.limit ? '大于50MB' : dir_size) + '</i> ' + (is_path_rule ? t_icon : '');
|
||||
var f_title = (is_path_rule ? '注意:此目录较大,可能为重要数据,请谨慎操作.\n' : '') + '目录:' + item.path + '(' + (item.limit ? '大于' : '') + dir_size + ')';
|
||||
|
||||
return '<div class="check_layer_site">' +
|
||||
'<span title="站点:' + item.name + '">站点名:' + item.name + '</span>' +
|
||||
'<span title="' + f_title + '" >目录:<span style="vertical-align: middle;max-width: 160px;width: auto;">' + item.path + '</span> (' + f_html + ')</span>' +
|
||||
'<span title="' + (is_time_rule ? '注意:此站点创建时间较早,可能为重要数据,请谨慎操作.\n' : '') + '时间:' + dir_time + '">创建时间:<i ' + (is_time_rule ? 'class="warning"' : '') + '>' + dir_time + '</i></span>' +
|
||||
'</div>'
|
||||
}(item)),
|
||||
database_html = (function (item) {
|
||||
if (!is_database || !item.database) return '';
|
||||
var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10),
|
||||
is_database_rule = res.db_size <= item.database.total,
|
||||
database_time = bt.format_data(item.database.st_time, 'yyyy-MM-dd'),
|
||||
database_size = bt.format_size(item.database.total);
|
||||
|
||||
var f_size = '<i ' + (is_database_rule ? 'class="warning"' : '') + ' style = "vertical-align: middle;" > ' + database_size + '</i> ' + (is_database_rule ? t_icon : '');
|
||||
var t_size = '注意:此数据库较大,可能为重要数据,请谨慎操作.\n数据库:' + database_size;
|
||||
|
||||
return '<div class="check_layer_database">' +
|
||||
'<span title="数据库:' + item.database.name + '">数据库:' + item.database.name + '</span>' +
|
||||
'<span title="' + t_size + '">大小:' + f_size + '</span>' +
|
||||
'<span title="' + (is_time_rule && item.database.total != 0 ? '重要:此数据库创建时间较早,可能为重要数据,请谨慎操作.' : '') + '时间:' + database_time + '">创建时间:<i ' + (is_time_rule && item.database.total != 0 ? 'class="warning"' : '') + '>' + database_time + '</i></span>' +
|
||||
'</div>'
|
||||
}(item))
|
||||
if ((site_html + database_html) !== '') html += '<div class="check_layer_item">' + site_html + database_html + '</div>';
|
||||
}
|
||||
if (html === '') html = '<div style="text-align: center;width: 100%;height: 100%;line-height: 300px;font-size: 15px;">无数据</div>'
|
||||
$('.check_layer_content').html(html)
|
||||
},
|
||||
yes: function (indes, layers) {
|
||||
if (typeof wname === "function") {
|
||||
wname(data)
|
||||
} else {
|
||||
bt.site.del_site(data, function (rdata) {
|
||||
layer.closeAll()
|
||||
if (rdata.status) site.get_list();
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof bt && bt.hasOwnProperty("firewall") && bt.firewall.hasOwnProperty("add_accept_port")){
|
||||
bt.firewall.add_accept_port = function(type, port, ps, callback) {
|
||||
var action = "AddDropAddress";
|
||||
if (type == 'port') {
|
||||
ports = port.split(':');
|
||||
if (port.indexOf('-') != -1) ports = port.split('-');
|
||||
for (var i = 0; i < ports.length; i++) {
|
||||
if (!bt.check_port(ports[i])) {
|
||||
layer.msg('可用端口范围:1-65535', { icon: 2 });
|
||||
// layer.msg(lan.firewall.port_err, {
|
||||
// icon: 5
|
||||
// });
|
||||
return;
|
||||
}
|
||||
}
|
||||
action = "AddAcceptPort";
|
||||
}
|
||||
|
||||
loading = bt.load();
|
||||
bt.send(action, 'firewall/' + action, { port: port, type: type, ps: ps }, function(rdata) {
|
||||
loading.close();
|
||||
if (callback) callback(rdata);
|
||||
})
|
||||
}
|
||||
}
|
||||
function SafeMessage(j, h, g, f) {
|
||||
if(f == undefined) {
|
||||
f = ""
|
||||
}
|
||||
var mess = layer.open({
|
||||
type: 1,
|
||||
title: j,
|
||||
area: "350px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content: "<div class='bt-form webDelete pd20 pb70'><p>" + h + "</p>" + f + "<div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm bt-cancel'>"+lan.public.cancel+"</button> <button type='button' id='toSubmit' class='btn btn-success btn-sm' >"+lan.public.ok+"</button></div></div>"
|
||||
});
|
||||
$(".bt-cancel").click(function(){
|
||||
layer.close(mess);
|
||||
});
|
||||
$("#toSubmit").click(function() {
|
||||
layer.close(mess);
|
||||
g();
|
||||
})
|
||||
}
|
||||
$(document).ready(function () {
|
||||
if($('#updata_pro_info').length>0){
|
||||
$('#updata_pro_info').html('');
|
||||
bt.set_cookie('productPurchase', 1);
|
||||
}
|
||||
})
|
122
wiki/files/win/PluginLoader.py
Normal file
122
wiki/files/win/PluginLoader.py
Normal file
@@ -0,0 +1,122 @@
|
||||
#coding: utf-8
|
||||
import public,os,sys,json
|
||||
|
||||
#获取插件列表(0/1)
|
||||
def get_plugin_list(force = 0):
|
||||
api_root_url = 'https://api.bt.cn'
|
||||
api_url = api_root_url+ '/wpanel/get_plugin_list'
|
||||
cache_file = 'data/plugin_list.json'
|
||||
|
||||
if force==0 and os.path.exists(cache_file):
|
||||
jsonData = public.readFile(cache_file)
|
||||
softList = json.loads(jsonData)
|
||||
else:
|
||||
try:
|
||||
jsonData = public.HttpGet(api_url)
|
||||
except Exception as ex:
|
||||
raise public.error_conn_cloud(str(ex))
|
||||
softList = json.loads(jsonData)
|
||||
if type(softList)!=dict or 'list' not in softList: raise Exception('云端插件列表获取失败')
|
||||
public.writeFile(cache_file, jsonData)
|
||||
return softList
|
||||
|
||||
#获取授权状态() 返回:0.免费版 1.专业版 2.企业版 -1.获取失败
|
||||
def get_auth_state():
|
||||
try:
|
||||
softList = get_plugin_list()
|
||||
if softList['ltd'] > -1:
|
||||
return 2
|
||||
elif softList['pro'] > -1:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
except:
|
||||
return -1
|
||||
|
||||
#执行插件方法(插件名,方法名,参数)
|
||||
def plugin_run(plugin_name, def_name, args):
|
||||
if not plugin_name or not def_name: return public.returnMsg(False,'插件名称和插件方法名称不能为空!')
|
||||
if not path_check(plugin_name) or not path_check(def_name): return public.returnMsg(False,'插件名或方法名不能包含特殊符号!')
|
||||
p_path = public.get_plugin_path(plugin_name)
|
||||
if not os.path.exists(p_path + '/index.php') and not os.path.exists(p_path + '/%s_main.py' % plugin_name): return public.returnMsg(False,'插件不存在!')
|
||||
|
||||
is_php = os.path.exists(p_path + '/index.php')
|
||||
if not is_php:
|
||||
sys.path.append(p_path)
|
||||
plugin_main = __import__(plugin_name + '_main')
|
||||
try:
|
||||
if sys.version_info[0] == 2:
|
||||
reload(plugin_main)
|
||||
else:
|
||||
from imp import reload
|
||||
reload(plugin_main)
|
||||
except:
|
||||
pass
|
||||
plu = eval('plugin_main.' + plugin_name + '_main()')
|
||||
if not hasattr(plu, def_name):
|
||||
return public.returnMsg(False,'在[%s]插件中找不到[%s]方法' % (plugin_name,def_name))
|
||||
|
||||
if 'plugin_get_object' in args and args.plugin_get_object == 1:
|
||||
if not is_php:
|
||||
return getattr(plu, def_name)
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
if not is_php:
|
||||
data = eval('plu.' + def_name + '(args)')
|
||||
else:
|
||||
import panelPHP
|
||||
args.s = def_name
|
||||
args.name = plugin_name
|
||||
data = panelPHP.panelPHP(plugin_name).exec_php_script(args)
|
||||
return data
|
||||
|
||||
#执行模块方法(模块名,方法名,参数)
|
||||
def module_run(mod_name, def_name, args):
|
||||
if not mod_name or not def_name: return public.returnMsg(False,'模块名称和模块方法名称不能为空!')
|
||||
if not path_check(mod_name) or not path_check(def_name): return public.returnMsg(False,'模块名或方法名不能包含特殊符号!')
|
||||
|
||||
if 'model_index' in args:
|
||||
if args.model_index:
|
||||
mod_file = "{}/{}Model/{}Model.py".format(public.get_class_path(),args.model_index,mod_name)
|
||||
else:
|
||||
mod_file = "{}/projectModel/{}Model.py".format(public.get_class_path(),mod_name)
|
||||
else:
|
||||
module_list = get_module_list()
|
||||
for module_dir in module_list:
|
||||
mod_file = "{}/{}/{}Model.py".format(public.get_class_path(),module_dir,mod_name)
|
||||
if os.path.exists(mod_file): break
|
||||
|
||||
if not os.path.exists(mod_file):
|
||||
return public.returnMsg(False,'模块[%s]不存在' % mod_name)
|
||||
|
||||
def_object = public.get_script_object(mod_file)
|
||||
if not def_object: return public.returnMsg(False,'模块[%s]不存在!' % mod_name)
|
||||
try:
|
||||
run_object = getattr(def_object.main(),def_name,None)
|
||||
except:
|
||||
return public.returnMsg(False,'模块入口实例化失败' % mod_name)
|
||||
if not run_object: return public.returnMsg(False,'在[%s]模块中找不到[%s]方法' % (mod_name,def_name))
|
||||
if 'module_get_object' in args and args.module_get_object == 1:
|
||||
return run_object
|
||||
result = run_object(args)
|
||||
return result
|
||||
|
||||
#获取模块文件夹列表
|
||||
def get_module_list():
|
||||
list = []
|
||||
class_path = public.get_class_path()
|
||||
f_list = os.listdir(class_path)
|
||||
for fname in f_list:
|
||||
f_path = class_path+'/'+fname
|
||||
if os.path.isdir(f_path) and len(fname) > 6 and fname.find('.') == -1 and fname.find('Model') != -1:
|
||||
list.append(fname)
|
||||
return list
|
||||
|
||||
#检查路径是否合法
|
||||
def path_check(path):
|
||||
list = ["./","..",",",";",":","?","'","\"","<",">","|","\\","\n","\r","\t","\b","\a","\f","\v","*","%","&","$","#","@","!","~","`","^","(",")","+","=","{","}","[","]"]
|
||||
for i in path:
|
||||
if i in list:
|
||||
return False
|
||||
return True
|
@@ -43,66 +43,128 @@ if("undefined" != typeof bt && bt.hasOwnProperty("prompt_confirm")){
|
||||
}
|
||||
if("undefined" != typeof database && database.hasOwnProperty("del_database")){
|
||||
database.del_database = function (wid, dbname,obj, callback) {
|
||||
var tips = '是否确认【删除数据库】,删除后可能会影响业务使用!';
|
||||
if(obj && obj.db_type > 0) tips = '远程数据库不支持数据库回收站,删除后将无法恢复,请谨慎操作';
|
||||
var title = typeof dbname === "function" ?'批量删除数据库':'删除数据库 [ '+ dbname +' ]';
|
||||
layer.open({
|
||||
type:1,
|
||||
title:title,
|
||||
icon:0,
|
||||
skin:'delete_site_layer',
|
||||
area: "530px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content:"<div class=\'bt-form webDelete pd30\' id=\'site_delete_form\'>" +
|
||||
"<i class=\'layui-layer-ico layui-layer-ico0\'></i>" +
|
||||
"<div class=\'f13 check_title\' style=\'margin-bottom: 20px;\'>"+tips+"</div>" +
|
||||
"<div style=\'color:red;margin:18px 0 18px 18px;font-size:14px;font-weight: bold;\'>注意:数据无价,请谨慎操作!!!"+(!recycle_bin_db_open?'<br>风险操作:当前数据库回收站未开启,删除数据库将永久消失!':'')+"</div>" +
|
||||
"</div>",
|
||||
btn:[lan.public.ok,lan.public.cancel],
|
||||
yes:function(indexs){
|
||||
var data = {id: wid,name: dbname};
|
||||
if(typeof dbname === "function"){
|
||||
delete data.id;
|
||||
delete data.name;
|
||||
}
|
||||
layer.close(indexs)
|
||||
if(typeof dbname === "function"){
|
||||
dbname(data)
|
||||
}else{
|
||||
bt.database.del_database(data, function (rdata) {
|
||||
layer.closeAll()
|
||||
if (rdata.status) database_table.$refresh_table_list(true);
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
var title = '',
|
||||
tips = '是否确认【删除数据库】,删除后可能会影响业务使用!';
|
||||
if(obj && obj.db_type > 0) tips = '远程数据库不支持数据库回收站,删除后将无法恢复,请谨慎操作';
|
||||
title = typeof dbname === "function" ?'批量删除数据库':'删除数据库 [ '+ dbname +' ]';
|
||||
layer.open({
|
||||
type:1,
|
||||
title:title,
|
||||
icon:0,
|
||||
skin:'delete_site_layer',
|
||||
area: "530px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content:"<div class=\'bt-form webDelete pd30\' id=\'site_delete_form\'>" +
|
||||
"<i class=\'layui-layer-ico layui-layer-ico0\'></i>" +
|
||||
"<div class=\'f13 check_title\' style=\'margin-bottom: 20px;\'>"+tips+"</div>" +
|
||||
"<div style=\'color:red;margin:18px 0 18px 18px;font-size:14px;font-weight: bold;\'>注意:数据无价,请谨慎操作!!!"+(!recycle_bin_db_open?'<br>风险操作:当前数据库回收站未开启,删除数据库将永久消失!':'')+"</div>" +
|
||||
"</div>",
|
||||
btn:[lan.public.ok,lan.public.cancel],
|
||||
yes:function(indexs){
|
||||
var data = {id: wid,name: dbname};
|
||||
if(typeof dbname === "function"){
|
||||
delete data.id;
|
||||
delete data.name;
|
||||
}
|
||||
layer.close(indexs)
|
||||
var arrs = wid instanceof Array ? wid : [wid]
|
||||
var ids = JSON.stringify(arrs), countDown = 9;
|
||||
if (arrs.length == 1) countDown = 4
|
||||
title = typeof dbname === "function" ?'二次验证信息,批量删除数据库':'二次验证信息,删除数据库 [ ' + dbname + ' ]';
|
||||
var loadT = bt.load('正在检测数据库数据信息,请稍后...')
|
||||
|
||||
bt_tools.send({url:'database/'+bt.data.db_tab_name+'/check_del_data',data:{data:JSON.stringify({ids: ids})}},function(res){
|
||||
loadT.close()
|
||||
layer.open({
|
||||
type:1,
|
||||
title:title,
|
||||
closeBtn: 2,
|
||||
skin: 'verify_site_layer_info',
|
||||
area: '740px',
|
||||
content: '<div class="check_delete_site_main pd30">' +
|
||||
'<i class="layui-layer-ico layui-layer-ico0"></i>' +
|
||||
'<div class="check_layer_title">堡塔温馨提示您,请冷静几秒钟,确认是否要删除以下数据。</div>' +
|
||||
'<div class="check_layer_content">' +
|
||||
'<div class="check_layer_item">' +
|
||||
'<div class="check_layer_site"></div>' +
|
||||
'<div class="check_layer_database"></div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="check_layer_error ' + (recycle_bin_db_open ? 'hide' : '') + '"><span class="glyphicon glyphicon-info-sign"></span>风险事项:当前未开启数据库回收站功能,删除数据库后,数据库将永久消失!</div>' +
|
||||
'<div class="check_layer_message"><span style="color:red">注意:请仔细阅读以上要删除信息,防止数据库被误删</span></div>' +
|
||||
'</div>',
|
||||
btn: ['确认删除', '取消删除'],
|
||||
success: function (layers) {
|
||||
var html = '', rdata = res.data;
|
||||
var filterData = rdata.filter(function(el){
|
||||
return ids.indexOf(el.id) != -1
|
||||
})
|
||||
for (var i = 0; i < filterData.length; i++) {
|
||||
var item = filterData[i], newTime = parseInt(new Date().getTime() / 1000),
|
||||
t_icon = '<span class="glyphicon glyphicon-info-sign" style="color: red;width:15px;height: 15px;;vertical-align: middle;"></span>';
|
||||
|
||||
database_html = (function(item){
|
||||
var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10),
|
||||
is_database_rule = res.db_size <= item.total,
|
||||
database_time = bt.format_data(item.st_time, 'yyyy-MM-dd'),
|
||||
database_size = bt.format_size(item.total);
|
||||
|
||||
var f_size = '<i ' + (is_database_rule ? 'class="warning"' : '') + ' style = "vertical-align: middle;" > ' + database_size + '</i> ' + (is_database_rule ? t_icon : '');
|
||||
var t_size = '注意:此数据库较大,可能为重要数据,请谨慎操作.\n数据库:' + database_size;
|
||||
|
||||
return '<div class="check_layer_database">' +
|
||||
'<span title="数据库:' + item.name + '">数据库:' + item.name + '</span>' +
|
||||
'<span title="' + t_size+'">大小:' + f_size +'</span>' +
|
||||
'<span title="' + (is_time_rule && item.total != 0 ? '重要:此数据库创建时间较早,可能为重要数据,请谨慎操作.' : '') + '时间:' + database_time+'">创建时间:<i ' + (is_time_rule && item.total != 0 ? 'class="warning"' : '') + '>' + database_time + '</i></span>' +
|
||||
'</div>'
|
||||
}(item))
|
||||
if(database_html !== '') html += '<div class="check_layer_item">' + database_html +'</div>';
|
||||
}
|
||||
if(html === '') html = '<div style="text-align: center;width: 100%;height: 100%;line-height: 300px;font-size: 15px;">无数据</div>'
|
||||
$('.check_layer_content').html(html)
|
||||
},
|
||||
yes:function(indes,layers){
|
||||
if(typeof dbname === "function"){
|
||||
dbname(data)
|
||||
}else{
|
||||
bt.database.del_database(data, function (rdata) {
|
||||
layer.closeAll()
|
||||
if (rdata.status) database_table.$refresh_table_list(true);
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof site && site.hasOwnProperty("del_site")){
|
||||
site.del_site = function(wid, wname, callback) {
|
||||
var title = typeof wname === "function" ?'批量删除站点':'删除站点 [ '+ wname +' ]';
|
||||
var title = typeof wname === "function" ? '批量删除站点' : '删除站点 [ ' + wname + ' ]';
|
||||
recycle_bin_open = bt.get_cookie("is_recycle") || bt.get_cookie("is_recycle") == null ? true : false
|
||||
layer.open({
|
||||
type:1,
|
||||
title:title,
|
||||
icon:0,
|
||||
skin:'delete_site_layer',
|
||||
type: 1,
|
||||
title: title,
|
||||
icon: 0,
|
||||
skin: 'delete_site_layer',
|
||||
area: "440px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content:"<div class=\'bt-form webDelete pd30\' id=\'site_delete_form\'>" +
|
||||
content: "<div class=\'bt-form webDelete pd30\' id=\'site_delete_form\'>" +
|
||||
'<i class="layui-layer-ico layui-layer-ico0"></i>' +
|
||||
"<div class=\'f13 check_title\'>是否要删除关联的FTP、数据库、站点目录!</div>" +
|
||||
"<div class=\"check_type_group\">" +
|
||||
"<label><input type=\"checkbox\" name=\"ftp\"><span>FTP</span></label>" +
|
||||
"<label><input type=\"checkbox\" name=\"database\"><span>数据库</span>"+ (!recycle_bin_db_open?'<span class="glyphicon glyphicon-info-sign" style="color: red"></span>':'') +"</label>" +
|
||||
"<label><input type=\"checkbox\" name=\"path\"><span>站点目录</span>"+ (!recycle_bin_open?'<span class="glyphicon glyphicon-info-sign" style="color: red"></span>':'') +"</label>" +
|
||||
"</div>"+
|
||||
"<label><input type=\"checkbox\" name=\"database\"><span>数据库</span>" + (!recycle_bin_db_open ? '<span class="glyphicon glyphicon-info-sign" style="color: red"></span>' : '') + "</label>" +
|
||||
"<label><input type=\"checkbox\" name=\"path\"><span>站点目录</span>" + (!recycle_bin_open ? '<span class="glyphicon glyphicon-info-sign" style="color: red"></span>' : '') + "</label>" +
|
||||
"</div>" +
|
||||
"</div>",
|
||||
btn:[lan.public.ok,lan.public.cancel],
|
||||
success:function(layers,indexs){
|
||||
btn: [lan.public.ok, lan.public.cancel],
|
||||
success: function (layers, indexs) {
|
||||
$(layers).find('.check_type_group label').hover(function () {
|
||||
var name = $(this).find('input').attr('name');
|
||||
if (name === 'data' && !recycle_bin_db_open) {
|
||||
@@ -114,14 +176,14 @@ if("undefined" != typeof site && site.hasOwnProperty("del_site")){
|
||||
layer.closeAll('tips');
|
||||
})
|
||||
},
|
||||
yes:function(indexs){
|
||||
var data = {id: wid,webname: wname};
|
||||
yes: function (indexs) {
|
||||
var data = { id: wid, webname: wname };
|
||||
$('#site_delete_form input[type=checkbox]').each(function (index, item) {
|
||||
if($(item).is(':checked')) data[$(item).attr('name')] = 1
|
||||
if ($(item).is(':checked')) data[$(item).attr('name')] = 1
|
||||
})
|
||||
var is_database = data.hasOwnProperty('database'),is_path = data.hasOwnProperty('path'),is_ftp = data.hasOwnProperty('ftp');
|
||||
if((!is_database && !is_path) && (!is_ftp || is_ftp)){
|
||||
if(typeof wname === "function"){
|
||||
var is_database = data.hasOwnProperty('database'), is_path = data.hasOwnProperty('path'), is_ftp = data.hasOwnProperty('ftp');
|
||||
if ((!is_database && !is_path) && (!is_ftp || is_ftp)) {
|
||||
if (typeof wname === "function") {
|
||||
wname(data)
|
||||
return false;
|
||||
}
|
||||
@@ -132,24 +194,104 @@ if("undefined" != typeof site && site.hasOwnProperty("del_site")){
|
||||
})
|
||||
return false
|
||||
}
|
||||
if(typeof wname === "function"){
|
||||
if (typeof wname === "function") {
|
||||
delete data.id;
|
||||
delete data.webname;
|
||||
}
|
||||
layer.close(indexs)
|
||||
if(typeof wname === "function"){
|
||||
console.log(data)
|
||||
wname(data)
|
||||
}else{
|
||||
bt.site.del_site(data, function (rdata) {
|
||||
layer.closeAll()
|
||||
if (rdata.status) site.get_list();
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
var arrs = wid instanceof Array ? wid : [wid]
|
||||
var ids = JSON.stringify(arrs), countDown = 9;
|
||||
if (arrs.length == 1) countDown = 4
|
||||
title = typeof wname === "function" ? '二次验证信息,批量删除站点' : '二次验证信息,删除站点 [ ' + wname + ' ]';
|
||||
var loadT = bt.load('正在检测站点数据信息,请稍后...')
|
||||
bt.send('check_del_data', 'site/check_del_data', { ids: ids }, function (res) {
|
||||
loadT.close()
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
closeBtn: 2,
|
||||
skin: 'verify_site_layer_info',
|
||||
area: '740px',
|
||||
content: '<div class="check_delete_site_main pd30">' +
|
||||
'<i class="layui-layer-ico layui-layer-ico0"></i>' +
|
||||
'<div class="check_layer_title">堡塔温馨提示您,请冷静几秒钟,确认以下要删除的数据。</div>' +
|
||||
'<div class="check_layer_content">' +
|
||||
'<div class="check_layer_item">' +
|
||||
'<div class="check_layer_site"></div>' +
|
||||
'<div class="check_layer_database"></div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="check_layer_error ' + (data.database && recycle_bin_db_open ? 'hide' : '') + '"><span class="glyphicon glyphicon-info-sign"></span>风险事项:当前未开启数据库回收站功能,删除数据库后,数据库将永久消失!</div>' +
|
||||
'<div class="check_layer_error ' + (data.path && recycle_bin_open ? 'hide' : '') + '"><span class="glyphicon glyphicon-info-sign"></span>风险事项:当前未开启文件回收站功能,删除站点目录后,站点目录将永久消失!</div>' +
|
||||
'<div class="check_layer_message"><span style="color:red">注意:请仔细阅读以上要删除信息,防止网站数据被误删</span></div>' +
|
||||
'</div>',
|
||||
// recycle_bin_db_open &&
|
||||
// recycle_bin_open &&
|
||||
btn: ['确认删除', '取消删除'],
|
||||
success: function (layers) {
|
||||
var html = '', rdata = res.data;
|
||||
for (var i = 0; i < rdata.length; i++) {
|
||||
var item = rdata[i], newTime = parseInt(new Date().getTime() / 1000),
|
||||
t_icon = '<span class="glyphicon glyphicon-info-sign" style="color: red;width:15px;height: 15px;;vertical-align: middle;"></span>';
|
||||
|
||||
site_html = (function (item) {
|
||||
if (!is_path) return ''
|
||||
var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10),
|
||||
is_path_rule = res.file_size <= item.total,
|
||||
dir_time = bt.format_data(item.st_time, 'yyyy-MM-dd'),
|
||||
dir_size = bt.format_size(item.total);
|
||||
|
||||
var f_html = '<i ' + (is_path_rule ? 'class="warning"' : '') + ' style = "vertical-align: middle;" > ' + dir_size + '</i> ' + (is_path_rule ? t_icon : '');
|
||||
var f_title = (is_path_rule ? '注意:此目录较大,可能为重要数据,请谨慎操作.\n' : '') + '目录:' + item.path + '(' + (item.limit ? '大于' : '') + dir_size + ')';
|
||||
|
||||
return '<div class="check_layer_site">' +
|
||||
'<span title="站点:' + item.name + '">站点名:' + item.name + '</span>' +
|
||||
'<span title="' + f_title + '" >目录:<span style="vertical-align: middle;max-width: 160px;width: auto;">' + item.path + '</span> (' + f_html + ')</span>' +
|
||||
'<span title="' + (is_time_rule ? '注意:此站点创建时间较早,可能为重要数据,请谨慎操作.\n' : '') + '时间:' + dir_time + '">创建时间:<i ' + (is_time_rule ? 'class="warning"' : '') + '>' + dir_time + '</i></span>' +
|
||||
'</div>'
|
||||
}(item)),
|
||||
database_html = (function (item) {
|
||||
if (!is_database || !item.database) return '';
|
||||
var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10),
|
||||
is_database_rule = res.db_size <= item.database.total,
|
||||
database_time = bt.format_data(item.database.st_time, 'yyyy-MM-dd'),
|
||||
database_size = bt.format_size(item.database.total);
|
||||
|
||||
var f_size = '<i ' + (is_database_rule ? 'class="warning"' : '') + ' style = "vertical-align: middle;" > ' + database_size + '</i> ' + (is_database_rule ? t_icon : '');
|
||||
var t_size = '注意:此数据库较大,可能为重要数据,请谨慎操作.\n数据库:' + database_size;
|
||||
|
||||
return '<div class="check_layer_database">' +
|
||||
'<span title="数据库:' + item.database.name + '">数据库:' + item.database.name + '</span>' +
|
||||
'<span title="' + t_size + '">大小:' + f_size + '</span>' +
|
||||
'<span title="' + (is_time_rule && item.database.total != 0 ? '重要:此数据库创建时间较早,可能为重要数据,请谨慎操作.' : '') + '时间:' + database_time + '">创建时间:<i ' + (is_time_rule && item.database.total != 0 ? 'class="warning"' : '') + '>' + database_time + '</i></span>' +
|
||||
'</div>'
|
||||
}(item))
|
||||
if ((site_html + database_html) !== '') html += '<div class="check_layer_item">' + site_html + database_html + '</div>';
|
||||
}
|
||||
if (html === '') html = '<div style="text-align: center;width: 100%;height: 100%;line-height: 300px;font-size: 15px;">无数据</div>'
|
||||
$('.check_layer_content').html(html)
|
||||
},
|
||||
yes: function (indes, layers) {
|
||||
if (typeof wname === "function") {
|
||||
wname(data)
|
||||
} else {
|
||||
bt.site.del_site(data, function (rdata) {
|
||||
layer.closeAll()
|
||||
if (rdata.status) site.get_list();
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
if(bt.get_cookie("is_recycle") || bt.get_cookie("is_recycle")==null){
|
||||
$('[name="path"]').attr('checked',true)
|
||||
}else{
|
||||
$('[name="path"]').removeProp('checked');
|
||||
}
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof bt && bt.hasOwnProperty("firewall") && bt.firewall.hasOwnProperty("add_accept_port")){
|
||||
|
@@ -1,60 +0,0 @@
|
||||
#coding: utf-8
|
||||
import public,os,sys,json
|
||||
|
||||
class Plugin:
|
||||
name = False
|
||||
p_path = None
|
||||
is_php = False
|
||||
plu = None
|
||||
__api_root_url = 'https://api.bt.cn'
|
||||
__api_url = __api_root_url+ '/wpanel/get_plugin_list'
|
||||
__cache_file = 'data/plugin_list.json'
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.p_path = public.get_plugin_path(name)
|
||||
self.is_php = os.path.exists(self.p_path + '/index.php')
|
||||
|
||||
def get_plugin_list(self, force = False):
|
||||
if force==False and os.path.exists(self.__cache_file):
|
||||
jsonData = public.readFile(self.__cache_file)
|
||||
softList = json.loads(jsonData)
|
||||
else:
|
||||
try:
|
||||
jsonData = public.HttpGet(self.__api_url)
|
||||
except Exception as ex:
|
||||
raise public.error_conn_cloud(str(ex))
|
||||
softList = json.loads(jsonData)
|
||||
if type(softList)!=dict or 'list' not in softList: raise Exception('云端插件列表获取失败')
|
||||
public.writeFile(self.__cache_file, jsonData)
|
||||
|
||||
return softList
|
||||
|
||||
def isdef(self, fun):
|
||||
if not self.is_php:
|
||||
sys.path.append(self.p_path)
|
||||
plugin_main = __import__(self.name + '_main')
|
||||
try:
|
||||
from imp import reload
|
||||
reload(plugin_main)
|
||||
except:
|
||||
pass
|
||||
self.plu = eval('plugin_main.' + self.name + '_main()')
|
||||
if not hasattr(self.plu, fun):
|
||||
if self.name == 'btwaf' and fun == 'index':
|
||||
raise Exception("未购买")
|
||||
return False
|
||||
return True
|
||||
|
||||
def exec_fun(self, args):
|
||||
fun = args.s
|
||||
if not self.is_php:
|
||||
plu = self.plu
|
||||
data = eval('plu.' + fun + '(args)')
|
||||
else:
|
||||
import panelPHP
|
||||
args.s = fun
|
||||
args.name = self.name
|
||||
data = panelPHP.panelPHP(self.name).exec_php_script(args)
|
||||
return data
|
||||
|
@@ -8,13 +8,15 @@
|
||||
|
||||
- 将class文件夹里面所有的.so文件删除
|
||||
|
||||
- 将PluginLoader.py复制到class文件夹
|
||||
- 将linux/PluginLoader.py复制到class文件夹
|
||||
|
||||
- 批量解密模块文件:执行 php think decrypt classdir <面板class文件夹路径>
|
||||
|
||||
- 全局搜索替换 https://api.bt.cn => http://www.example.com
|
||||
|
||||
- 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/(需排除clearModel.py)
|
||||
- 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/(需排除clearModel.py、scanningModel.py、ipsModel.py)
|
||||
|
||||
- 全局搜索替换 http://download.bt.cn/install/update6.sh => http://www.example.com/install/update6.sh
|
||||
- 全局搜索替换 https://download.bt.cn/install/update6.sh => http://www.example.com/install/update6.sh
|
||||
|
||||
- class/ajax.py 文件 \#是否执行升级程序 下面的 public.get_url() 改成 public.GetConfigValue('home')
|
||||
|
||||
@@ -38,20 +40,30 @@
|
||||
|
||||
在 def check_domain_cloud(domain): 这一行下面加上 return
|
||||
|
||||
在 def get_improvement(): 这一行下面加上 return False
|
||||
|
||||
在free_login_area方法内get_free_ips_area替换成get_ips_area
|
||||
|
||||
- class/panelPlugin.py 文件,download_icon方法内替换 public.GetConfigValue('home') => 'https://www.bt.cn'
|
||||
|
||||
- class/panelPlugin.py 文件,set_pyenv方法内,temp_file = public.readFile(filename)这行代码下面加上
|
||||
删除public.total_keyword(get.query)这一行
|
||||
|
||||
set_pyenv方法内,temp_file = public.readFile(filename)这行代码下面加上
|
||||
|
||||
```python
|
||||
temp_file = temp_file.replace('wget -O Tpublic.sh', '#wget -O Tpublic.sh')
|
||||
temp_file = temp_file.replace('\cp -rpa Tpublic.sh', '#\cp -rpa Tpublic.sh')
|
||||
temp_file = temp_file.replace('http://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh')
|
||||
temp_file = temp_file.replace('https://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh')
|
||||
```
|
||||
|
||||
|
||||
- class/plugin_deployment.py 文件,SetupPackage方法内替换 public.GetConfigValue('home') => 'https://www.bt.cn'
|
||||
|
||||
- install/install_soft.sh 在bash执行之前加入以下代码
|
||||
|
||||
```shell
|
||||
sed -i "s/http:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" lib.sh
|
||||
sed -i "s/https:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" lib.sh
|
||||
sed -i "/wget -O Tpublic.sh/d" $name.sh
|
||||
```
|
||||
|
||||
@@ -61,18 +73,18 @@
|
||||
|
||||
"update_software_list": update_software_list,
|
||||
|
||||
"check_files_panel": check_files_panel,
|
||||
|
||||
"check_panel_msg": check_panel_msg,
|
||||
|
||||
- 去除面板日志上报:script/site_task.py 文件
|
||||
PluginLoader.daemon_panel()
|
||||
|
||||
删除最下面 logs_analysis() 这1行
|
||||
- 去除WebRTC连接:BTPanel/static/js/public.js 删除stun.start();这一行
|
||||
|
||||
- 去除首页广告:BTPanel/static/js/index.js 文件删除最下面index.recommend_paid_version()这一行
|
||||
|
||||
- 去除首页自动检测更新,避免频繁请求云端:BTPanel/static/js/index.js 文件注释掉bt.system.check_update这一段代码外的setTimeout
|
||||
|
||||
- 去除内页广告:BTPanel/templates/default/layout.html 删除getPaymentStatus();这一行
|
||||
|
||||
- [可选]去除各种计算题:复制bt.js到 BTPanel/static/ ,在 BTPanel/templates/default/layout.html 的\</body\>前面加入
|
||||
|
||||
```javascript
|
||||
|
@@ -8,11 +8,11 @@
|
||||
|
||||
Windows版宝塔由于加密文件太多,无法全部解密,因此无法做到全开源。
|
||||
|
||||
- 删除pluginAuth.cp38-win_amd64.pyd,将win/pluginAuth.py复制到class文件夹
|
||||
- 删除PluginLoader.pyd,将win/PluginLoader.py复制到class文件夹
|
||||
|
||||
- 全局搜索替换 https://api.bt.cn => http://www.example.com
|
||||
|
||||
- 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/
|
||||
- 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/(需排除ipsModel.py)
|
||||
|
||||
- 全局搜索替换 http://www.bt.cn/api/ => http://www.example.com/api/
|
||||
|
||||
@@ -50,12 +50,14 @@ Windows版宝塔由于加密文件太多,无法全部解密,因此无法做
|
||||
|
||||
- 去除面板日志上报:script/site_task.py 文件
|
||||
|
||||
删除最下面 logs_analysis() 这1行
|
||||
- 删除最下面 logs_analysis() 这1行
|
||||
|
||||
- 去除首页广告:BTPanel/static/js/index.js 文件删除最下面index.recommend_paid_version()这一行
|
||||
- 去除首页广告:BTPanel/static/js/index.js 文件删除最下面index.recommend_paid_version()这一行以及index.consultancy_services()这一行
|
||||
|
||||
- 去除首页自动检测更新,避免频繁请求云端:BTPanel/static/js/index.js 文件注释掉bt.system.check_update这一段代码外的setTimeout
|
||||
|
||||
- 去除内页广告:BTPanel/templates/default/layout.html 删除getPaymentStatus();这一行
|
||||
|
||||
- [可选]去除各种计算题:复制win/bt.js到 BTPanel/static/ ,在 BTPanel/templates/default/layout.html 的尾部加入
|
||||
|
||||
```javascript
|
||||
@@ -72,5 +74,5 @@ Windows版宝塔由于加密文件太多,无法全部解密,因此无法做
|
||||
|
||||
删除 if not os.path.exists(self.sitePath + '/.htaccess') 这一行
|
||||
|
||||
|
||||
- [可选]关闭自动生成访问日志:在 BTPanel/\_\_init\_\_.py 删除public.write_request_log()这一行
|
||||
|
||||
|
Reference in New Issue
Block a user