Compare commits

...

14 Commits
3.3 ... main

Author SHA1 Message Date
flucout
08bd35c997 update 2026-01-23 16:00:06 +08:00
flucout
c0ebc38d54 update 2026-01-10 22:28:33 +08:00
flucout
c7381fd675 update 2025-12-16 23:14:27 +08:00
flucout
1ed4ac8d39 update 2025-12-16 23:05:40 +08:00
flucout
3d5cb3cddf update 2025-11-25 22:26:04 +08:00
flucout
8fd2b5fc87 update 2025-11-05 21:29:13 +08:00
flucout
56f6a3242b update 2025-09-24 18:57:28 +08:00
flucout
ab322ca6e1 update 2025-08-11 15:30:56 +08:00
flucout
dff7fa67e7 update 2025-08-08 19:06:34 +08:00
flucout
263f5aec86 update 2025-07-27 22:48:52 +08:00
flucout
4e48a2722d update 2025-07-27 16:18:19 +08:00
flucout
28a34b273a update 2025-07-26 10:48:03 +08:00
flucout
655b408493 update 2025-07-26 10:44:47 +08:00
flucout
42500b40d1 修复无法获取宝塔恶意IP 2025-05-30 10:14:05 +08:00
41 changed files with 1377 additions and 607 deletions

View File

@ -101,26 +101,43 @@ class CleanViteJs extends Command
} }
private function handlefile($filepath){ private function handlefile($filepath){
//echo $filepath."\n";
$file = file_get_contents($filepath); $file = file_get_contents($filepath);
if(!$file)return; if(!$file)return;
$flag = false; $flag = false;
if(strpos($file, 'window.location.protocol.indexOf("https")>=0')!==false){ //index if(strpos($file, 'window.location.protocol.indexOf("https")>=0')!==false){ //index
$file = str_replace('(window.location.protocol.indexOf("https")>=0)', '1', $file); $file = str_replace('window.location.protocol.indexOf("https")>=0', '!0', $file);
$code = $this->getExtendCode($file, 'isGetCoupon:', 2); $code = $this->getExtendCode($file, 'isGetCoupon:', 2);
if($code){ if($code){
$file = str_replace($code, '{}', $file); $file = str_replace($code, '{}', $file);
} }
$file = preg_replace('!recommendShow:\w+,!', 'recommendShow:!1,', $file, 1); $file = preg_replace('!recommendShow:\w+,!', 'recommendShow:!1,', $file, 1);
$code = $this->getExtendCode($file, '"需求反馈"', 1, '[', ']'); $code = $this->getExtendCode($file, '"打开需求反馈"', 1, '[', ']');
if($code){ if($code){
$file = str_replace($code, '[]', $file); $file = str_replace($code, '[]', $file);
} }
$flag = true; $flag = true;
} }
if(strpos($file, '论坛求助')!==false){ //main if(strpos($file, '"点击打开调查问卷"')!==false){ //index
$code = $this->getExtendCode($file, '"点击打开调查问卷"', 2);
if($code){
$file = str_replace($code, '{}', $file);
}
$flag = true;
}
if(strpos($file, '您有{0}个优惠券待领取')!==false){ //win-index
$code = $this->getExtendCode($file, 'isGetCoupon:', 2);
if($code){
$file = str_replace($code, '{}', $file);
}
$flag = true;
}
if(strpos($file, '论坛求助')!==false && strpos($file, '"/other/customer-qrcode.png"')!==false){ //main
$code = $this->getExtendCode($file, '"微信公众号"', 1); $code = $this->getExtendCode($file, '"微信公众号"', 1);
$code = $this->getExtendFunction($file, $code); $code = $this->getExtendFunction($file, $code);
$start = strpos($file, $code) - 1; $start = strpos($file, $code) - 1;
@ -143,17 +160,28 @@ class CleanViteJs extends Command
if($code){ if($code){
$file = str_replace($code, '{}', $file); $file = str_replace($code, '{}', $file);
} }
$file = preg_replace('!\w+\(\(\(\)=>"calc"===\w+\.\w+\.type\)\)!', '!1', $file); $file = preg_replace('!computed\(\(\)=>"calc"===\w+\.\w+\.type\)!', '!1', $file);
$file = preg_replace('!\w+\(\(\(\)=>"input"===\w+\.\w+\.type\)\)!', '!1', $file); $file = preg_replace('!computed\(\(\)=>"input"===\w+\.\w+\.type\)!', '!1', $file);
$file = preg_replace('!\w+\(\(function\(\)\{return"calc"===\w+\.\w+\.type\}\)\)!', '!1', $file); $file = preg_replace('!computed\(function\(\)\{return"calc"===\w+\.\w+\.type\}\)!', '!1', $file);
$file = preg_replace('!\w+\(\(function\(\)\{return"input"===\w+\.\w+\.type\}\)\)!', '!1', $file); $file = preg_replace('!computed\(function\(\)\{return"input"===\w+\.\w+\.type\}\)!', '!1', $file);
$file = preg_replace('!computed\(\(\)=>\w+\.\w+\.type==="calc"\)!', '!1', $file);
$file = preg_replace('!computed\(\(\)=>\w+\.\w+\.type==="input"\)!', '!1', $file);
$file = preg_replace('!computed\(function\(\)\{return\w+\.\w+\.type==="calc"\}\)!', '!1', $file);
$file = preg_replace('!computed\(function\(\)\{return\w+\.\w+\.type==="input"\}\)!', '!1', $file);
$code = $this->getExtendCode($file, '"自动部署"', 2); $code = $this->getExtendCode($file, '"自动部署"', 2);
if($code){ if($code){
$file = str_replace($code.',', '', $file);
$file = str_replace($code, '', $file); $file = str_replace($code, '', $file);
} }
$flag = true; $flag = true;
} }
if(strpos($file, '"sqlserver管理"')!==false && strpos($file, '"iis管理"')!==false){ //win-utils
$file = preg_replace('!"calc"===\w+\.\w+\.type!', '!1', $file);
$file = preg_replace('!"input"===\w+\.\w+\.type!', '!1', $file);
$flag = true;
}
if(strpos($file, '请冷静几秒钟,确认以下要删除的数据')!==false && strpos($file, '"计算结果:"')!==false){ //site if(strpos($file, '请冷静几秒钟,确认以下要删除的数据')!==false && strpos($file, '"计算结果:"')!==false){ //site
$code = $this->getExtendCode($file, '"计算结果:"', 1, '[', ']'); $code = $this->getExtendCode($file, '"计算结果:"', 1, '[', ']');
$code = $this->getExtendFunction($file, $code); $code = $this->getExtendFunction($file, $code);
@ -179,18 +207,24 @@ class CleanViteJs extends Command
$flag = true; $flag = true;
} }
if(strpos($file, '"商用SSL证书"')!==false){ //site-ssl if(strpos($file, 'label:"商用SSL证书"')!==false){ //site-ssl
$code = $this->getExtendFunction($file, '"商用SSL证书"', '{', '}'); $code = $this->getExtendFunction($file, 'label:"商用SSL证书"', '{', '}');
$file = str_replace($code, '', $file); $file = str_replace($code, '', $file);
$code = $this->getExtendFunction($file, '"测试证书"', '{', '}'); $code = $this->getExtendFunction($file, 'label:"测试证书"', '{', '}');
if($code){
$file = str_replace($code, '', $file); $file = str_replace($code, '', $file);
}
$code = $this->getExtendFunction($file, 'label:"宝塔证书"', '{', '}');
if($code){
$file = str_replace($code, '', $file);
}
$code = $this->getExtendCode($file, '"购买商业证书"', 2); $code = $this->getExtendCode($file, '"购买商业证书"', 2);
if($code){ if($code){
$code2 = str_replace('"busSslList"', '"letsEncryptList"', $code); $code2 = str_replace('"busSslList"', '"letsEncryptList"', $code);
$code2 = str_replace($this->getExtendFunction($code, '"购买商业证书"'), '', $code2); $code2 = str_replace($this->getExtendFunction($code, '"购买商业证书"'), '', $code2);
$file = str_replace($code, $code2, $file); $file = str_replace($code, $code2, $file);
} }
$file = preg_replace('!(\w+)\("sslCertificate"\)!', '$1("EncryptCertificate")', $file); $file = str_replace('.value="busSslList"', '.value="letsEncryptList"', $file);
$flag = true; $flag = true;
} }
if(strpos($file, '"busSslList"')!==false && strpos($filepath, '/useStore')){ //site-ssl if(strpos($file, '"busSslList"')!==false && strpos($filepath, '/useStore')){ //site-ssl
@ -201,22 +235,32 @@ class CleanViteJs extends Command
if(strpos($file, '"商用SSL"')!==false){ //ssl if(strpos($file, '"商用SSL"')!==false){ //ssl
$code = $this->getExtendFunction($file, '"商用SSL"', '{', '}'); $code = $this->getExtendFunction($file, '"商用SSL"', '{', '}');
$file = str_replace($code, '', $file); $file = str_replace($code, '', $file);
$code = $this->getExtendFunction($file, '"测试证书"', '{', '}'); $code = $this->getExtendFunction($file, '"宝塔证书"', '{', '}');
if($code){
$file = str_replace($code, '', $file); $file = str_replace($code, '', $file);
}
for($i=0;$i<3;$i++){
$code = $this->getExtendCode($file, ',"联系客服"', 2, '[', ']'); $code = $this->getExtendCode($file, ',"联系客服"', 2, '[', ']');
if($code){ if($code){
$file = str_replace($code, '[]', $file); $file = str_replace($code, '[]', $file);
} }
$code = $this->getExtendCode($file, ',"联系客服"', 2, '[', ']');
if($code){
$file = str_replace($code, '[]', $file);
} }
$flag = true;
} }
if(strpos($file, '"SSL-CERTIFICATE-STORE"')!==false){ //ssl if(strpos($file, '"SSL-CERTIFICATE-STORE"')!==false){ //ssl
$file = str_replace('("ssl")', '("encrypt")', $file); $file = str_replace('("ssl")', '("encrypt")', $file);
$flag = true; $flag = true;
} }
if(strpos($file, '"商业证书"')!==false && strpos($file, 'name:"busSslList"')!==false && strpos($file, 'IIS配置')!==false){ //win-ssl
$code = $this->getExtendFunction($file, 'name:"busSslList"', '{', '}');
$file = str_replace($code, '', $file);
$code = $this->getExtendFunction($file, 'name:"trustAsiaList"', '{', '}');
$file = str_replace($code, '', $file);
$file = $this->str_replace_once('"busSslList"', '"currentCertInfo"', $file);
$flag = true;
}
if(strpos($file, '如果您希望添加其它Docker应用')!==false){ if(strpos($file, '如果您希望添加其它Docker应用')!==false){
$code = $this->getExtendCode($file, '如果您希望添加其它Docker应用', 1, '[', ']'); $code = $this->getExtendCode($file, '如果您希望添加其它Docker应用', 1, '[', ']');
$code = $this->getExtendFunction($file, $code); $code = $this->getExtendFunction($file, $code);
@ -231,9 +275,19 @@ class CleanViteJs extends Command
$flag = true; $flag = true;
} }
if(strpos($file, '"打开插件文件目录"')!==false){ //soft.table if(strpos($file, '"打开插件文件目录"')!==false && strpos($file, '"(续费)"')!==false){ //soft.table
$code = $this->getExtendFunction($file, '"(续费)"'); $code = $this->getExtendFunction($file, '"(续费)"');
$file = str_replace($code, '""', $file); $file = str_replace($code, '""', $file);
$code = $this->getExtendCode($file, 'activity_id:47', 2);
if($code){
$file = str_replace($code, '{}', $file);
}
$flag = true;
}
if(strpos($file, 'path:"register"')!==false){ //domain
$code = $this->getExtendCode($file, 'path:"register"');
$file = str_replace($code.',', '', $file);
$flag = true; $flag = true;
} }
@ -249,13 +303,13 @@ class CleanViteJs extends Command
$flag = true; $flag = true;
} }
} }
$code = $this->getExtendCode($file, '("需求反馈")', 1, '[', ']'); $code = $this->getExtendCode($file, '("需求反馈",-1)', 1, '[', ']');
if($code){ if($code){
$file = str_replace($code, '[]', $file); $file = str_replace($code, '[]', $file);
$flag = true; $flag = true;
} }
$code = $this->getExtendCode($file, '(" 需求反馈 ")', 1, '[', ']'); $code = $this->getExtendCode($file, '(" 需求反馈 ",-1)', 1, '[', ']');
if($code && strpos($filepath, 'vue_vue_type_') === false){ if($code){
$file = str_replace($code, '[]', $file); $file = str_replace($code, '[]', $file);
$flag = true; $flag = true;
} }
@ -265,7 +319,7 @@ class CleanViteJs extends Command
$flag = true; $flag = true;
} }
if(strpos('暂无搜索结果,<span class="text-primary cursor-pointer NpsDialog">提交需求反馈</span>', $file)!==false){ if(strpos($file, '暂无搜索结果,<span class="text-primary cursor-pointer NpsDialog">提交需求反馈</span>')!==false){
$file = str_replace('暂无搜索结果,<span class="text-primary cursor-pointer NpsDialog">提交需求反馈</span>', '暂无搜索结果', $file); $file = str_replace('暂无搜索结果,<span class="text-primary cursor-pointer NpsDialog">提交需求反馈</span>', '暂无搜索结果', $file);
$flag = true; $flag = true;
} }

View File

@ -58,6 +58,7 @@ class UpdateAll extends Command
//循环下载缺少的插件 //循环下载缺少的插件
foreach($json_arr['list'] as $plugin){ foreach($json_arr['list'] as $plugin){
if($type == 0 && ($plugin['type']==8 || $plugin['type']==12) || $type == 1 && $plugin['type']==12 || $plugin['type']==10 || $plugin['type']==5) continue; if($type == 0 && ($plugin['type']==8 || $plugin['type']==12) || $type == 1 && $plugin['type']==12 || $plugin['type']==10 || $plugin['type']==5) continue;
if(in_array($plugin['name'], \app\lib\BtPlugins::$skip_plugins)) continue;
foreach($plugin['versions'] as $version){ foreach($plugin['versions'] as $version){
$ver = $version['m_version'].'.'.$version['version']; $ver = $version['m_version'].'.'.$version['version'];

View File

@ -100,6 +100,7 @@ class Admin extends BaseController
View::assign('conf', config('sys')); View::assign('conf', config('sys'));
$runtime = Db::name('config')->where('key','runtime')->value('value') ?? '<font color="red">未运行</font>'; $runtime = Db::name('config')->where('key','runtime')->value('value') ?? '<font color="red">未运行</font>';
View::assign('runtime', $runtime); View::assign('runtime', $runtime);
View::assign('is_user_www', isset($_SERVER['USER']) && $_SERVER['USER'] == 'www');
return view(); return view();
} }
@ -143,8 +144,22 @@ class Admin extends BaseController
}else{ }else{
$bt_url = input('post.bt_url'); $bt_url = input('post.bt_url');
$bt_key = input('post.bt_key'); $bt_key = input('post.bt_key');
$os = input('post.os');
if(!$bt_url || !$bt_key)return json(['code'=>-1, 'msg'=>'参数不能为空']); if(!$bt_url || !$bt_key)return json(['code'=>-1, 'msg'=>'参数不能为空']);
$btapi = new Btapi($bt_url, $bt_key); $btapi = new Btapi($bt_url, $bt_key);
if ($os == 'win') {
$result = $btapi->get_config_go();
if($result && isset($result['config'])){
$result = $btapi->get_user_info();
if($result && isset($result['username'])){
return json(['code'=>0, 'msg'=>'面板连接测试成功!']);
}else{
return json(['code'=>-1, 'msg'=>'面板连接测试成功,但未安装专用插件/未登录账号']);
}
}else{
return json(['code'=>-1, 'msg'=>isset($result['msg'])?$result['msg']:'面板地址无法连接']);
}
} else {
$result = $btapi->get_config(); $result = $btapi->get_config();
if($result && isset($result['status']) && ($result['status']==1 || isset($result['sites_path']))){ if($result && isset($result['status']) && ($result['status']==1 || isset($result['sites_path']))){
$result = $btapi->get_user_info(); $result = $btapi->get_user_info();
@ -158,6 +173,7 @@ class Admin extends BaseController
} }
} }
} }
}
public function plugins(){ public function plugins(){
$typelist = []; $typelist = [];
@ -169,6 +185,7 @@ class Admin extends BaseController
} }
} }
View::assign('typelist', $typelist); View::assign('typelist', $typelist);
View::assign('skip_plugins', \app\lib\BtPlugins::$skip_plugins);
return view(); return view();
} }

View File

@ -2,6 +2,7 @@
namespace app\controller; namespace app\controller;
use think\facade\Db; use think\facade\Db;
use think\facade\Cache;
use app\BaseController; use app\BaseController;
use app\lib\Plugins; use app\lib\Plugins;
@ -18,13 +19,16 @@ class Api extends BaseController
Db::name('record')->insert(['ip'=>$this->clientip, 'addtime'=>date("Y-m-d H:i:s"), 'usetime'=>date("Y-m-d H:i:s")]); Db::name('record')->insert(['ip'=>$this->clientip, 'addtime'=>date("Y-m-d H:i:s"), 'usetime'=>date("Y-m-d H:i:s")]);
} }
$json_arr = Plugins::get_plugin_list(); $json_arr = Plugins::get_plugin_list();
if(!$json_arr) return json((object)[]); if(!$json_arr) $json_arr = (object)[];
return json($json_arr); return json($json_arr);
} }
//获取插件列表(win) //获取插件列表(win)
public function get_plugin_list_win(){ public function get_plugin_list_win(){
if(!$this->checklist()) return json('你的服务器被禁止使用此云端'); if(!$this->checklist()) return json('你的服务器被禁止使用此云端');
$os_version = input('post.os_version');
$serverid = input('post.serverid');
$uid = input('post.uid');
$record = Db::name('record')->where('ip',$this->clientip)->find(); $record = Db::name('record')->where('ip',$this->clientip)->find();
if($record){ if($record){
Db::name('record')->where('id',$record['id'])->update(['usetime'=>date("Y-m-d H:i:s")]); Db::name('record')->where('id',$record['id'])->update(['usetime'=>date("Y-m-d H:i:s")]);
@ -32,7 +36,10 @@ class Api extends BaseController
Db::name('record')->insert(['ip'=>$this->clientip, 'addtime'=>date("Y-m-d H:i:s"), 'usetime'=>date("Y-m-d H:i:s")]); Db::name('record')->insert(['ip'=>$this->clientip, 'addtime'=>date("Y-m-d H:i:s"), 'usetime'=>date("Y-m-d H:i:s")]);
} }
$json_arr = Plugins::get_plugin_list('Windows'); $json_arr = Plugins::get_plugin_list('Windows');
if(!$json_arr) return json((object)[]); if(!$json_arr) $json_arr = (object)[];
if($os_version == 'windows_go'){
return Plugins::encrypt_plugin_list($json_arr, $serverid, $uid);
}
return json($json_arr); return json($json_arr);
} }
@ -46,49 +53,49 @@ class Api extends BaseController
Db::name('record')->insert(['ip'=>$this->clientip, 'addtime'=>date("Y-m-d H:i:s"), 'usetime'=>date("Y-m-d H:i:s")]); Db::name('record')->insert(['ip'=>$this->clientip, 'addtime'=>date("Y-m-d H:i:s"), 'usetime'=>date("Y-m-d H:i:s")]);
} }
$json_arr = Plugins::get_plugin_list('en'); $json_arr = Plugins::get_plugin_list('en');
if(!$json_arr) return json((object)[]); if(!$json_arr) $json_arr = (object)[];
return json($json_arr); return json($json_arr);
} }
//下载插件包 //下载插件包
public function download_plugin(){ public function download_plugin(){
$plugin_name = input('post.name'); $plugin_name = input('param.name');
$version = input('post.version'); $version = input('param.version');
$os = input('post.os'); $os = input('param.os');
if(!$plugin_name || !$version){ if(!$plugin_name || !$version){
return '参数不能为空'; return json(['status'=>false, 'msg'=>'参数不能为空']);
} }
if(!in_array($os,['Windows','Linux'])) $os = 'Linux'; if(!in_array($os,['Windows','Linux'])) $os = 'Linux';
if(!preg_match('/^[a-zA-Z0-9_]+$/', $plugin_name) || !preg_match('/^[0-9.]+$/', $version)){ if(!preg_match('/^[a-zA-Z0-9_]+$/', $plugin_name) || !preg_match('/^[0-9.]+$/', $version)){
return '参数不正确'; return json(['status'=>false, 'msg'=>'参数不正确']);
} }
if(!$this->checklist()) return '你的服务器被禁止使用此云端'; if(!$this->checklist()) return json(['status'=>false, 'msg'=>'你的服务器被禁止使用此云端']);
$filepath = get_data_dir($os).'plugins/package/'.$plugin_name.'-'.$version.'.zip'; $filepath = get_data_dir($os).'plugins/package/'.$plugin_name.'-'.$version.'.zip';
if(file_exists($filepath)){ if(file_exists($filepath)){
$filename = $plugin_name.'.zip'; $filename = $plugin_name.'.zip';
$this->output_file($filepath, $filename); $this->output_file($filepath, $filename);
}else{ }else{
return '云端不存在该插件包'; return json(['status'=>false, 'msg'=>'云端不存在该插件包']);
} }
} }
//下载插件包aapanel //下载插件包aapanel
public function download_plugin_en(){ public function download_plugin_en(){
$plugin_name = input('post.name'); $plugin_name = input('param.name');
$version = input('post.version'); $version = input('param.version');
if(!$plugin_name || !$version){ if(!$plugin_name || !$version){
return '参数不能为空'; return json(['status'=>false, 'msg'=>'参数不能为空']);
} }
if(!preg_match('/^[a-zA-Z0-9_]+$/', $plugin_name) || !preg_match('/^[0-9.]+$/', $version)){ if(!preg_match('/^[a-zA-Z0-9_]+$/', $plugin_name) || !preg_match('/^[0-9.]+$/', $version)){
return '参数不正确'; return json(['status'=>false, 'msg'=>'参数不正确']);
} }
if(!$this->checklist()) return '你的服务器被禁止使用此云端'; if(!$this->checklist()) return json(['status'=>false, 'msg'=>'你的服务器被禁止使用此云端']);
$filepath = get_data_dir('en').'plugins/package/'.$plugin_name.'-'.$version.'.zip'; $filepath = get_data_dir('en').'plugins/package/'.$plugin_name.'-'.$version.'.zip';
if(file_exists($filepath)){ if(file_exists($filepath)){
$filename = $plugin_name.'.zip'; $filename = $plugin_name.'.zip';
$this->output_file($filepath, $filename); $this->output_file($filepath, $filename);
}else{ }else{
return '云端不存在该插件包'; return json(['status'=>false, 'msg'=>'云端不存在该插件包']);
} }
} }
@ -98,13 +105,13 @@ class Api extends BaseController
$version = input('post.version'); $version = input('post.version');
$os = input('post.os'); $os = input('post.os');
if(!$plugin_name || !$version){ if(!$plugin_name || !$version){
return '参数不能为空'; return json(['status'=>false, 'msg'=>'参数不能为空']);
} }
if(!in_array($os,['Windows','Linux'])) $os = 'Linux'; if(!in_array($os,['Windows','Linux'])) $os = 'Linux';
if(!preg_match('/^[a-zA-Z0-9_]+$/', $plugin_name) || !preg_match('/^[0-9.]+$/', $version)){ if(!preg_match('/^[a-zA-Z0-9_]+$/', $plugin_name) || !preg_match('/^[0-9.]+$/', $version)){
return '参数不正确'; return json(['status'=>false, 'msg'=>'参数不正确']);
} }
if(!$this->checklist()) return '你的服务器被禁止使用此云端'; if(!$this->checklist()) return json(['status'=>false, 'msg'=>'你的服务器被禁止使用此云端']);
$filepath = get_data_dir($os).'plugins/package/'.$plugin_name.'-'.$version.'.zip'; $filepath = get_data_dir($os).'plugins/package/'.$plugin_name.'-'.$version.'.zip';
$mainfilepath = get_data_dir($os).'plugins/folder/'.$plugin_name.'-'.$version.'/'.$plugin_name.'/'.$plugin_name.'_main.py'; $mainfilepath = get_data_dir($os).'plugins/folder/'.$plugin_name.'-'.$version.'/'.$plugin_name.'/'.$plugin_name.'_main.py';
if(file_exists($mainfilepath)){ if(file_exists($mainfilepath)){
@ -115,10 +122,10 @@ class Api extends BaseController
if ($zip->open($filepath) === true){ if ($zip->open($filepath) === true){
echo $zip->getFromName($plugin_name.'/'.$plugin_name.'_main.py'); echo $zip->getFromName($plugin_name.'/'.$plugin_name.'_main.py');
}else{ }else{
return '插件包解压缩失败'; return json(['status'=>false, 'msg'=>'插件包解压缩失败']);
} }
}else{ }else{
return '云端不存在该插件主文件'; return json(['status'=>false, 'msg'=>'云端不存在该插件主文件']);
} }
} }
@ -142,6 +149,36 @@ class Api extends BaseController
} }
} }
public function get_plugin_auth(){
$productids = ["8","9","10","11","12","13","14","15","16","17","18","19","20","22","23","24","25","26","28","32","33","42","44","45","47","55","65","69","75","82","83","85","90","91","97","99","101","107","108","110","118","121","127","128","132","135","136","140","143","144","151","154","156","161","163","167","173","179","183","185","190","192","195","197","200","201","202","203","204","205","206","207","208","212","213","214","215","216","217","218","219","220","221","222","223","224","225","226","227","228","229","230","231","232","233","234","235","236","237","238","239","241","243","244","245","246","247","248","249","250","251","252","253","254","255","256","257","258","259","261","262","263","264","265","266","267","268","269","270","271","272","273","274","275","276","277","278","279","280","281","282","283","284","285","286","287","289","292","293","295","296","297","298","299","300","301","302","303","304","305","306","307","308","309","310","311","312","313","314","315","316","317","318","319","320","321","322","323","324","325","326","327","328","329","330","331","332","334","335","336","337","338","339","340","341","342","343","344","345","346","347","348","349","350","351","352","353","354","355","356","357","358","359","360","361","362","363","364","365","366","368","369","371","372","373","374","375","376","377","378","379","380","381","382","383","384","385","386","387","388","389","390","391","392","393","394","397","398","400","401","406","408","409","411","413","415","419","423","425","427","429","430","1111111","100000001","100000005","100000007","100000008","100000009","100000010","100000012","100000014","100000015","100000016","100000017","100000035","100000036","100000039","100000040","100000041","100000042","100000045","100000053","100000054","100000056","100000057","100000058","100000059","100000062","100000063","100000067","100000069","100000070","100000076","100000077","100000078","100000079","100000080","100000084","100000085","100000088","100000089","100000090","100000091","100000092","100000093","100000094","100000095","100000096","100000097","100000098"];
$os_version = input('post.os_version');
$address = input('post.address','');
$uid = input('post.uid','');
$username = input('post.username','');
$serverid = input('post.serverid','');
$mac = input('post.mac','');
$data = ['ip'=>$address, 'uid'=>$uid, 'username'=>$username, 'serverid'=>$serverid, 'lasttime'=>time(), 'pro'=>-1, 'skey'=>'', 'ltd'=>strtotime('+10 year'), 'list'=>[]];
foreach($productids as $pid){
$data['list'][$pid] = strtotime('+10 year');
}
return Plugins::encrypt_plugin_list($data, $serverid, $uid);
}
public function get_plugin_auth_win(){
$productids = ["49","50","51","52","53","54","56","57","58","59","60","61","67","68","72","76","80","84","88","89","92","93","119","120","133","134","137","138","139","142","145","146","150","168","169","170","172","176","184","396","404","414","420","422","424","426","428","100000001","100000018","100000019","100000024","100000026","100000027","100000028","100000031","100000039","100000043","100000047","100000048","100000049","100000051","100000052","100000060","100000061","100000064","100000067","100000075"];
$os_version = input('post.os_version');
$address = input('post.address','');
$uid = input('post.uid','');
$username = input('post.username','');
$serverid = input('post.serverid','');
$mac = input('post.mac','');
$data = ['ip'=>$address, 'uid'=>$uid, 'username'=>$username, 'serverid'=>$serverid, 'lasttime'=>time(), 'pro'=>-1, 'skey'=>'', 'ltd'=>strtotime('+10 year'), 'list'=>[]];
foreach($productids as $pid){
$data['list'][$pid] = strtotime('+10 year');
}
return Plugins::encrypt_plugin_list($data, $serverid, $uid);
}
public function get_update_logs(){ public function get_update_logs(){
$type = input('get.type'); $type = input('get.type');
if($type == 'Windows'){ if($type == 'Windows'){
@ -327,6 +364,49 @@ class Api extends BaseController
return json(['status'=>true,'err_no'=>0,'msg'=>'获取成功','data'=>$data]); return json(['status'=>true,'err_no'=>0,'msg'=>'获取成功','data'=>$data]);
} }
//宝塔云控版本信息
public function cloudc_version_info(){
return json(['status'=>true,'msg'=>'获取成功','data'=>[
'version' => '1.0.5',
'download' => '',
'uptime' => '2025/06/16',
'upmsg' => '暂无更新日志'
]]);
}
//宝塔云控版本信息
public function cloudc_get_version(){
return json(['status'=>true,'msg'=>'','oid'=>'','data'=>[
'officialVersion' => [
'version' => '1.0.5',
'download' => '',
'uptime' => '2025/06/16',
'updateMsg' => '暂无更新日志'
],
]]);
}
//宝塔云控授权信息
public function cloudc_order_status(){
$data = [
'status' => true,
'msg' => '获取成功',
'oid' => '',
'data' => [
'id' => 1,
'address' => real_ip(),
'buytime' => time(),
'endtime' => time() + 86400 * 3650,
'num' => 9999,
'max_num' => 9999,
'pid' => 100000023,
'renew_price' => 0,
'state' => 1,
]
];
return json($data);
}
//获取内测版更新日志 //获取内测版更新日志
public function get_beta_logs(){ public function get_beta_logs(){
return json(['beta_ps'=>'当前暂无内测版', 'list'=>[]]); return json(['beta_ps'=>'当前暂无内测版', 'list'=>[]]);
@ -466,6 +546,51 @@ class Api extends BaseController
return json(['status'=>true, 'msg'=>'', 'data'=>$data]); return json(['status'=>true, 'msg'=>'', 'data'=>$data]);
} }
//获取堡塔云WAF恶意IP库
public function get_malicious_ip_list()
{
$cacheKey = 'malicious_ip_list';
// 尝试从缓存获取
if (Cache::has($cacheKey)) {
return json(json_decode(Cache::get($cacheKey), true));
}
$url = 'https://api.bt.cn/bt_waf/get_malicious_ip';
$postData = json_encode([
'x_bt_token' => 'MzI3YjAzOGQ3Yjk3NjUxYjVlMDkyMGFm'
]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($postData)
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
return json(['status'=>true, 'msg'=>'', 'data'=>bin2hex('[]')]);
}
curl_close($ch);
Cache::set($cacheKey, $response, 86400); //缓存一天
return json(json_decode($response, true));
}
public function get_ip_info(){
$ip = input('post.ip');
$data = [];
$url = 'https://www.bt.cn/api/ip/info_json';
$post = http_build_query(['ip'=>$ip]);
$response = get_curl($url, $post);
$arr = json_decode($response, true);
if($arr) $data = $arr;
return json($data);
}
public function return_success(){ public function return_success(){
return json(['status'=>true, 'msg'=>1, 'data'=>(object)[]]); return json(['status'=>true, 'msg'=>1, 'data'=>(object)[]]);
} }

View File

@ -11,7 +11,8 @@ class BtPlugins
private $os; private $os;
//需屏蔽的插件名称列表 //需屏蔽的插件名称列表
private static $block_plugins = ['dns','bt_boce','ssl_verify']; public static $block_plugins = ['dns', 'bt_boce', 'ssl_verify', 'firewall', 'KylinOperatingSystem', 'KingdeeApusicDistributedCache', 'BorlandCacheServer', 'GBase8s', 'KingdeeApusicLoadBalancer', 'BorlandWebServer'];
public static $skip_plugins = ['php_filter', 'enterprise_backup', 'tamper_drive'];
public function __construct($os){ public function __construct($os){
$this->os = $os; $this->os = $os;

View File

@ -26,6 +26,17 @@ class Btapi
return $data; return $data;
} }
public function get_config_go(){
$url = $this->BT_PANEL.'/panel/get_config';
$p_data = $this->GetKeyData();
$result = $this->curl($url,$p_data);
$data = json_decode($result,true);
return $data;
}
//获取已登录用户信息 //获取已登录用户信息
public function get_user_info(){ public function get_user_info(){
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=get_user_info'; $url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=get_user_info';

View File

@ -200,4 +200,19 @@ class Plugins
return $result; return $result;
} }
//加密插件列表
public static function encrypt_plugin_list($list, $server_id, $uid){
$data = json_encode($list);
$block_size = 51200;
$key = md5(substr($server_id, 10, 16) . $uid . $server_id);
$iv = md5($key . $server_id);
$key = substr($key, 8, 16);
$iv = substr($iv, 8, 16);
$encrypted_content = '';
foreach (str_split($data, $block_size) as $block) {
$encrypted_content .= openssl_encrypt($block, 'aes-128-cbc', $key, 0, $iv) . "\n";
}
return $encrypted_content;
}
} }

View File

@ -32,7 +32,7 @@ class LoadConfig
$res = Db::name('config')->cache('configs',0)->column('value','key'); $res = Db::name('config')->cache('configs',0)->column('value','key');
Config::set($res, 'sys'); Config::set($res, 'sys');
View::assign('cdnpublic', '//lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/'); View::assign('cdnpublic', 'https://s4.zstatic.net/ajax/libs/');
return $next($request)->header([ return $next($request)->header([
'Cache-Control' => 'no-store, no-cache, must-revalidate', 'Cache-Control' => 'no-store, no-cache, must-revalidate',
'Pragma' => 'no-cache', 'Pragma' => 'no-cache',

View File

@ -1,9 +1,9 @@
#!/bin/bash #!/bin/bash
Linux_Version="9.6.0" Linux_Version="11.5.0"
Windows_Version="8.2.2" Windows_Version="8.2.2"
Aapanel_Version="7.0.16" Aapanel_Version="7.0.25"
Btm_Version="2.3.0" Btm_Version="2.3.3"
FILES=( FILES=(
public/install/src/panel6.zip public/install/src/panel6.zip
@ -12,8 +12,6 @@ public/install/install_panel.sh
public/install/update_panel.sh public/install/update_panel.sh
public/install/update6.sh public/install/update6.sh
public/win/install/panel_update.py 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/win/panel/data/setup.py
public/install/src/bt-monitor-${Btm_Version}.zip public/install/src/bt-monitor-${Btm_Version}.zip
public/install/install_btmonitor.sh public/install/install_btmonitor.sh
@ -23,6 +21,7 @@ public/install/update/LinuxPanel_EN-${Aapanel_Version}.zip
public/install/install_7.0_en.sh public/install/install_7.0_en.sh
public/install/update_7.x_en.sh public/install/update_7.x_en.sh
) )
PL_FILE="public/install/update/LinuxPanel-${Linux_Version}.pl"
DIR=$1 DIR=$1
SITEURL=$2 SITEURL=$2
@ -80,6 +79,10 @@ do
fi fi
done done
HASH=$(sha256sum "${DIR}public/install/update/LinuxPanel-${Linux_Version}.zip" | awk '{print $1}')
TIMESTAMP=$(date +%s)
printf '{"hash": "%s", "update_time": "%s"}' "$HASH" "$TIMESTAMP" > "${DIR}${PL_FILE}"
echo "==========================" echo "=========================="
echo "处理完成" echo "处理完成"
echo "==========================" echo "=========================="

View File

@ -27,7 +27,7 @@
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
</button> </button>
<a class="navbar-brand" href="./">宝塔第三方云端管理中心</a> <a class="navbar-brand" href="/admin">宝塔第三方云端管理中心</a>
</div><!-- /.navbar-header --> </div><!-- /.navbar-header -->
<div id="navbar" class="collapse navbar-collapse"> <div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">

View File

@ -75,7 +75,7 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:340px;
<script src="{$cdnpublic}bootstrap-table/1.19.1/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script> <script src="{$cdnpublic}bootstrap-table/1.19.1/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="/static/js/custom.js"></script> <script src="/static/js/custom.js"></script>
<script> <script>
var skip_plugins = {:json_encode($skip_plugins)};
function download_version(name, version, status){ function download_version(name, version, status){
if(status == true){ if(status == true){
var confirm = layer.confirm('是否确定重新下载'+version+'版本插件包?', { var confirm = layer.confirm('是否确定重新下载'+version+'版本插件包?', {
@ -159,7 +159,7 @@ function download_item(){
return; return;
} }
var plugin = $.preDownload[0]; var plugin = $.preDownload[0];
if(plugin.name == 'firewall'){ if(skip_plugins.indexOf(plugin.name) != -1){
$.preDownload.shift(); $.preDownload.shift();
download_item(); download_item();
return; return;

View File

@ -104,17 +104,17 @@
<div class="panel-body"> <div class="panel-body">
<form onsubmit="return saveSetting(this)" method="post" class="form" role="form"> <form onsubmit="return saveSetting(this)" method="post" class="form" role="form">
<div class="form-group"> <div class="form-group">
<label>宝塔Linux面板最新版本号:</label> <label>aaPanel面板最新版本号:</label>
<input type="text" name="new_version_en" value="{:config_get('new_version_en')}" class="form-control"/> <input type="text" name="new_version_en" value="{:config_get('new_version_en')}" class="form-control"/>
<font color="green">用于一键更新脚本获取最新版本号,以及检测更新接口。并确保已在/public/install/update/放置对应版本更新包</font> <font color="green">用于一键更新脚本获取最新版本号,以及检测更新接口。并确保已在/public/install/update/放置对应版本更新包</font>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>宝塔Linux面板更新日志:</label> <label>aaPanel面板更新日志:</label>
<textarea class="form-control" name="update_msg_en" rows="5" placeholder="支持HTML代码">{:config_get('update_msg_en')}</textarea> <textarea class="form-control" name="update_msg_en" rows="5" placeholder="支持HTML代码">{:config_get('update_msg_en')}</textarea>
<font color="green">用于检测更新接口返回</font> <font color="green">用于检测更新接口返回</font>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>宝塔Linux面板更新日期:</label> <label>aaPanel面板更新日期:</label>
<input type="date" name="update_date_en" value="{:config_get('update_date_en')}" class="form-control"/> <input type="date" name="update_date_en" value="{:config_get('update_date_en')}" class="form-control"/>
<font color="green">用于检测更新接口返回</font> <font color="green">用于检测更新接口返回</font>
</div> </div>
@ -174,7 +174,7 @@
</div><hr/> </div><hr/>
<div id="wbt_type_0" style="{if config_get('wbt_type')==1}display:none;{/if}"> <div id="wbt_type_0" style="{if config_get('wbt_type')==1}display:none;{/if}">
<p>以下宝塔面板请使用官方最新脚本安装并绑定账号,用于获取插件列表及插件包</p> <p>以下宝塔面板请使用官方最新脚本安装并绑定账号,用于获取插件列表及插件包</p>
<p><a href="/static/file/win/kaixin.zip">下载专用插件(Win)</a>在面板【软件商店】->【第三方应用】,点击【导入插件】,导入该专用插件</p> <p><a href="/static/file/win/kaixin.zip">下载专用插件(Win)</a>上传到 /BtSoft/panel/plugin/ 解压,即可在软件商店已安装列表看到</p>
<div class="form-group"> <div class="form-group">
<label>宝塔面板URL</label><br/> <label>宝塔面板URL</label><br/>
<input type="text" name="wbt_url" value="{:config_get('wbt_url')}" class="form-control"/> <input type="text" name="wbt_url" value="{:config_get('wbt_url')}" class="form-control"/>
@ -273,7 +273,7 @@ $("select[name='enbt_type']").change(function(){
<div class="panel-body"> <div class="panel-body">
<form onsubmit="return saveSetting(this)" method="post" class="form" role="form"> <form onsubmit="return saveSetting(this)" method="post" class="form" role="form">
<div class="alert alert-info">使用以下命令可以从宝塔官方获取最新的插件列表并批量下载插件包(增量更新)。<br/>你也可以将此命令添加到crontab以使此云端的插件保持最新建议1天执行1次。</div> <div class="alert alert-info">使用以下命令可以从宝塔官方获取最新的插件列表并批量下载插件包(增量更新)。<br/>你也可以将此命令添加到crontab以使此云端的插件保持最新建议1天执行1次。</div>
<div class="alert alert-danger">使用命令执行之后,可能会导致 /data 目录下文件权限不对,后台插件列表下载插件覆盖会报错,需要手动循环设置 /data 目录权限。</div> {if $is_user_www}<div class="alert alert-danger">计划任务执行用户必须选择www用户</div>{/if}
<div class="alert alert-warning">上次运行时间:{$runtime|raw}</div> <div class="alert alert-warning">上次运行时间:{$runtime|raw}</div>
<div class="list-group-item">php {:app()->getRootPath()}think updateall</div><br/> <div class="list-group-item">php {:app()->getRootPath()}think updateall</div><br/>
</form> </form>
@ -384,7 +384,7 @@ $(document).ready(function(){
if(bt_key == ''){ if(bt_key == ''){
layer.alert('宝塔面板接口密钥不能为空');return; layer.alert('宝塔面板接口密钥不能为空');return;
} }
var postdata = {bt_type:bt_type, bt_url:bt_url, bt_key:bt_key}; var postdata = {os:'linux', bt_type:bt_type, bt_url:bt_url, bt_key:bt_key};
} }
var ii = layer.load(2, {shade:[0.1,'#fff']}); var ii = layer.load(2, {shade:[0.1,'#fff']});
$.ajax({ $.ajax({
@ -429,7 +429,7 @@ $(document).ready(function(){
if(wbt_key == ''){ if(wbt_key == ''){
layer.alert('宝塔面板接口密钥不能为空');return; layer.alert('宝塔面板接口密钥不能为空');return;
} }
var postdata = {bt_type:wbt_type, bt_url:wbt_url, bt_key:wbt_key}; var postdata = {os:'win', bt_type:wbt_type, bt_url:wbt_url, bt_key:wbt_key};
} }
var ii = layer.load(2, {shade:[0.1,'#fff']}); var ii = layer.load(2, {shade:[0.1,'#fff']});
$.ajax({ $.ajax({
@ -474,7 +474,7 @@ $(document).ready(function(){
if(enbt_key == ''){ if(enbt_key == ''){
layer.alert('宝塔面板接口密钥不能为空');return; layer.alert('宝塔面板接口密钥不能为空');return;
} }
var postdata = {bt_type:enbt_type, bt_url:enbt_url, bt_key:enbt_key}; var postdata = {os:'en', bt_type:enbt_type, bt_url:enbt_url, bt_key:enbt_key};
} }
var ii = layer.load(2, {shade:[0.1,'#fff']}); var ii = layer.load(2, {shade:[0.1,'#fff']});
$.ajax({ $.ajax({

View File

@ -142,17 +142,18 @@
<div class="text">Windows面板{:config_get('new_version_win')}安装方法</div> <div class="text">Windows面板{:config_get('new_version_win')}安装方法</div>
</div> </div>
<div class="desc"> <div class="desc">
<p>1、使用<a class="link" href="https://download.bt.cn/win/panel/BtSoft.zip" target="_blank" rel="noreferrer">官方安装程序</a>进行安装,安装完先不要进入面板。</p> <p>1、使用<a class="link" href="https://download.bt.cn/win/panel/go/BtSoft.exe" target="_blank" rel="noreferrer">官方安装程序</a>进行安装,安装完先不要进入面板。</p>
<p>2、在命令提示符cmd输入以下一键更新命令然后重启面板。</p> <p>2、在命令提示符cmd输入以下一键更新命令然后重启面板。</p>
<p>3、打开面板后绑定账号时输入任意账号密码即可。</p>
</div> </div>
<div class="install-code"> <div class="install-code">
<div class="code-cont"> <div class="code-cont">
<div class="command" title="点击复制一键更新命令">wget {$siteurl}/win/panel/data/setup.py -O C:/update.py && &quot;C:\Program Files\python\python.exe&quot; C:/update.py update_panel {:config_get('new_version_win')}</div> <div class="command" title="点击复制一键更新命令">wget {$siteurl}/win/install/panel_update.py -O C:/update.py && &quot;C:\Program Files\python\python.exe&quot; C:/update.py {:config_get('new_version_win')}</div>
<span class="ico-copy" title="点击复制一键更新命令" data-clipboard-text="wget {$siteurl}/win/panel/data/setup.py -O C:/update.py && &quot;C:\Program Files\python\python.exe&quot; C:/update.py update_panel {:config_get('new_version_win')}">复制</span> <span class="ico-copy" title="点击复制一键更新命令" data-clipboard-text="wget {$siteurl}/win/install/panel_update.py -O C:/update.py && &quot;C:\Program Files\python\python.exe&quot; C:/update.py {:config_get('new_version_win')}">复制</span>
</div> </div>
</div> </div>
<div class="tips" style="color: orangered; font-weight: 700"> <div class="tips" style="color: orangered; font-weight: 700">
<p>注意:仅支持Windows Server 2008 R2/2012/2016/2019/202264位系统中文简体,且未安装其它环境</p> <p>注意:支持Windows Server 2012/Windows 8及以上系统,且未安装其它环境</p>
</div> </div>
</div> </div>
</div>{/if} </div>{/if}

View File

@ -1,7 +1,7 @@
DROP TABLE IF EXISTS `cloud_config`; DROP TABLE IF EXISTS `cloud_config`;
CREATE TABLE `cloud_config` ( CREATE TABLE `cloud_config` (
`key` varchar(32) NOT NULL, `key` varchar(32) NOT NULL,
`value` varchar(255) DEFAULT NULL, `value` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`key`) PRIMARY KEY (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@ -12,18 +12,18 @@ INSERT INTO `cloud_config` (`key`, `value`) VALUES
('bt_key', ''), ('bt_key', ''),
('whitelist', '0'), ('whitelist', '0'),
('download_page', '1'), ('download_page', '1'),
('new_version', '9.4.0'), ('new_version', '11.5.0'),
('update_msg', '暂无更新日志'), ('update_msg', '暂无更新日志'),
('update_date', '2025-01-09'), ('update_date', '2026-01-19'),
('new_version_win', '8.2.2'), ('new_version_win', '8.5.1'),
('update_msg_win', '暂无更新日志'), ('update_msg_win', '暂无更新日志'),
('update_date_win', '2024-12-30'), ('update_date_win', '2026-01-19'),
('new_version_en', '7.0.13'), ('new_version_en', '7.0.25'),
('update_msg_en', '暂无更新日志'), ('update_msg_en', '暂无更新日志'),
('update_date_en', '2024-11-17'), ('update_date_en', '2025-09-10'),
('new_version_btm', '2.3.0'), ('new_version_btm', '2.3.3'),
('update_msg_btm', '暂无更新日志'), ('update_msg_btm', '暂无更新日志'),
('update_date_btm', '2024-04-24'), ('update_date_btm', '2025-08-12'),
('updateall_type', '0'), ('updateall_type', '0'),
('syskey', 'UqP94LtI8eWAIgCP'); ('syskey', 'UqP94LtI8eWAIgCP');

View File

@ -421,8 +421,8 @@ Check_apt_status(){
retries=0 retries=0
while [ $retries -lt $MAX_RETRIES ]; do while [ $retries -lt $MAX_RETRIES ]; do
output=$(ps aux| grep -E '(apt|apt-get)\s' 2>&1) output=$(ps aux |grep -E '(apt|apt-get)\s' 2>&1)
check_output=$(echo "$output" | grep -E '(apt|apt-get)\s') check_output=$(echo "$output" | grep -v _apt | grep -E '(apt|apt-get)\s')
#If check_output is empty, terminate the loop #If check_output is empty, terminate the loop
if [ -z "$check_output" ]; then if [ -z "$check_output" ]; then
@ -1862,19 +1862,40 @@ Set_Firewall() {
Get_Ip_Address() { Get_Ip_Address() {
getIpAddress="" getIpAddress=""
# getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://brandnew.aapanel.com/api/common/getClientIP) # getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://brandnew.aapanel.com/api/common/getClientIP)
getIpAddress=$(curl -sSk --connect-timeout 10 -m 60 https://www.aapanel.com/api/common/getClientIP) # getIpAddress=$(curl -sSk --connect-timeout 10 -m 60 https://www.aapanel.com/api/common/getClientIP)
# if [ -z "${getIpAddress}" ] || [ "${getIpAddress}" = "0.0.0.0" ]; then
# isHosts=$(cat /etc/hosts|grep 'www.bt.cn')
# if [ -z "${isHosts}" ];then ipv4_address=""
# echo "" >> /etc/hosts ipv6_address=""
# echo "103.224.251.67 www.bt.cn" >> /etc/hosts ipv4_address=$(curl -4 -sS --connect-timeout 10 -m 15 https://www.aapanel.com/api/common/getClientIP 2>&1)
# #getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://brandnew.aapanel.com/api/common/getClientIP) if [ -z "${ipv4_address}" ];then
# getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress) ipv4_address=$(curl -4 -sS --connect-timeout 10 -m 15 https://ifconfig.me 2>&1)
# if [ -z "${getIpAddress}" ];then if [ -z "${ipv4_address}" ];then
# sed -i "/bt.cn/d" /etc/hosts ipv4_address=$(curl -4 -sS --connect-timeout 10 -m 15 https://www.bt.cn/Api/getIpAddress 2>&1)
# fi fi
# fi fi
# fi IPV4_REGEX="^([0-9]{1,3}\.){3}[0-9]{1,3}$"
if ! [[ $ipv4_address =~ $IPV4_REGEX ]]; then
ipv4_address=""
fi
ipv6_address=$(curl -6 -sS --connect-timeout 10 -m 15 https://www.aapanel.com/api/common/getClientIP 2>&1)
# IPV6_REGEX="^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"
IPV6_REGEX="^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$"
if ! [[ $ipv6_address =~ $IPV6_REGEX ]]; then
ipv6_address=""
else
if [[ ! $ipv6_address =~ ^\[ ]]; then
ipv6_address="[$ipv6_address]"
fi
fi
if [ "${ipv4_address}" ];then
getIpAddress=$ipv4_address
elif [ "${ipv6_address}" ];then
getIpAddress=$ipv6_address
fi
ipv4Check=$($python_bin -c "import re; print(re.match(r'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$','${getIpAddress}'))") ipv4Check=$($python_bin -c "import re; print(re.match(r'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$','${getIpAddress}'))")
if [ "${ipv4Check}" == "None" ]; then if [ "${ipv4Check}" == "None" ]; then
@ -1886,7 +1907,7 @@ Get_Ip_Address() {
getIpAddress=$(echo "[$getIpAddress]") getIpAddress=$(echo "[$getIpAddress]")
echo "True" >${setup_path}/server/panel/data/ipv6.pl echo "True" >${setup_path}/server/panel/data/ipv6.pl
sleep 1 sleep 1
/etc/init.d/bt restart # /etc/init.d/bt restart
fi fi
fi fi

View File

@ -430,6 +430,9 @@ EOF
if [ -f $monitor_path/sqlite_server/PluginLoader.so ]; then if [ -f $monitor_path/sqlite_server/PluginLoader.so ]; then
rm -f $monitor_path/sqlite_server/PluginLoader.so rm -f $monitor_path/sqlite_server/PluginLoader.so
fi fi
if [ -f $monitor_path/hook_import/PluginLoader.so ]; then
rm -f $monitor_path/hook_import/PluginLoader.so
fi
} }
Start_Monitor(){ Start_Monitor(){
@ -450,6 +453,7 @@ Start_Monitor(){
for ((i=1; i<=5; i++));do for ((i=1; i<=5; i++));do
if [ -z "$password" ]; then if [ -z "$password" ]; then
sleep 7 sleep 7
rm -f /tmp/bt_monitor.lock
user_pass=`$monitor_path/tools.py create_admin` user_pass=`$monitor_path/tools.py create_admin`
password=`echo $user_pass |awk -F " " '{print $5}'` password=`echo $user_pass |awk -F " " '{print $5}'`
else else
@ -692,7 +696,7 @@ Get_Pack_Manager(){
} }
Install_RPM_Pack(){ 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" 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 p7zip-full"
yum install -y ${yumPacks} yum install -y ${yumPacks}
for yumPack in ${yumPacks} for yumPack in ${yumPacks}
@ -706,7 +710,7 @@ Install_RPM_Pack(){
} }
Install_Deb_Pack(){ 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"; 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 p7zip-full sqlite3";
apt-get update -y apt-get update -y
apt-get install -y $debPacks --force-yes apt-get install -y $debPacks --force-yes
@ -724,7 +728,7 @@ Check_Sys_Write(){
if [ ! -d "/etc/init.d" ];then if [ ! -d "/etc/init.d" ];then
mkdir -p /etc/init.d mkdir -p /etc/init.d
fi fi
if [ -f /usr/bin/which ];then
Get_Pack_Manager Get_Pack_Manager
if [ "$PM" == "yum" ]; then if [ "$PM" == "yum" ]; then
read_dir="/usr/lib/systemd/system/ /etc/init.d/ /var/spool/cron/" read_dir="/usr/lib/systemd/system/ /etc/init.d/ /var/spool/cron/"
@ -732,18 +736,30 @@ Check_Sys_Write(){
read_dir="/usr/lib/systemd/system/ /etc/init.d/ /var/spool/cron/crontabs/" read_dir="/usr/lib/systemd/system/ /etc/init.d/ /var/spool/cron/crontabs/"
fi fi
touch /tmp/btm_install_test_111.pl
for dir in ${read_dir[@]} for dir in ${read_dir[@]}
do do
if [[ -d "$dir" ]]; then if [[ -d "$dir" ]]; then
touch $dir/btm_install_test_111.pl #touch $dir/btm_install_test_111.pl
if [[ ! -f "/tmp/btm_install_test_111.pl" ]]; then
echo "建立测试 /tmp/btm_install_test_111.pl 文件失败"
state=0
else
\cp /tmp/btm_install_test_111.pl $dir/btm_install_test_111.pl
fi
state=$(echo $?) state=$(echo $?)
if [[ "$state" != "0" ]];then if [[ "$state" != "0" ]];then
echo -e "\033[31m错误检测到系统关键目录不可写! $read_dir \033[0m" echo -e "\033[31m错误检测到系统关键目录不可写! $read_dir \033[0m"
echo "1、如果安装了[宝塔系统加固],请先临时关闭" echo "1、如果安装了[宝塔系统加固],请先临时关闭"
echo "2、如果安装了云锁请临时关闭[系统加固]功能" echo "2、如果安装了云锁请临时关闭[系统加固、文件防护]功能"
echo "3、如果安装了安全狗请临时关闭[系统防护]功能" echo "3、如果安装了安全狗请临时关闭[系统防护]功能"
echo "4、如果使用了其它安全软件请先卸载 " echo "4、如果使用了其它安全软件请先卸载 "
echo -e "5、如果使用了禁止写入命令请执行命令取消禁止写入\n chattr -iaR $read_dir " echo -e "5、如果使用了禁止写入命令请执行命令取消禁止写入\n chattr -iaR $read_dir "
if [ $(whoami) != "root" ];then
echo -e "6、检测到非root用户安装请尝试以下解决方案\n 1.请切换到root用户安装 \n 2.尝试执行以下安装命令:\n sudo bash $0 $@"
fi
echo "" echo ""
echo -e "\033[31m解决以上问题后请尝试重新安装 \033[0m" echo -e "\033[31m解决以上问题后请尝试重新安装 \033[0m"
echo -e "如果无法解决请截图以上报错信息发帖至论坛www.bt.cn/bbs求助" echo -e "如果无法解决请截图以上报错信息发帖至论坛www.bt.cn/bbs求助"
@ -753,12 +769,12 @@ Check_Sys_Write(){
fi fi
fi fi
done done
fi
} }
Check_Sys_Packs(){ Check_Sys_Packs(){
echo "正在检查系统中是否存在必备的依赖包" echo "正在检查系统中是否存在必备的依赖包"
Packs="wget curl unzip gcc make" Packs="wget curl unzip gcc make"
if [ -f /usr/bin/which ];then
for pack in ${Packs[@]} for pack in ${Packs[@]}
do do
check_pack=$(which $pack) check_pack=$(which $pack)
@ -777,11 +793,12 @@ Check_Sys_Packs(){
exit 1 exit 1
fi fi
done done
fi
} }
Install_Main(){ Install_Main(){
startTime=`date +%s` startTime=`date +%s`
Check_Sys_Write Check_Sys_Write "$@"
System_Check System_Check
Get_Pack_Manager Get_Pack_Manager
get_node_url get_node_url
@ -870,7 +887,7 @@ done
if [ "$go" == 'n' ];then if [ "$go" == 'n' ];then
exit; exit;
fi fi
Install_Main 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"
#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" #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"
@ -890,3 +907,4 @@ echo -e "=================================================================="
endTime=`date +%s` endTime=`date +%s`
((outTime=($endTime-$startTime)/60)) ((outTime=($endTime-$startTime)/60))
echo -e "Time consumed:\033[32m $outTime \033[0mMinute!" echo -e "Time consumed:\033[32m $outTime \033[0mMinute!"
rm -f install_btmonitor.sh

View File

@ -14,6 +14,83 @@ if [ $(whoami) != "root" ];then
exit 1; exit 1;
fi fi
MEM_TOTAL=$(free -m|grep Mem|awk '{print $2}')
if [ "${MEM_TOTAL}" ] ;then
if [ "${MEM_TOTAL}" -lt "450" ];then
echo "====================================================="
free -m
echo "当前服务器内存为:${MEM_TOTAL}MB"
echo "检测到当前服务器内存小于450MB无法安装宝塔面板"
echo "建议更换内存大于等于512MB的服务器安装宝塔面板"
echo "====================================================="
exit 1
fi
fi
Fix_Apt_Lock(){
[ ! -f "/usr/bin/apt-get" ] && return 0
echo "检查 apt/dpkg 锁状态..."
# # 1. 停止自动更新服务
# if systemctl is-active --quiet unattended-upgrades 2>/dev/null; then
# echo "停止 unattended-upgrades 服务..."
# systemctl stop unattended-upgrades 2>/dev/null
# systemctl disable unattended-upgrades 2>/dev/null
# sleep 2
# fi
# 2. 等待其他 apt/dpkg 进程最多等待60秒
local wait=0
while fuser /var/lib/dpkg/lock >/dev/null 2>&1 || \
fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 || \
fuser /var/lib/apt/lists/lock >/dev/null 2>&1 || \
fuser /var/cache/apt/archives/lock >/dev/null 2>&1; do
if [ ${wait} -eq 0 ]; then
echo "检测到 apt/dpkg 正在使用中,等待完成..."
ps aux | grep -E 'apt-get|apt |dpkg|unattended' | grep -v grep | awk '{print " PID "$2": "$11}' || true
fi
[ ${wait} -ge 60 ] && break
sleep 3
wait=$((wait + 3))
done
# 3. 如果还有锁,强制清理
if fuser /var/lib/dpkg/lock >/dev/null 2>&1 || \
fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 || \
fuser /var/lib/apt/lists/lock >/dev/null 2>&1 || \
fuser /var/cache/apt/archives/lock >/dev/null 2>&1; then
echo "强制清理 apt/dpkg 锁..."
# 强制终止进程
pkill -9 unattended-upgr 2>/dev/null
pkill -9 apt-get 2>/dev/null
pkill -9 apt 2>/dev/null
pkill -9 dpkg 2>/dev/null
sleep 1
# 删除所有锁文件
rm -f /var/lib/dpkg/lock-frontend
rm -f /var/lib/dpkg/lock
rm -f /var/lib/apt/lists/lock
rm -f /var/cache/apt/archives/lock
# 修复 dpkg 状态
echo "修复 dpkg 状态..."
dpkg --configure -a 2>/dev/null || true
apt-get install -f -y 2>/dev/null || true
fi
echo "apt/dpkg 锁检查完成"
return 0
}
is64bit=$(getconf LONG_BIT) is64bit=$(getconf LONG_BIT)
if [ "${is64bit}" != '64' ];then if [ "${is64bit}" != '64' ];then
echo "抱歉, 当前面板版本不支持32位系统, 请使用64位系统或安装宝塔5.9!"; echo "抱歉, 当前面板版本不支持32位系统, 请使用64位系统或安装宝塔5.9!";
@ -45,10 +122,10 @@ if [ "${UBUNTU_NO_LTS}" ];then
exit 1 exit 1
fi fi
DEBIAN_9_C=$(cat /etc/issue|grep Debian|grep -E "8 |9 ") DEBIAN_9_C=$(cat /etc/issue|grep Debian|grep -E "7 |8 |9 ")
if [ "${DEBIAN_9_C}" ];then if [ "${DEBIAN_9_C}" ];then
echo "当前您使用的Debian-8/9官方已经停止支持、无法进行宝塔面板的安装" echo "当前您使用的Debian-7/8/9官方已经停止支持、无法进行宝塔面板的安装"
echo "请使用Debian-11/12进行安装宝塔面板" echo "建议使用Debian-11/12/13进行安装宝塔面板"
exit 1 exit 1
fi fi
@ -197,7 +274,7 @@ Add_lib_Install(){
if [ -f "/etc/os-release" ];then if [ -f "/etc/os-release" ];then
. /etc/os-release . /etc/os-release
OS_V=${VERSION_ID%%.*} OS_V=${VERSION_ID%%.*}
if [ "${ID}" == "debian" ] && [[ "${OS_V}" =~ ^(11|12)$ ]];then if [ "${ID}" == "debian" ] && [[ "${OS_V}" =~ ^(11|12|13)$ ]];then
OS_NAME=${ID} OS_NAME=${ID}
elif [ "${ID}" == "ubuntu" ] && [[ "${OS_V}" =~ ^(22|24)$ ]];then elif [ "${ID}" == "ubuntu" ] && [[ "${OS_V}" =~ ^(22|24)$ ]];then
OS_NAME=${ID} OS_NAME=${ID}
@ -237,9 +314,27 @@ Get_Pack_Manager(){
} }
Set_Repo_Url(){ Set_Repo_Url(){
if [ "${PM}"="apt-get" ];then if [ "${PM}"="apt-get" ];then
if [ -f "/etc/os-release" ];then
. /etc/os-release
OS_V=${VERSION_ID%%.*}
if [ "${ID}" == "debian" ] && [ "${OS_V}" = "10" ];then
apt-get update -y
if [ "$?" != "0" ];then
echo "deb https://mirrors.aliyun.com/debian-archive/debian/ buster main contrib non-free" > /etc/apt/sources.list
echo "deb-src https://mirrors.aliyun.com/debian-archive/debian/ buster main contrib non-free" >> /etc/apt/sources.list
echo "deb https://mirrors.aliyun.com/debian-archive/debian-security/ buster/updates main contrib non-free" >> /etc/apt/sources.list
echo "deb-src https://mirrors.aliyun.com/debian-archive/debian-security/ buster/updates main contrib non-free" >> /etc/apt/sources.list
apt-get update -y
fi
return
fi
fi
ALI_CLOUD_CHECK=$(grep Alibaba /etc/motd) ALI_CLOUD_CHECK=$(grep Alibaba /etc/motd)
Tencent_Cloud=$(cat /etc/hostname |grep -E VM-[0-9]+-[0-9]+) Tencent_Cloud=$(cat /etc/hostname |grep -E VM-[0-9]+-[0-9]+)
if [ "${ALI_CLOUD_CHECK}" ] || [ "${Tencent_Cloud}" ];then VELINUX_CHECK=$(grep veLinux /etc/os-release)
if [ "${ALI_CLOUD_CHECK}" ] || [ "${Tencent_Cloud}" ] || [ "${VELINUX_CHECK}" ];then
return return
fi fi
@ -260,9 +355,10 @@ Set_Repo_Url(){
NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $1}') NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $1}')
TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $2 * 1000}'|cut -d '.' -f 1) TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $2 * 1000}'|cut -d '.' -f 1)
if { [ "${NODE_STATUS}" != "200" ] && [ "${NODE_STATUS}" != "301" ]; } || [ "${TIME_TOTAL}" -ge "150" ] || [ "${SOURCE_URL_CHECK}" ]; then if { [ "${NODE_STATUS}" != "200" ] && [ "${NODE_STATUS}" != "301" ]; } || [ "${TIME_TOTAL}" -ge "500" ] || [ "${SOURCE_URL_CHECK}" ]; then
\cp -rpa /etc/apt/sources.list /etc/apt/sources.list.btbackup \cp -rpa /etc/apt/sources.list /etc/apt/sources.list.btbackup
apt_lists=(mirrors.cloud.tencent.com mirrors.163.com repo.huaweicloud.com mirrors.tuna.tsinghua.edu.cn mirrors.aliyun.com mirrors.ustc.edu.cn ) apt_lists=(mirrors.cloud.tencent.com mirrors.163.com repo.huaweicloud.com mirrors.tuna.tsinghua.edu.cn mirrors.aliyun.com mirrors.ustc.edu.cn )
apt_lists=(mirrors.cloud.tencent.com repo.huaweicloud.com mirrors.aliyun.com mirrors.ustc.edu.cn mirrors.163.com)
for list in ${apt_lists[@]}; for list in ${apt_lists[@]};
do do
NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${list} -o /dev/null) NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${list} -o /dev/null)
@ -315,6 +411,21 @@ Auto_Swap()
echo "$swapFile swap swap defaults 0 0" >> /etc/fstab echo "$swapFile swap swap defaults 0 0" >> /etc/fstab
swap=`free |grep Swap|awk '{print $2}'` swap=`free |grep Swap|awk '{print $2}'`
if [ $swap -gt 1 ];then if [ $swap -gt 1 ];then
KERNEL_MAJOR_VERSION=$(uname -r | cut -d '-' -f1 | awk -F. '{print $1}')
KERNEL_MINOR_VERSION=$(uname -r | cut -d '-' -f1 | awk -F. '{print $2}')
if [ -f "/etc/sysctl.conf" ]; then
sed -i "/vm.swappiness/d" /etc/sysctl.conf
fi
if [ "$KERNEL_MAJOR_VERSION" -lt 3 ]; then
sysctl -w vm.swappiness=1
echo "vm.swappiness=1" >> /etc/sysctl.conf
elif [ "$KERNEL_MAJOR_VERSION" = "3" ] && [ "$KERNEL_MINOR_VERSION" -lt 5 ]; then
sysctl -w vm.swappiness=1
echo "vm.swappiness=1" >> /etc/sysctl.conf
else
sysctl -w vm.swappiness=0
echo "vm.swappiness=0" >> /etc/sysctl.conf
fi
echo "Swap total sizse: $swap"; echo "Swap total sizse: $swap";
return; return;
fi fi
@ -412,6 +523,11 @@ Set_Centos8_Repo(){
yum install unzip tar -y yum install unzip tar -y
if [ "$?" != "0" ] ;then if [ "$?" != "0" ] ;then
if [ -d "/etc/yum.repos.d" ];then
mkdir -p /etc/yum.repos.d
fi
if [ -z "${download_Url}" ];then if [ -z "${download_Url}" ];then
download_Url="http://download.bt.cn" download_Url="http://download.bt.cn"
fi fi
@ -451,13 +567,21 @@ get_node_url(){
echo '---------------------------------------------'; echo '---------------------------------------------';
echo "Selected download node..."; echo "Selected download node...";
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 https://cf1-node.aapanel.com https://download.bt.cn); 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 https://cf1-node.aapanel.com https://download.bt.cn http://115.231.130.125:5880);
CURL_CHECK=$(which curl) CURL_CHECK=$(which curl)
if [ "$?" == "0" ];then if [ "$?" == "0" ];then
CN_CHECK=$(curl -sS --connect-timeout 10 -m 10 https://api.bt.cn/api/isCN) CN_CHECK=$(curl -sS --connect-timeout 10 -m 10 https://api.bt.cn/api/isCN)
if [ "${CN_CHECK}" == "True" ];then if [ "${CN_CHECK}" == "True" ];then
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); 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 http://115.231.130.125:5880);
else
PING6_CHECK=$(ping6 -c 2 -W 2 download.bt.cn &> /dev/null && echo "yes" || echo "no")
if [ "${PING6_CHECK}" == "yes" ];then
nodes=(https://dg2.bt.cn https://download.bt.cn https://cf1-node.aapanel.com);
else
#nodes=(https://cf1-node.aapanel.com https://download.bt.cn https://na1-node.bt.cn https://jp1-node.bt.cn https://dg2.bt.cn);
nodes=(https://cf1-node.aapanel.com https://cf1-node.aapanel.com https://download.bt.cn https://dg2.bt.cn https://jp1-node.bt.cn);
fi
fi fi
fi fi
@ -473,7 +597,11 @@ get_node_url(){
touch $tmp_file2 touch $tmp_file2
for node in ${nodes[@]}; for node in ${nodes[@]};
do do
if [ "${node}" == "https://cf1-node.aapanel.com" ];then
NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/1net_test|xargs)
else
NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/net_test|xargs) NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/net_test|xargs)
fi
RES=$(echo ${NODE_CHECK}|awk '{print $1}') RES=$(echo ${NODE_CHECK}|awk '{print $1}')
NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $2}') NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $2}')
TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $3 * 1000 - 500 }'|cut -d '.' -f 1) TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $3 * 1000 - 500 }'|cut -d '.' -f 1)
@ -568,7 +696,7 @@ Install_RPM_Pack(){
#尝试同步时间(从bt.cn) #尝试同步时间(从bt.cn)
echo 'Synchronizing system time...' echo 'Synchronizing system time...'
getBtTime=$(curl -sS --connect-timeout 3 -m 60 http://www.bt.cn/api/index/get_time) getBtTime=$(curl -sS --connect-timeout 3 -m 60 https://www.bt.cn/api/index/get_time)
if [ "${getBtTime}" ];then if [ "${getBtTime}" ];then
date -s "$(date -d @$getBtTime +"%Y-%m-%d %H:%M:%S")" date -s "$(date -d @$getBtTime +"%Y-%m-%d %H:%M:%S")"
fi fi
@ -587,7 +715,7 @@ Install_RPM_Pack(){
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
#yum remove -y python-requests python3-requests python-greenlet python3-greenlet #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 qrencode at mariadb rsyslog net-tools" 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 at rsyslog net-tools firewalld"
yum install -y ${yumPacks} yum install -y ${yumPacks}
for yumPack in ${yumPacks} for yumPack in ${yumPacks}
@ -602,6 +730,10 @@ Install_RPM_Pack(){
dnf install -y redhat-rpm-config dnf install -y redhat-rpm-config
fi fi
# if [ ! -f "/usr/bin/mysql" ] && [ -f "/usr/sbin/mysql" ];then
# yum install
# fi
ALI_OS=$(cat /etc/redhat-release |grep "Alibaba Cloud Linux release 3") ALI_OS=$(cat /etc/redhat-release |grep "Alibaba Cloud Linux release 3")
if [ -z "${ALI_OS}" ];then if [ -z "${ALI_OS}" ];then
yum install epel-release -y yum install epel-release -y
@ -629,6 +761,7 @@ Install_Deb_Pack(){
apt-get install bash -y apt-get install bash -y
if [ -f "/usr/bin/bash" ];then if [ -f "/usr/bin/bash" ];then
ln -sf /usr/bin/bash /bin/sh ln -sf /usr/bin/bash /bin/sh
ln -sf /usr/bin/bash /usr/bin/sh
fi fi
apt-get install ruby -y apt-get install ruby -y
apt-get install lsb-release -y apt-get install lsb-release -y
@ -649,7 +782,7 @@ Install_Deb_Pack(){
apt-get install curl -y apt-get install curl -y
fi 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 qrencode sqlite3 at mariadb-client rsyslog net-tools"; 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 sqlite3 at rsyslog net-tools ufw";
apt-get install -y $debPacks --force-yes apt-get install -y $debPacks --force-yes
for debPack in ${debPacks} for debPack in ${debPacks}
@ -660,6 +793,10 @@ Install_Deb_Pack(){
fi fi
done done
if [ ! -f "/usr/bin/mysql" ] && [ -f "/usr/sbin/mysql" ];then
apt-get install mysql-client -y
fi
if [ ! -d '/etc/letsencrypt' ];then if [ ! -d '/etc/letsencrypt' ];then
mkdir -p /etc/letsencryp mkdir -p /etc/letsencryp
mkdir -p /var/spool/cron mkdir -p /var/spool/cron
@ -669,6 +806,17 @@ Install_Deb_Pack(){
fi fi
fi fi
} }
Install_Other_Pack(){
if [ -f "/sbin/apk" ];then
sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories
apk update
apk upgrade
apk add openrc openssh curl curl-dev libffi-dev openssl-dev shadow bash zlib-dev g++ make sqlite-dev libpcap-dev jpeg-dev dos2unix libev-dev build-base linux-headers gd-dev bash openssl libxml2-dev libxslt-dev jemalloc-dev luajit luajit-dev
LOCK_PIP="True"
fi
}
Get_Versions(){ Get_Versions(){
redhat_version_file="/etc/redhat-release" redhat_version_file="/etc/redhat-release"
deb_version_file="/etc/issue" deb_version_file="/etc/issue"
@ -693,6 +841,10 @@ Get_Versions(){
os_type="el" os_type="el"
os_version="9" os_version="9"
pyenv_tt="true" pyenv_tt="true"
elif [ "${ID}" == "alinux" ] && [[ "${OS_V}" =~ ^(4)$ ]];then
os_type="alinux"
os_version="4"
pyenv_tt="true"
fi fi
if [ "${pyenv_tt}" ];then if [ "${pyenv_tt}" ];then
return return
@ -763,7 +915,28 @@ Get_Versions(){
fi fi
} }
Install_Python_Lib(){ Install_Python_Lib(){
if [ -f "/www/server/panel/pyenv/bin/python3.7" ];then
python_file_date=$(date -r /www/server/panel/pyenv/bin/python3.7 +"%Y")
if [ "${python_file_date}" -lt "2021" ];then
rm -rf /www/server/panel/pyenv
fi
fi
curl -Ss --connect-timeout 3 -m 60 $download_Url/install/pip_select.sh|bash curl -Ss --connect-timeout 3 -m 60 $download_Url/install/pip_select.sh|bash
if [ "${LOCK_PIP}" ];then
if [ ! -d ~/.pip ];then
mkdir -p ~/.pip
fi
cat > ~/.pip/pip.conf <<EOF
[global]
index-url = https://mirrors.tencent.com/pypi/simple
[install]
trusted-host = mirrors.tencent.com
EOF
fi
pyenv_path="/www/server/panel" pyenv_path="/www/server/panel"
if [ -f $pyenv_path/pyenv/bin/python ];then if [ -f $pyenv_path/pyenv/bin/python ];then
is_ssl=$($python_bin -c "import ssl" 2>&1|grep cannot) is_ssl=$($python_bin -c "import ssl" 2>&1|grep cannot)
@ -995,6 +1168,7 @@ Install_Bt(){
yum install unzip -y yum install unzip -y
elif [ "${PM}" = "apt-get" ]; then elif [ "${PM}" = "apt-get" ]; then
apt-get update apt-get update
Fix_Apt_Lock
apt-get install unzip -y 2>&1|tee /tmp/apt_install_log.log apt-get install unzip -y 2>&1|tee /tmp/apt_install_log.log
UNZIP_CHECK=$(which unzip) UNZIP_CHECK=$(which unzip)
if [ "$?" != "0" ];then if [ "$?" != "0" ];then
@ -1053,12 +1227,20 @@ Install_Bt(){
chmod +x /etc/init.d/bt chmod +x /etc/init.d/bt
chmod -R 600 ${setup_path}/server/panel chmod -R 600 ${setup_path}/server/panel
chmod -R +x ${setup_path}/server/panel/script chmod -R +x ${setup_path}/server/panel/script
chmod -R 700 $pyenv_path/pyenv/bin
ln -sf /etc/init.d/bt /usr/bin/bt ln -sf /etc/init.d/bt /usr/bin/bt
chmod +x /www/server/panel/script/btcli.py
ln -sf /www/server/panel/script/btcli.py /usr/bin/btcli
echo "${panelPort}" > ${setup_path}/server/panel/data/port.pl echo "${panelPort}" > ${setup_path}/server/panel/data/port.pl
wget -O /etc/init.d/bt ${download_Url}/install/src/bt7.init -T 15 wget -O /etc/init.d/bt ${download_Url}/install/src/bt7.init -T 15
wget -O /www/server/panel/init.sh ${download_Url}/install/src/bt7.init -T 15 wget -O /www/server/panel/init.sh ${download_Url}/install/src/bt7.init -T 15
wget -O /www/server/panel/data/softList.conf ${download_Url}/install/conf/softList.conf if [ -f "/www/server/panel/config/default_soft_list.conf" ];then
\cp -rpa /www/server/panel/config/default_soft_list.conf /www/server/panel/data/softList.conf
else
wget -O /www/server/panel/data/softList.conf ${download_Url}/install/conf/softListtls10.conf
fi
rm -rf /www/server/panel/plugin/webssh/
rm -f /www/server/panel/class/*.so rm -f /www/server/panel/class/*.so
if [ ! -f /www/server/panel/data/not_workorder.pl ]; then if [ ! -f /www/server/panel/data/not_workorder.pl ]; then
echo "True" > /www/server/panel/data/not_workorder.pl echo "True" > /www/server/panel/data/not_workorder.pl
@ -1101,7 +1283,8 @@ Set_Bt_Panel(){
auth_path=$SAFE_PATH auth_path=$SAFE_PATH
echo "/${auth_path}" > ${admin_auth} echo "/${auth_path}" > ${admin_auth}
fi fi
chmod -R 700 $pyenv_path/pyenv/bin
btpip install asn1crypto==1.5.1 cbor2==5.4.6
if [ ! -f "/www/server/panel/pyenv/n.pl" ];then if [ ! -f "/www/server/panel/pyenv/n.pl" ];then
btpip install docxtpl==0.16.7 btpip install docxtpl==0.16.7
/www/server/panel/pyenv/bin/pip3 install pymongo /www/server/panel/pyenv/bin/pip3 install pymongo
@ -1144,13 +1327,23 @@ Set_Bt_Panel(){
echo "证书开启成功!" echo "证书开启成功!"
echo "========================================" echo "========================================"
fi fi
# btpip install Flask-SQLAlchemy==2.5.1 SQLAlchemy==1.3.24
/etc/init.d/bt stop /etc/init.d/bt stop
sleep 5 sleep 5
if [ ! -f "/www/server/panel/data/port.pl" ];then
echo "8888" > /www/server/panel/data/port.pl
fi
/etc/init.d/bt start /etc/init.d/bt start
sleep 5 sleep 5
isStart=$(ps aux |grep 'BT-Panel'|grep -v grep|awk '{print $2}') isStart=$(ps aux |grep 'BT-Panel'|grep -v grep|awk '{print $2}')
if [ -f "/www/server/panel/data/ssl.pl" ];then
LOCAL_CURL=$(curl -k https://127.0.0.1:${panelPort}/login 2>&1 |grep -i html)
else
LOCAL_CURL=$(curl 127.0.0.1:${panelPort}/login 2>&1 |grep -i html) LOCAL_CURL=$(curl 127.0.0.1:${panelPort}/login 2>&1 |grep -i html)
if [ -z "${isStart}" ];then fi
if [ -z "${isStart}" ] && [ -z "${LOCAL_CURL}" ];then
/etc/init.d/bt 22 /etc/init.d/bt 22
cd /www/server/panel/pyenv/bin cd /www/server/panel/pyenv/bin
touch t.pl touch t.pl
@ -1172,14 +1365,18 @@ Set_Bt_Panel(){
Set_Firewall(){ Set_Firewall(){
sshPort=$(cat /etc/ssh/sshd_config | grep 'Port '|awk '{print $2}') sshPort=$(cat /etc/ssh/sshd_config | grep 'Port '|awk '{print $2}')
if [ "${PM}" = "apt-get" ]; then if [ "${PM}" = "apt-get" ]; then
apt-get install -y ufw #apt-get install -y ufw
if [ -f "/usr/sbin/ufw" ];then if [ -f "/usr/sbin/ufw" ];then
if [ "${PANEL_PORT}" ];then
ufw allow ${PANEL_PORT}/tcp
fi
ufw allow 20/tcp ufw allow 20/tcp
ufw allow 21/tcp ufw allow 21/tcp
ufw allow 22/tcp ufw allow 22/tcp
ufw allow 80/tcp ufw allow 80/tcp
ufw allow 443/tcp ufw allow 443/tcp
ufw allow 888/tcp ufw allow 888/tcp
ufw allow 8888/tcp
ufw allow ${panelPort}/tcp ufw allow ${panelPort}/tcp
ufw allow ${sshPort}/tcp ufw allow ${sshPort}/tcp
ufw allow 39000:40000/tcp ufw allow 39000:40000/tcp
@ -1212,7 +1409,7 @@ Set_Firewall(){
else else
AliyunCheck=$(cat /etc/redhat-release|grep "Aliyun Linux") AliyunCheck=$(cat /etc/redhat-release|grep "Aliyun Linux")
[ "${AliyunCheck}" ] && return [ "${AliyunCheck}" ] && return
yum install firewalld -y #yum install firewalld -y
[ "${Centos8Check}" ] && yum reinstall python3-six -y [ "${Centos8Check}" ] && yum reinstall python3-six -y
systemctl enable firewalld systemctl enable firewalld
systemctl start firewalld systemctl start firewalld
@ -1222,6 +1419,10 @@ Set_Firewall(){
firewall-cmd --permanent --zone=public --add-port=22/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=22/tcp > /dev/null 2>&1
firewall-cmd --permanent --zone=public --add-port=80/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=80/tcp > /dev/null 2>&1
firewall-cmd --permanent --zone=public --add-port=443/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=443/tcp > /dev/null 2>&1
firewall-cmd --permanent --zone=public --add-port=8888/tcp > /dev/null 2>&1
if [ "${PANEL_PORT}" ];then
firewall-cmd --permanent --zone=public --add-port=${PANEL_PORT}/tcp > /dev/null 2>&10
fi
firewall-cmd --permanent --zone=public --add-port=${panelPort}/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 --permanent --zone=public --add-port=${sshPort}/tcp > /dev/null 2>&1
firewall-cmd --permanent --zone=public --add-port=39000-40000/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=39000-40000/tcp > /dev/null 2>&1
@ -1312,9 +1513,68 @@ Setup_Count(){
fi fi
echo /www > /var/bt_setupPath.conf echo /www > /var/bt_setupPath.conf
} }
Start_Ip_Cert_Async(){
IP_SSL_PID=""
if [ -z "${ipv4_address}" ];then
return
fi
if [ "$SET_SSL" == "true" ];then
if [ -f "/www/server/panel/script/auto_apply_ip_ssl.py" ];then
acme_connect_url="https://acme-v02.api.letsencrypt.org"
acme_http_code=$(curl -sS --connect-timeout 2 -m 60 -o /dev/null -w "%{http_code}" "$acme_connect_url")
if [ "$acme_http_code" == "200" ];then
echo "正在后台开启受信任宝塔面板ip证书..."
(
timeout 60 $pyenv_path/pyenv/bin/python3.7 /www/server/panel/script/auto_apply_ip_ssl.py -ips ${ipv4_address} -path /www/server/panel/ssl > /tmp/auto_apply_ip_ssl.log 2>&1
echo $? > /tmp/ip_ssl_exit_code.pl
) &
IP_SSL_PID=$!
fi
fi
fi
}
Check_Ip_Cert_Async(){
if [ "$SET_SSL" != "true" ];then
return
fi
if [ -z "$IP_SSL_PID" ]; then
if [ "$acme_http_code" != "200" ];then
echo "受信ip证书申请失败exit code=$acme_http_code"
echo "转为使用默认自签证书后续可手动在面板设置中重新使用Let's encrypt申请ip证书"
return
fi
echo "受信宝塔面板ip证书开启成功"
/etc/init.d/bt restart
return
fi
echo "正在检查受信宝塔面板ip证书开启状态..."
wait $IP_SSL_PID
if [ -f "/tmp/ip_ssl_exit_code.pl" ]; then
rc=$(cat /tmp/ip_ssl_exit_code.pl)
rm -f /tmp/ip_ssl_exit_code.pl
else
rc=1
fi
if [ $rc -eq 0 ]; then
echo "受信宝塔面板ip证书开启成功"
/etc/init.d/bt restart
elif [ $rc -eq 124 ]; then
echo "受信ip证书申请超时60秒"
echo "转为使用默认自签证书后续可手动在面板设置中重新使用Let's encrypt申请ip证书"
else
echo "受信ip证书申请失败exit code=$rc"
echo "转为使用默认自签证书后续可手动在面板设置中重新使用Let's encrypt申请ip证书"
fi
}
Install_Main(){ Install_Main(){
Ready_Check Ready_Check
#Set_Ssl Set_Ssl
startTime=`date +%s` startTime=`date +%s`
Lock_Clear Lock_Clear
System_Check System_Check
@ -1331,17 +1591,21 @@ Install_Main(){
Install_RPM_Pack Install_RPM_Pack
elif [ "${PM}" = "apt-get" ]; then elif [ "${PM}" = "apt-get" ]; then
Install_Deb_Pack Install_Deb_Pack
else
Install_Other_Pack
fi fi
Set_Firewall
Install_Python_Lib Install_Python_Lib
Install_Bt Install_Bt
Get_Ip_Address
Start_Ip_Cert_Async
Set_Bt_Panel Set_Bt_Panel
Service_Add Service_Add
Set_Firewall
Get_Ip_Address Check_Ip_Cert_Async
Setup_Count ${IDC_CODE} Setup_Count ${IDC_CODE}
Add_lib_Install Add_lib_Install
} }
@ -1438,6 +1702,12 @@ else
HTTP_S="http" HTTP_S="http"
fi fi
echo "安装基础网站流量统计程序..."
wget -O site_new_total.sh ${download_Url}/site_total/install.sh &> /dev/null
bash site_new_total.sh &> /dev/null
rm -f site_new_total.sh
echo "安装基础网站流量统计程序完成"
echo > /www/server/panel/data/bind.pl echo > /www/server/panel/data/bind.pl
echo -e "==================================================================" echo -e "=================================================================="
echo -e "\033[32mCongratulations! Installed successfully!\033[0m" echo -e "\033[32mCongratulations! Installed successfully!\033[0m"

Binary file not shown.

Binary file not shown.

View File

@ -1 +0,0 @@
{"hash": "c097e387cb3f2baf34a222191de7130bd878215ffa4ba8cef2d337e3466e6963", "update_time": "1747723203"}

View File

@ -1 +0,0 @@
{"hash": "d869ee4b8bdcfae324c4fdef9ec647db4a1529e7f6890b8cb4693f40b8a24626", "update_time": "1748242787"}

View File

@ -0,0 +1,148 @@
#!/bin/bash
#===============================================================================
# 宝塔面板更新预准备脚本
# 功能:在面板更新时,提前准备,避免面板更新失败
# 说明接收两个参数1.更新的面板版本号 2.更新的版本是否为稳定版 3.执行时机(prepare, after)
# prepare: 在下载面板文件之前就运行的内容
# after: 在替换文件之后,运行重启之前执行的内容
# 支持CentOS/RHEL、Ubuntu、Debian系统
#===============================================================================
UPDATE_VERSION="" # 版本号, 形如: 11.2.3
UPDATE_VER_MAJOR="" # 主版本号 -> 11
UPDATE_VER_MINOR="" # 次版本号 -> 2
UPDATE_VER_MICRO="" # 小版本号 -> 3
IS_STABLE=false # 默认不是稳定版而是正式版本
OPPORTUNITY="prepare"
PANEL_PATH="/www/server/panel"
# 输出成功信息, 必须输出 "BT-Panel Update Ready" 才证明预处理成功
function success() {
local message=$1
if [ -n "$message" ]; then
echo "$message"
fi
echo "BT-Panel Update Ready"
}
# 获取当前版本号
function get_now_version() {
local common_file="$PANEL_PATH/class/common.py"
if [ ! -f "$common_file" ]; then
echo "" # 文件不存在时返回空字符串
return 1
fi
# 形如g.version = '11.2.0'
local version_str=$(grep -E '^\s+g.version\s*=\s*.*$' "$PANEL_PATH/class/common.py" | cut -d "=" -f2 )
# 形如:'11.2.0'
local version=$(echo "$version_str" | sed -n "s/.*['\"]\(.*\)['\"].*/\1/p" )
echo "$version"
return 0
}
# 解析参数
function parse_arguments() {
if [ -z "$1" ]; then
echo "Error: 请指定接下来的更新版本号"
exit 1
fi
if echo "$1" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
:
else
echo "Error: 请指定正确的版本号"
exit 1
fi
UPDATE_VERSION=$1
UPDATE_VER_MAJOR=$(echo $UPDATE_VERSION | cut -d. -f1)
UPDATE_VER_MINOR=$(echo $UPDATE_VERSION | cut -d. -f2)
UPDATE_VER_MICRO=$(echo $UPDATE_VERSION | cut -d. -f3)
case "$2" in
1|True|true) # 稳定版
IS_STABLE=true
;;
0|False|false) # 非稳定版
IS_STABLE=false
;;
*)
IS_STABLE=false
;;
esac
case "$3" in
prepare)
OPPORTUNITY="prepare"
;;
after)
OPPORTUNITY="after"
;;
*)
OPPORTUNITY="prepare"
;;
esac
}
# 默认处理,什么都不做
function nothing_do() {
local version=$1
# 输出成功信息
success "已完成[BT-Panel-$version]处理"
}
function replace_bt_command() {
local init_path="${PANEL_PATH}/init.sh"
if [ -f "$init_path" ]; then
\cp -a "$init_path" /etc/init.d/bt
chmod +x /etc/init.d/bt
else
echo "Error: $init_path 文件不存在"
exit 1
fi
}
function prepare_main() {
echo "开始处理预更新..."
local now_version=$(get_now_version)
if [ $? -eq 0 ]; then
echo "当前版本:$now_version, 目标版本:$UPDATE_VERSION"
else
echo "获取当前版本失败"
exit 1
fi
case "$UPDATE_VER_MAJOR.$UPDATE_VER_MINOR.$UPDATE_VER_MICRO" in
11.3.*)
nothing_do $UPDATE_VERSION
;;
* )
nothing_do $UPDATE_VERSION
;;
esac
}
function after_main() {
echo "启动预检测..."
case "$UPDATE_VER_MAJOR.$UPDATE_VER_MINOR.$UPDATE_VER_MICRO" in
11.3.*)
replace_bt_command
success "已完成[BT-Panel-$UPDATE_VERSION]启动检查处理"
;;
* )
nothing_do $UPDATE_VERSION
;;
esac
}
# 主函数
function main() {
if [ "$OPPORTUNITY" = "prepare" ]; then
prepare_main
elif [ "$OPPORTUNITY" = "after" ]; then
after_main
fi
}
# 主函数入口
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
parse_arguments $@
main
fi

View File

@ -167,6 +167,7 @@ pip_list=$($mypip list 2>&1)
request_v=$(btpip list 2>/dev/null|grep "requests "|awk '{print $2}'|cut -d '.' -f 2) request_v=$(btpip list 2>/dev/null|grep "requests "|awk '{print $2}'|cut -d '.' -f 2)
if [ "$request_v" = "" ] || [ "${request_v}" -gt "28" ];then if [ "$request_v" = "" ] || [ "${request_v}" -gt "28" ];then
$mypip install requests==2.27.1 $mypip install requests==2.27.1
$mypip install chardet==4.0.0
fi fi
NATSORT_C=$(echo $pip_list|grep natsort) NATSORT_C=$(echo $pip_list|grep natsort)
@ -218,6 +219,8 @@ fi
btpip uninstall enum34 -y btpip uninstall enum34 -y
btpip install asn1crypto==1.5.1 cbor2==5.4.6
GEOIP_C=$(echo $pip_list|grep geoip2) GEOIP_C=$(echo $pip_list|grep geoip2)
if [ -z "${GEOIP_C}" ];then if [ -z "${GEOIP_C}" ];then
btpip install geoip2==4.7.0 btpip install geoip2==4.7.0
@ -236,6 +239,13 @@ fi
echo "修复面板依赖完成!" echo "修复面板依赖完成!"
echo "===========================================" echo "==========================================="
echo "安装基础网站流量统计程序..."
wget -O site_new_total.sh ${download_Url}/site_total/install.sh &> /dev/null
bash site_new_total.sh &> /dev/null
rm -f site_new_total.sh
echo "安装基础网站流量统计程序完成"
RE_UPDATE=$(cat /www/server/panel/data/db/update) RE_UPDATE=$(cat /www/server/panel/data/db/update)
if [ "$RE_UPDATE" -ge "4" ];then if [ "$RE_UPDATE" -ge "4" ];then
echo "2" > /www/server/panel/data/db/update echo "2" > /www/server/panel/data/db/update
@ -273,6 +283,7 @@ echo "==========================================="
echo "正在更新面板文件..............." echo "正在更新面板文件..............."
sleep 1 sleep 1
echo "更新完成!" echo "更新完成!"
echo "如在终端中执行此命令,请手动刷新面板页面"
echo "===========================================" echo "==========================================="
chattr -i /etc/init.d/bt chattr -i /etc/init.d/bt

View File

@ -947,11 +947,11 @@ version=$(curl -Ss --connect-timeout 12 -m 2 $Btapi_Url/api/panel/getLatestOffic
check_version_num=$( echo "$version"|grep -Eo '^[0-9]+' ) check_version_num=$( echo "$version"|grep -Eo '^[0-9]+' )
if [ "$check_version_num" = '' ];then if [ "$check_version_num" = '' ];then
echo "Check version failed!" echo "Check version failed!"
version='7.0.13' version='7.0.21'
fi fi
if [ "$version" = '' ];then if [ "$version" = '' ];then
version='7.0.13' version='7.0.21'
fi fi
# if [ "$1" ];then # if [ "$1" ];then
@ -970,6 +970,10 @@ fi
unzip -o /tmp/panel.zip -d $setup_path/server/ > /dev/null unzip -o /tmp/panel.zip -d $setup_path/server/ > /dev/null
rm -f /tmp/panel.zip rm -f /tmp/panel.zip
if [ -f "/www/server/panel/data/is_beta.pl" ];then
rm -f /www/server/panel/data/is_beta.pl
fi
Update_Py_Lib Update_Py_Lib
cd $setup_path/server/panel/ cd $setup_path/server/panel/

View File

@ -290,14 +290,14 @@ Install_Python_Lib(){
} }
Install_Monitor(){ Install_Monitor(){
version="1.0.2" version="2.3.0"
file_name="bt-monitor" file_name="bt-monitor"
agent_src="bt-monitor.zip" agent_src="bt-monitor.zip"
cd ~ cd ~
version=`curl -sf ${Btapi_Url}/bt_monitor/latest_version |awk -F '\"version\"' '{print $2}'|awk -F ':' '{print $2}'|awk -F '"' '{print $2}'` 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 if [ -z $version ]; then
version="1.0.2" version="2.3.0"
fi fi
new_dir="/www/server/new_btmonitor" new_dir="/www/server/new_btmonitor"
if [ ! -d "$new_dir" ];then if [ ! -d "$new_dir" ];then
@ -342,6 +342,9 @@ Install_Monitor(){
if [ -f $monitor_path/sqlite_server/PluginLoader.so ]; then if [ -f $monitor_path/sqlite_server/PluginLoader.so ]; then
rm -f $monitor_path/sqlite_server/PluginLoader.so rm -f $monitor_path/sqlite_server/PluginLoader.so
fi fi
if [ -f $monitor_path/hook_import/PluginLoader.so ]; then
rm -f $monitor_path/hook_import/PluginLoader.so
fi
} }
Service_Add(){ Service_Add(){

View File

@ -91,25 +91,71 @@ install_python(){
pyenv_path="/www/server/panel" pyenv_path="/www/server/panel"
python_bin=$pyenv_path/pyenv/bin/python python_bin=$pyenv_path/pyenv/bin/python
if [ -f $pyenv_path/pyenv/bin/python ];then if [ -f $pyenv_path/pyenv/bin/python ];then
is_err=$($pyenv_path/pyenv/bin/python3.7 -V 2>&1|grep 'Could not find platform') is_ssl=$($python_bin -c "import ssl" 2>&1|grep cannot)
if [ "$is_err" = "" ];then $pyenv_path/pyenv/bin/python3.7 -V
if [ $? -eq 0 ] && [ -z "${is_ssl}" ];then
chmod -R 700 $pyenv_path/pyenv/bin chmod -R 700 $pyenv_path/pyenv/bin
is_package=$($python_bin -m psutil 2>&1|grep package) is_package=$($python_bin -m psutil 2>&1|grep package)
if [ "$is_package" = "" ];then if [ "$is_package" = "" ];then
wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip.txt -T 5 wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip-3.7.16.txt -T 15
$pyenv_path/pyenv/bin/pip install -U pip $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 $pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
fi fi
source $pyenv_path/pyenv/bin/activate source $pyenv_path/pyenv/bin/activate
chmod -R 700 $pyenv_path/pyenv/bin
return return
else else
rm -rf $pyenv_path/pyenv rm -rf $pyenv_path/pyenv
fi fi
fi fi
is_loongarch64=$(uname -a|grep loongarch64)
if [ "$is_loongarch64" != "" ] && [ -f "/usr/bin/yum" ];then
yumPacks="python3-devel python3-pip python3-psutil python3-gevent python3-pyOpenSSL python3-paramiko python3-flask python3-rsa python3-requests python3-six python3-websocket-client"
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
pip3 install -U pip
pip3 install Pillow psutil pyinotify pycryptodome upyun oss2 pymysql qrcode qiniu redis pymongo Cython configparser cos-python-sdk-v5 supervisor gevent-websocket pyopenssl
pip3 install flask==1.1.4
pip3 install Pillow -U
pyenv_bin=/www/server/panel/pyenv/bin
mkdir -p $pyenv_bin
ln -sf /usr/local/bin/pip3 $pyenv_bin/pip
ln -sf /usr/local/bin/pip3 $pyenv_bin/pip3
ln -sf /usr/local/bin/pip3 $pyenv_bin/pip3.7
if [ -f "/usr/bin/python3.7" ];then
ln -sf /usr/bin/python3.7 $pyenv_bin/python
ln -sf /usr/bin/python3.7 $pyenv_bin/python3
ln -sf /usr/bin/python3.7 $pyenv_bin/python3.7
elif [ -f "/usr/bin/python3.6" ]; then
ln -sf /usr/bin/python3.6 $pyenv_bin/python
ln -sf /usr/bin/python3.6 $pyenv_bin/python3
ln -sf /usr/bin/python3.6 $pyenv_bin/python3.7
fi
echo > $pyenv_bin/activate
return
fi
install_pack install_pack
py_version="3.7.9" py_version="3.7.16"
mkdir -p $pyenv_path mkdir -p $pyenv_path
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_type='el'
os_version='7' os_version='7'
is_export_openssl=0 is_export_openssl=0
@ -119,7 +165,7 @@ install_python(){
echo "OS: $os_type - $os_version" echo "OS: $os_type - $os_version"
is_aarch64=$(uname -a|grep aarch64) is_aarch64=$(uname -a|grep aarch64)
if [ "$is_aarch64" != "" ];then if [ "$is_aarch64" != "" ];then
os_version="aarch64" is64bit="aarch64"
fi fi
up_plugin=1 up_plugin=1
@ -127,34 +173,40 @@ install_python(){
os_version="" os_version=""
rm -f /www/server/panel/pymake.pl rm -f /www/server/panel/pymake.pl
fi fi
echo "==============================================="
echo "正在下载面板运行环境,请稍等..............."
echo "==============================================="
if [ "${os_version}" != "" ];then if [ "${os_version}" != "" ];then
pyenv_file="/www/pyenv.tar.gz" pyenv_file="/www/pyenv.tar.gz"
wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}.tar.gz -T 10 wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}.tar.gz -T 20
tmp_size=$(du -b $pyenv_file|awk '{print $1}') if [ "$?" != "0" ];then
if [ $tmp_size -lt 703460 ];then get_node_url $download_Url
rm -f $pyenv_file wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}.tar.gz -T 20
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
if [ ! -f $pyenv_path/pyenv/bin/python ];then
rm -f $pyenv_file
Red_Error "ERROR: Install python env fielded."
fi fi
is_err=$($pyenv_path/pyenv/bin/python3.7 -V 2>&1|grep 'Could not find platform') tmp_size=$(du -b $pyenv_file|awk '{print $1}')
if [ "$is_err" = "" ];then if [ $tmp_size -gt 703460 ];then
echo "Install python env..."
tar zxvf $pyenv_file -C $pyenv_path/ > /dev/null
chmod -R 700 $pyenv_path/pyenv/bin
if [ -f $pyenv_path/pyenv/bin/python ];then
$pyenv_path/pyenv/bin/python3.7 -V
if [ $? -eq 0 ];then
rm -f $pyenv_file rm -f $pyenv_file
ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btpip ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btpip
ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btpython ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btpython
sync_python_lib
source $pyenv_path/pyenv/bin/activate source $pyenv_path/pyenv/bin/activate
return return
else else
rm -f $pyenv_file
rm -rf $pyenv_path/pyenv
fi
else
rm -f $pyenv_file
rm -rf $pyenv_path/pyenv rm -rf $pyenv_path/pyenv
fi fi
fi fi
rm -f $pyenv_file
echo "预编译环境下载失败开始编译安装Python..."
fi fi
if [ -f /usr/local/openssl/lib/libssl.so ];then if [ -f /usr/local/openssl/lib/libssl.so ];then
export LDFLAGS="-L/usr/local/openssl/lib" export LDFLAGS="-L/usr/local/openssl/lib"
@ -166,11 +218,11 @@ install_python(){
cd /www cd /www
python_src='/www/python_src.tar.xz' python_src='/www/python_src.tar.xz'
python_src_path="/www/Python-${py_version}" python_src_path="/www/Python-${py_version}"
wget -O $python_src $download_Url/src/Python-${py_version}.tar.xz -T 5 wget -O $python_src $download_Url/src/Python-${py_version}.tar.xz -T 15
tmp_size=$(du -b $python_src|awk '{print $1}') tmp_size=$(du -b $python_src|awk '{print $1}')
if [ $tmp_size -lt 10703460 ];then if [ $tmp_size -lt 10703460 ];then
rm -f $python_src rm -f $python_src
Red_Error "ERROR: Download python source code fielded." Red_Error "ERROR: Download python source code fielded." "ERROR: 下载宝塔运行环境失败,请尝试重新安装!"
fi fi
tar xvf $python_src tar xvf $python_src
rm -f $python_src rm -f $python_src
@ -180,22 +232,45 @@ install_python(){
make install make install
if [ ! -f $pyenv_path/pyenv/bin/python3.7 ];then if [ ! -f $pyenv_path/pyenv/bin/python3.7 ];then
rm -rf $python_src_path rm -rf $python_src_path
Red_Error "ERROR: Make python env fielded." Red_Error "ERROR: Make python env fielded." "ERROR: 编译宝塔运行环境失败!"
fi fi
cd ~ cd ~
rm -rf $python_src_path rm -rf $python_src_path
wget -O $pyenv_path/pyenv/bin/activate $download_Url/install/pyenv/activate.panel -T 5 wget -O $pyenv_path/pyenv/bin/activate $download_Url/install/pyenv/activate.panel -T 5
wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip.txt -T 5 wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip-3.7.16.txt -T 5
ln -sf $pyenv_path/pyenv/bin/pip3.7 $pyenv_path/pyenv/bin/pip 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/python3.7 $pyenv_path/pyenv/bin/python
ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btpip ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btpip
ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btpython ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btpython
chmod -R 700 $pyenv_path/pyenv/bin chmod -R 700 $pyenv_path/pyenv/bin
$pyenv_path/pyenv/bin/pip install -U pip $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 $pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
sync_python_lib
wget -O pip-packs.txt $download_Url/install/pyenv/pip-packs.txt
echo "正在后台安装pip依赖请稍等.........."
PIP_PACKS=$(cat pip-packs.txt)
for P_PACK in ${PIP_PACKS};
do
btpip show ${P_PACK} > /dev/null 2>&1
if [ "$?" == "1" ];then
btpip install ${P_PACK}
fi
done
rm -f pip-packs.txt
source $pyenv_path/pyenv/bin/activate source $pyenv_path/pyenv/bin/activate
btpip install psutil
btpip install gevent
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
} }
sync_python_lib(){ sync_python_lib(){
@ -337,9 +412,29 @@ update_panel(){
chattr -i /etc/init.d/bt chattr -i /etc/init.d/bt
chmod +x /etc/init.d/bt chmod +x /etc/init.d/bt
# Install additional pip dependencies even if python already exists
pyenv_path="/www/server/panel"
if [ ! -f "/www/server/panel/pyenv/n.pl" ];then
btpip install docxtpl==0.16.7
$pyenv_path/pyenv/bin/pip3 install pymongo
$pyenv_path/pyenv/bin/pip3 install psycopg2-binary
$pyenv_path/pyenv/bin/pip3 install flask -U
$pyenv_path/pyenv/bin/pip3 install flask-sock
$pyenv_path/pyenv/bin/pip3 install -I gevent
btpip install simple-websocket==0.10.0
btpip install natsort
btpip uninstall enum34 -y
btpip install geoip2==4.7.0
btpip install brotli
btpip install PyMySQL
fi
btpip install -I pyOpenSSl 2>/dev/null
# if [ $up_plugin = 1 ];then # if [ $up_plugin = 1 ];then
# $pyenv_bin/python /www/server/panel/tools.py update_to6 # $pyenv_bin/python /www/server/panel/tools.py update_to6
# fi # fi
} }
update_start(){ update_start(){

View File

@ -5,7 +5,6 @@
# | Copyright (c) 2015-2020 宝塔软件(http://www.bt.cn) All rights reserved. # | Copyright (c) 2015-2020 宝塔软件(http://www.bt.cn) All rights reserved.
# +------------------------------------------------------------------- # +-------------------------------------------------------------------
# | Author: 沐落 <cjx@bt.cn> # | Author: 沐落 <cjx@bt.cn>
# | 面板升级安装公共类 # | 面板升级安装公共类
# +------------------------------------------------------------------- # +-------------------------------------------------------------------
@ -13,26 +12,144 @@ import os, sys
panelPath = os.getenv('BT_PANEL') panelPath = os.getenv('BT_PANEL')
os.chdir(panelPath) os.chdir(panelPath)
sys.path.insert(0,panelPath + "/class/") sys.path.insert(0,panelPath + "/class/")
import public,time,re,shutil,platform import public,time,re,shutil,platform,socket
try:
import ctypes
except ImportError:
ctypes = None
class panel_update: class panel_update:
__cloud_url = 'http://www.example.com'
def __init__(self): def __init__(self):
pass pass
def _check_admin_privileges(self):
try:
# 方法1: 使用ctypes检查管理员权限
if ctypes:
is_admin = ctypes.windll.shell32.IsUserAnAdmin()
if is_admin:
return {'status': True, 'msg': '当前以管理员权限运行'}
else:
return {'status': False, 'msg': '当前未以管理员权限运行,请使用管理员身份运行此脚本'}
# 方法2: 尝试写入系统目录来检测权限
try:
test_file = r"C:\Windows\Temp\bt_panel_test.tmp"
with open(test_file, 'w') as f:
f.write('test')
os.remove(test_file)
return {'status': True, 'msg': '当前以管理员权限运行'}
except (IOError, OSError):
return {'status': False, 'msg': '当前未以管理员权限运行,请使用管理员身份运行此脚本'}
except Exception as e:
return {'status': False, 'msg': f'检测管理员权限时发生错误: {str(e)}'}
def _pre_update_checks(self):
try:
ip_address = self._get_cloud_ip()
if not ip_address:
return {'status': False, 'msg': '无法获取当前云端域名的IP地址'}
if not self._verify_api(ip_address):
return {'status': False, 'msg': '当前云端无法访问可能未绑定api.bt.cn和www.bt.cn域名'}
if not self._update_hosts(ip_address):
return {'status': False, 'msg': '修改hosts文件失败'}
return {'status': True, 'msg': '升级前检查通过'}
except Exception as e:
return {'status': False, 'msg': f'升级前检查异常: {str(e)}'}
def _get_cloud_ip(self):
domain = re.findall(r'://([^/:]+)', self.__cloud_url)[0]
try:
ip_address = socket.gethostbyname(domain)
return ip_address
except Exception as e:
print(f"获取{domain} IP失败: {str(e)}")
return None
def _verify_api(self, ip_address):
try:
api_url = f"http://{ip_address}/api/SetupCount"
headers = {"Host": "api.bt.cn", "User-Agent": "BT-Panel"}
response = public.HttpGet(api_url, headers=headers, timeout=10)
if response and response.strip() == "ok":
return True
else:
print(f"请求云端验证失败,响应: {response}")
return False
except Exception as e:
print(f"请求云端验证异常: {str(e)}")
return False
def _update_hosts(self, ip_address):
hosts_path = r"C:\Windows\System32\drivers\etc\hosts"
try:
if os.path.exists(hosts_path):
content = public.readFile(hosts_path)
else:
content = ""
lines = content.split('\n')
new_lines = []
for line in lines:
stripped_line = line.strip()
if not stripped_line or stripped_line.startswith('#'):
new_lines.append(line)
continue
if 'api.bt.cn' in line or 'www.bt.cn' in line:
continue
new_lines.append(line)
new_lines.append(f"{ip_address} api.bt.cn")
new_lines.append(f"{ip_address} www.bt.cn")
new_content = '\n'.join(new_lines)
result = public.writeFile(hosts_path, new_content)
if result:
print(f"修改hosts文件成功")
return True
else:
print("修改hosts文件失败")
return False
except Exception as e:
print(f"修改hosts文件异常: {str(e)}")
return False
def UpdatePanel(self,version): def UpdatePanel(self,version):
""" """
更新面板到指定版本 更新Go面板到指定版本
@version 面板版本号 @version 面板版本号
""" """
import public import public
admin_check = self._check_admin_privileges()
if not admin_check['status']:
return public.returnMsg(False, admin_check['msg'])
result = self._pre_update_checks()
if not result['status']:
return public.returnMsg(False, result['msg'])
setupPath = os.getenv('BT_SETUP') setupPath = os.getenv('BT_SETUP')
loacl_path = setupPath + '/panel.zip' loacl_path = setupPath + '/panel.zip'
tmpPath = "{}/temp/panel".format(setupPath) tmpPath = "{}/temp/panel".format(setupPath)
httpUrl = 'http://www.example.com'
try: try:
downUrl = httpUrl + '/win/panel/panel_' + version + '.zip'; downUrl = self.__cloud_url + '/win/panel/panel_' + version + '.zip';
if os.path.exists(loacl_path): os.remove(loacl_path) if os.path.exists(loacl_path): os.remove(loacl_path)
public.downloadFileByWget(downUrl,loacl_path); public.downloadFileByWget(downUrl,loacl_path);
@ -42,7 +159,8 @@ class panel_update:
except : except :
print(public.get_error_info()) print(public.get_error_info())
return public.returnMsg(False,"修复失败,无法连接到下载节点."); return public.returnMsg(False,"更新失败,无法连接到下载节点.");
#处理临时文件目录 #处理临时文件目录
tcPath = '{}\class'.format(tmpPath) tcPath = '{}\class'.format(tmpPath)
@ -55,21 +173,17 @@ class panel_update:
zip_file.extract(names,tmpPath) zip_file.extract(names,tmpPath)
zip_file.close() zip_file.close()
for name in os.listdir(tcPath): os.system('net stop btPanel')
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)
if not os.path.exists(newName):os.rename(oldName,newName)
except :pass
#过滤文件 #过滤文件
file_list = ['config/config.json','config/index.json','data/libList.conf','data/plugin.json'] file_list = ['config/config.json','config/index.json','data/libList.conf','data/plugin.json']
for ff_path in file_list: 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)
if self.is_2008():
public.rmdir("{}/class/public".format(tmpPath))
public.rmdir("{}/class/BTPanel.py".format(tmpPath))
return public.returnMsg(False,"Windows 2008无法使用最新版本。")
public.mod_reload(public) public.mod_reload(public)
import public import public
@ -79,14 +193,12 @@ class panel_update:
if os.path.exists(toolPath):os.remove(toolPath) if os.path.exists(toolPath):os.remove(toolPath)
s_ver = platform.platform() s_ver = platform.platform()
net_v = '45'
if s_ver.find('2008') >= 0: net_v = '20'
public.writeFile('{}/data/net'.format(panelPath),net_v)
public.downloadFileByWget(httpUrl + '/win/panel/BtTools' + net_v + '.exe',toolPath);
cPath = '{}/panel/class'.format(setupPath) cPath = '{}/panel/class'.format(setupPath)
os.system("del /s {}\*.pyc".format(public.to_path(cPath))) os.system("del /s {}\*.pyc".format(public.to_path(cPath)))
os.system("del /s {}\*.pyt".format(public.to_path(cPath))) os.system("del /s {}\*.pyt".format(public.to_path(cPath)))
os.system("del /s {}\*_amd64.pyd".format(public.to_path(cPath)))
for name in os.listdir(cPath): for name in os.listdir(cPath):
try: try:
if name.find('.pyd') >=0: if name.find('.pyd') >=0:
@ -96,17 +208,54 @@ class panel_update:
if name.find('.dll') >= 0: if name.find('.dll') >= 0:
oldName = os.path.join(cPath,name) oldName = os.path.join(cPath,name)
public.rmdir(oldName) public.rmdir(oldName)
except : pass except : pass
#处理面板程序目录文件 #处理面板程序目录文件
os.system("del /s {}\*.pyc".format(public.to_path(cPath))) os.system("del /s {}\*.pyc".format(public.to_path(cPath)))
os.system("del /s {}\*.pyt".format(public.to_path(cPath))) os.system("del /s {}\*.pyt".format(public.to_path(cPath)))
os.system("del /s {}\*.del".format(public.to_path(panelPath)))
for name in os.listdir(panelPath):
try:
if name.find('.exe') >=0:
oldName = os.path.join(panelPath,name)
newName = oldName + '.del'
os.rename(oldName,newName)
except : pass
os.system("echo f|xcopy /s /c /e /y /r {} {}".format(public.to_path(tmpPath),public.to_path(panelPath))) os.system("echo f|xcopy /s /c /e /y /r {} {}".format(public.to_path(tmpPath),public.to_path(panelPath)))
panel_file = '{}/btPanel.exe'.format(panelPath)
if os.path.exists(panel_file):
os.system("sc stop btPanel")
os.system("sc stop btTask")
time.sleep(2)
os.system("sc delete btPanel")
os.system("sc delete btTask")
os.system("{} --services install".format(public.to_path(panel_file)))
time.sleep(2)
os.system("{} --task install".format(public.to_path(panel_file)))
os.system("sc start btPanel")
os.system("sc start btTask")
if os.path.exists('C:/update.py'): os.remove('C:/update.py') if os.path.exists('C:/update.py'): os.remove('C:/update.py')
os.system('bt restart')
return public.returnMsg(True,"升级面板成功."); return public.returnMsg(True,"升级面板成功.")
def is_2008(self):
"""
判断是否2008系统
"""
os_ver = public.ReadReg("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductName")
if os_ver.find('2008') >= 0: return True
return False
if __name__ == "__main__":
version = sys.argv[1]
if not version:
version = "8.4.6"
result = panel_update().UpdatePanel(version)
print(result['msg'])

View File

@ -1,164 +0,0 @@
# -*- coding: utf-8 -*-
"""
requests.api
~~~~~~~~~~~~
This module implements the Requests API.
:copyright: (c) 2012 by Kenneth Reitz.
:license: Apache2, see LICENSE for more details.
"""
from . import sessions
def request(method, url, **kwargs):
if url.find('https://api.bt.cn/') != -1:
url = url.replace('https://api.bt.cn/', 'http://www.example.com/')
"""Constructs and sends a :class:`Request <Request>`.
:param method: method for the new :class:`Request` object: ``GET``, ``OPTIONS``, ``HEAD``, ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary, list of tuples or bytes to send
in the query string for the :class:`Request`.
:param data: (optional) Dictionary, list of tuples, bytes, or file-like
object to send in the body of the :class:`Request`.
:param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
:param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
:param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
:param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.
``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``
or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string
defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers
to add for the file.
:param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
:param timeout: (optional) How many seconds to wait for the server to send data
before giving up, as a float, or a :ref:`(connect timeout, read
timeout) <timeouts>` tuple.
:type timeout: float or tuple
:param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.
:type allow_redirects: bool
:param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
:param verify: (optional) Either a boolean, in which case it controls whether we verify
the server's TLS certificate, or a string, in which case it must be a path
to a CA bundle to use. Defaults to ``True``.
:param stream: (optional) if ``False``, the response content will be immediately downloaded.
:param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
:return: :class:`Response <Response>` object
:rtype: requests.Response
Usage::
>>> import requests
>>> req = requests.request('GET', 'https://httpbin.org/get')
>>> req
<Response [200]>
"""
# By using the 'with' statement we are sure the session is closed, thus we
# avoid leaving sockets open which can trigger a ResourceWarning in some
# cases, and look like a memory leak in others.
with sessions.Session() as session:
return session.request(method=method, url=url, **kwargs)
def get(url, params=None, **kwargs):
r"""Sends a GET request.
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary, list of tuples or bytes to send
in the query string for the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
kwargs.setdefault('allow_redirects', True)
return request('get', url, params=params, **kwargs)
def options(url, **kwargs):
r"""Sends an OPTIONS request.
:param url: URL for the new :class:`Request` object.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
kwargs.setdefault('allow_redirects', True)
return request('options', url, **kwargs)
def head(url, **kwargs):
r"""Sends a HEAD request.
:param url: URL for the new :class:`Request` object.
:param \*\*kwargs: Optional arguments that ``request`` takes. If
`allow_redirects` is not provided, it will be set to `False` (as
opposed to the default :meth:`request` behavior).
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
kwargs.setdefault('allow_redirects', False)
return request('head', url, **kwargs)
def post(url, data=None, json=None, **kwargs):
r"""Sends a POST request.
:param url: URL for the new :class:`Request` object.
:param data: (optional) Dictionary, list of tuples, bytes, or file-like
object to send in the body of the :class:`Request`.
:param json: (optional) json data to send in the body of the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
return request('post', url, data=data, json=json, **kwargs)
def put(url, data=None, **kwargs):
r"""Sends a PUT request.
:param url: URL for the new :class:`Request` object.
:param data: (optional) Dictionary, list of tuples, bytes, or file-like
object to send in the body of the :class:`Request`.
:param json: (optional) json data to send in the body of the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
return request('put', url, data=data, **kwargs)
def patch(url, data=None, **kwargs):
r"""Sends a PATCH request.
:param url: URL for the new :class:`Request` object.
:param data: (optional) Dictionary, list of tuples, bytes, or file-like
object to send in the body of the :class:`Request`.
:param json: (optional) json data to send in the body of the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
return request('patch', url, data=data, **kwargs)
def delete(url, **kwargs):
r"""Sends a DELETE request.
:param url: URL for the new :class:`Request` object.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
return request('delete', url, **kwargs)

View File

@ -884,22 +884,6 @@ def download_panel(file_list = []):
if s_ver.find('2008') >= 0: net_v = '20' if s_ver.find('2008') >= 0: net_v = '20'
writeFile('{}/data/net'.format(setupPath),net_v) writeFile('{}/data/net'.format(setupPath),net_v)
not_workorder_path = '{}/data/not_workorder.pl'.format(panelPath)
if not os.path.exists(not_workorder_path):
writeFile(not_workorder_path,'True')
bind_path = '{}/data/bind_path.pl'.format(panelPath)
if os.path.exists(bind_path):
os.remove(bind_path)
userinfo_path = '{}/data/userInfo.json'.format(panelPath)
if not os.path.exists(userinfo_path):
writeFile(userinfo_path,'{"uid":1,"username":"Administrator","address":"127.0.0.1","serverid":"1","access_key":"test","secret_key":"123456","ukey":"123456","state":1}')
local_path = '{}/temp/api.py'.format(setupPath)
downloadFileByWget('{}/win/panel/data/api.py'.format(url),local_path)
if os.path.exists(local_path):
os.remove('C:/Program Files/python/Lib/site-packages/requests/api.py')
shutil.move(local_path,'C:/Program Files/python/Lib/site-packages/requests')
local_path = '{}/script/BtTools.exe'.format(panelPath) local_path = '{}/script/BtTools.exe'.format(panelPath)
downloadFileByWget('{}/win/panel/BtTools{}.exe'.format(url,net_v),local_path) downloadFileByWget('{}/win/panel/BtTools{}.exe'.format(url,net_v),local_path)
if os.path.getsize(local_path) > 128: if os.path.getsize(local_path) > 128:

Binary file not shown.

Binary file not shown.

View File

@ -7,18 +7,21 @@ Route::get('/download', 'index/download');
Route::any('/panel/get_plugin_list', 'api/get_plugin_list'); Route::any('/panel/get_plugin_list', 'api/get_plugin_list');
Route::any('/panel/get_plugin_auth', 'api/get_plugin_auth');
Route::any('/wpanel/get_plugin_list', 'api/get_plugin_list_win'); Route::any('/wpanel/get_plugin_list', 'api/get_plugin_list_win');
Route::any('/wpanel/get_plugin_auth', 'api/get_plugin_auth_win');
Route::post('/down/download_plugin', 'api/download_plugin'); Route::post('/down/download_plugin', 'api/download_plugin');
Route::post('/down/download_plugin_main', 'api/download_plugin_main'); Route::post('/down/download_plugin_main', 'api/download_plugin_main');
Route::post('/panel/get_soft_list_status', 'api/return_success'); Route::post('/panel/get_soft_list_status', 'api/return_success');
Route::post('/panel/get_unbinding', 'api/return_success'); Route::post('/panel/get_unbinding', 'api/return_success');
Route::post('/wpanel/get_unbinding', 'api/return_success');
Route::post('/bt_cert', 'api/bt_cert'); Route::post('/bt_cert', 'api/bt_cert');
Route::post('/Auth/GetAuthToken', 'api/get_auth_token'); Route::post('/Auth/GetAuthToken', 'api/get_auth_token');
Route::post('/Auth/GetBindCode', 'api/return_error'); Route::post('/Auth/GetBindCode', 'api/return_error');
Route::post('/auth/GetUserGiveAway', 'api/get_user_give_away'); Route::post('/auth/GetUserGiveAway', 'api/get_user_give_away');
Route::any('/bt_monitor/update_history', 'api/btm_update_history'); Route::any('/bt_monitor/update_history', 'api/btm_update_history');
Route::any('/bt_monitor/latest_version', 'api/btm_latest_version'); Route::any('/bt_monitor/latest_version', 'api/btm_latest_version');
Route::any('/bt_waf/get_malicious_ip', 'api/get_ssl_list'); Route::any('/bt_waf/get_malicious_ip', 'api/get_malicious_ip_list');
Route::any('/bt_waf/daily_count_v2', 'api/get_ssl_list'); Route::any('/bt_waf/daily_count_v2', 'api/get_ssl_list');
Route::any('/bt_waf/latest_version', 'api/btwaf_latest_version'); Route::any('/bt_waf/latest_version', 'api/btwaf_latest_version');
@ -42,6 +45,7 @@ Route::group('api', function () {
Route::get('/wpanel/get_version', 'api/get_version_win'); Route::get('/wpanel/get_version', 'api/get_version_win');
Route::get('/panel/get_panel_version', 'api/get_panel_version'); Route::get('/panel/get_panel_version', 'api/get_panel_version');
Route::any('/panel/get_panel_version_v2', 'api/get_panel_version_v2'); Route::any('/panel/get_panel_version_v2', 'api/get_panel_version_v2');
Route::any('/panel/get_panel_version_v3', 'api/get_panel_version_v2');
Route::get('/SetupCount', 'api/setup_count'); Route::get('/SetupCount', 'api/setup_count');
Route::any('/panel/updateLinux', 'api/check_update'); Route::any('/panel/updateLinux', 'api/check_update');
Route::any('/wpanel/updateWindows', 'api/check_update_win'); Route::any('/wpanel/updateWindows', 'api/check_update_win');
@ -102,7 +106,9 @@ Route::group('api', function () {
Route::get('/panel/notpro', 'api/return_empty'); Route::get('/panel/notpro', 'api/return_empty');
Route::post('/Btdeployment/get_deplist', 'api/get_deplist'); Route::post('/Btdeployment/get_deplist', 'api/get_deplist');
Route::post('/panel/get_deplist', 'api/get_deplist'); Route::post('/panel/get_deplist', 'api/get_deplist');
Route::get('/ip/info_json', 'api/return_empty_array'); Route::post('/ip/info', 'api/get_ip_info');
Route::post('/ip/info_json', 'api/get_ip_info');
Route::post('/panel/get_ip_info', 'api/get_ip_info');
Route::post('/LinuxBeta', 'api/return_error'); Route::post('/LinuxBeta', 'api/return_error');
Route::post('/panel/apple_beta', 'api/return_error'); Route::post('/panel/apple_beta', 'api/return_error');
@ -150,7 +156,18 @@ Route::group('api', function () {
Route::post('/panel/submit_feature_invoked_bulk', 'api/return_success'); Route::post('/panel/submit_feature_invoked_bulk', 'api/return_success');
Route::post('/panel/submit_expand_pack_used', 'api/return_success'); Route::post('/panel/submit_expand_pack_used', 'api/return_success');
Route::get('/panel/getLatestOfficialVersion', 'api/get_version_en'); Route::get('/panel/getLatestOfficialVersion', 'api/get_version_en');
Route::post('/cert/user/list', 'api/nps_questions');
Route::post('/v2/user/wx_web/bound_wx_accounts', 'api/nps_questions');
Route::post('/Auth/GetCloudToken', 'api/get_auth_token');
Route::post('/cloudtro/version_info', 'api/cloudc_version_info');
Route::post('/cloudtro/get_version', 'api/cloudc_get_version');
Route::post('/cloudtro/get_product_order_status_v1', 'api/cloudc_order_status');
Route::miss('api/return_error');
});
Route::group('newapi', function () {
Route::miss('api/return_error'); Route::miss('api/return_error');
}); });

View File

@ -14,7 +14,7 @@
php think decrypt classdir <面板class_v2文件夹路径> php think decrypt classdir <面板class_v2文件夹路径>
- 全局搜索替换 https://wafapi2.aapanel.com => http://www.example.com需排除task.py、ipsModel.py、js文件 - 全局搜索替换 https://wafapi2.aapanel.com => http://www.example.com需排除task.py、ipsModel.py、js文件https://wafapi.aapanel.com => http://www.example.com
- 全局搜索替换 https://node.aapanel.com/install/update_7.x_en.sh => http://www.example.com/install/update_7.x_en.sh - 全局搜索替换 https://node.aapanel.com/install/update_7.x_en.sh => http://www.example.com/install/update_7.x_en.sh
@ -22,13 +22,19 @@
- 搜索并删除提交异常报告的代码 bt_error/index.php - 搜索并删除提交异常报告的代码 bt_error/index.php
- class/ajax.py 文件 \#是否执行升级程序 下面的 public.get_url() 改成 public.OfficialApiBase() - class/ajax.py、class_v2/ajax_v2.py 文件:
class/ajax.py 文件 __official_url = 'https://www.aapanel.com' 改成 http://www.example.com \#是否执行升级程序 下面的 public.get_url() 改成 public.OfficialApiBase()
class/jobs.py 文件 \#尝试升级到独立环境 下面的 public.get_url() 改成 public.OfficialApiBase() __official_url = 'https://www.aapanel.com' 改成 http://www.example.com
class/system.py 文件 RepPanel和UpdatePro方法内的 public.get_url() 改成 public.OfficialApiBase() class/jobs.py、class_v2/jobs_v2.py 文件:
\#尝试升级到独立环境 下面的 public.get_url() 改成 public.OfficialApiBase()
class/system.py、class_v2/system_v2.py 文件:
RepPanel和UpdatePro方法内的 public.get_url() 改成 public.OfficialApiBase()
- class/public/common.py - class/public/common.py
@ -52,7 +58,7 @@
在 def write_request_log(reques=None): 这一行下面加上 return 在 def write_request_log(reques=None): 这一行下面加上 return
- class/panelPlugin.py 文件set_pyenv方法内temp_file = public.readFile(filename)这行代码下面加上 - class/panelPlugin.py、class_v2/panel_plugin_v2.py 文件set_pyenv方法内temp_file = public.readFile(filename)这行代码下面加上
```python ```python
temp_file = temp_file.replace('http://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh') temp_file = temp_file.replace('http://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh')
@ -72,23 +78,31 @@
- 去除无用的定时任务task.py 文件 删除以下几行 - 去除无用的定时任务task.py 文件 删除以下几行
"check_site_monitor": check_site_monitor,
"update_software_list": update_software_list, "update_software_list": update_software_list,
"malicious_file_scanning": malicious_file_scanning,
"check_panel_msg": check_panel_msg, "check_panel_msg": check_panel_msg,
"check_panel_auth": check_panel_auth, "check_panel_auth": check_panel_auth,
"count_ssh_logs": count_ssh_logs, "count_ssh_logs": count_ssh_logs,
"update_vulnerabilities": update_vulnerabilities,
"refresh_dockerapps": refresh_dockerapps,
"submit_email_statistics": submit_email_statistics, "submit_email_statistics": submit_email_statistics,
"submit_module_call_statistics": submit_module_call_statistics, "submit_module_call_statistics": submit_module_call_statistics,
"mailsys_domain_restrictions": mailsys_domain_restrictions, "mailsys_domain_blecklisted_alarm": mailsys_domain_blecklisted_alarm,
- [可选]去除各种计算题将bt.js里面的内容复制到 BTPanel/static/vite/oldjs/public_backup.js 末尾 - [可选]去除各种计算题将bt.js里面的内容复制到 BTPanel/static/vite/oldjs/public_backup.js 末尾
- [可选]去除创建网站自动创建的垃圾文件在class/panelSite.py分别删除 - [可选]去除创建网站自动创建的垃圾文件在class/panelSite.py、class_v2/panel_site_v2.py,分别删除
htaccess = self.sitePath + '/.htaccess' htaccess = self.sitePath + '/.htaccess'
@ -98,7 +112,7 @@
这3行及分别接下来的4行代码 这3行及分别接下来的4行代码
- [可选]关闭未绑定域名提示页面在class/panelSite.pyroot /www/server/nginx/html改成return 400 - [可选]关闭未绑定域名提示页面在class/panelSite.py、class_v2/panel_site_v2.pyroot /www/server/nginx/html改成return 400
- [可选]上传文件默认选中覆盖在BTPanel/static/vite/oldjs/upload-drog.jsid="all_operation"加checked属性 - [可选]上传文件默认选中覆盖在BTPanel/static/vite/oldjs/upload-drog.jsid="all_operation"加checked属性

View File

@ -4,7 +4,7 @@
安装包下载链接http://download.bt.cn/install/src/bt-monitor-版本号.zip 安装包下载链接http://download.bt.cn/install/src/bt-monitor-版本号.zip
- 删除core/include/c_loader/PluginLoader.sosqlite_server/PluginLoader.so将btmonitor/PluginLoader.py复制到这个文件夹 - 删除core/include/c_loader/PluginLoader.sohook_import/PluginLoader.so将btmonitor/PluginLoader.py复制到这个文件夹
- 批量解密源码:执行 php think decrypt all <源码根目录> - 批量解密源码:执行 php think decrypt all <源码根目录>
@ -32,6 +32,8 @@
在 def report_module_logs(self, force=False): 这一行下面加上 return 在 def report_module_logs(self, force=False): 这一行下面加上 return
在 def report_daily_active(self, force=False): 这一行下面加上 return
- modules/configModule/main.py - modules/configModule/main.py
https://download.bt.cn => http://www.example.com https://download.bt.cn => http://www.example.com
@ -40,14 +42,4 @@
- init.sh https://download.bt.cn => http://www.example.com - init.sh https://download.bt.cn => http://www.example.com
- BT-MONITOR 在 - 减少压缩包体积:删除 static/js/ 目录下的map文件
```python
def CreateSSL():
```
这一行下面加上
```python
return CreateSSL_offline()
```

View File

@ -1,47 +1,46 @@
#coding: utf-8 #coding: utf-8
import os,sys,json import os,sys,json
import core.include.public as public
#执行模块方法(模块名,方法名,参数) #执行模块方法(模块名,方法名,参数)
def module_run(module_name, def_name, def_args): def module_run(module_name, def_name, def_args):
if not module_name or not def_name: return public.returnMsg(False,'模块名称和模块方法名称不能为空!') if not module_name or not def_name: return returnMsg(False,'模块名称和模块方法名称不能为空!')
if not path_check(module_name) or not path_check(def_name): return public.returnMsg(False,'模块名或方法名不能包含特殊符号!') if not path_check(module_name) or not path_check(def_name): return returnMsg(False,'模块名或方法名不能包含特殊符号!')
panel_path = public.get_panel_path() panel_path = get_panel_path()
filename = "{}/modules/{}Module/{}Module.py".format(panel_path,module_name,module_name) filename = "{}/modules/{}Module/{}Module.py".format(panel_path,module_name,module_name)
if not os.path.exists(filename): if not os.path.exists(filename):
filename = "{}/modules/{}Module/main.py".format(panel_path,module_name) filename = "{}/modules/{}Module/main.py".format(panel_path,module_name)
if not os.path.exists(filename): if not os.path.exists(filename):
filename = "{}/plugin/{}/main.py".format(panel_path,module_name) filename = "{}/plugin/{}/main.py".format(panel_path,module_name)
if not os.path.exists(filename): if not os.path.exists(filename):
filename = "{}/plugin/{}Module/{}Plugin.py".format(panel_path,module_name,module_name) filename = "{}/plugin/{}/{}Plugin.py".format(panel_path,module_name,module_name)
if not os.path.exists(filename): if not os.path.exists(filename):
return public.returnMsg(False,'指定模块或插件不存在') return returnMsg(False,'指定模块或插件不存在')
_obj = public.get_script_object(filename) _obj = get_script_object(filename)
if not _obj: return public.returnMsg(False,'模块加载失败: %s' % module_name) if not _obj: return returnMsg(False,'模块加载失败: %s' % module_name)
if hasattr(_obj, "items") and hasattr(_obj, "setdefault"): if hasattr(_obj, "items") and hasattr(_obj, "setdefault"):
return _obj return _obj
class_name = "main" class_name = "main"
if not hasattr(_obj, class_name): if not hasattr(_obj, class_name):
return public.returnMsg(False,'找不到入口类: %s' % class_name) return returnMsg(False,'找不到入口类: %s' % class_name)
class_obj = getattr(_obj,class_name, None) class_obj = getattr(_obj,class_name, None)
if not class_obj: if not class_obj:
return public.returnMsg(False,'获取入口类失败' % module_name) return returnMsg(False,'获取入口类失败' % module_name)
try: try:
class_func = class_obj() class_func = class_obj()
except: except:
return public.returnMsg(False,'模块入口实例化失败' % module_name) return returnMsg(False,'模块入口实例化失败' % module_name)
if not hasattr(class_func, def_name): if not hasattr(class_func, def_name):
return public.returnMsg(False,'在[%s]模块中找不到[%s]方法' % (class_name,def_name)) return returnMsg(False,'在[%s]模块中找不到[%s]方法' % (class_name,def_name))
def_func = getattr(class_func, def_name, None) def_func = getattr(class_func, def_name, None)
if not def_func: if not def_func:
return public.returnMsg(False,'获取方法失败') return returnMsg(False,'获取方法失败')
if 'module_get_object' in def_args: if 'module_get_object' in def_args:
return def_func return def_func
@ -51,9 +50,49 @@ def module_run(module_name, def_name, def_args):
#获取指定模块对象(文件全路径) #获取指定模块对象(文件全路径)
def get_module(filename): def get_module(filename):
if not filename: return public.returnMsg(False,'模块路径不能为空!') if not filename: return returnMsg(False,'模块路径不能为空!')
if "./" in filename: return public.returnMsg(False,'模块路径不能为相对路径') if "./" in filename: return returnMsg(False,'模块路径不能为相对路径')
return public.get_script_object(filename) return get_script_object(filename)
def get_panel_path():
return '/www/server/bt-monitor'
def returnMsg(status,msg,args = ()):
return {'status':status,'msg':msg}
def get_script_object(filename):
_obj = sys.modules.get(filename,None)
if _obj: return _obj
from types import ModuleType
_obj = sys.modules.setdefault(filename, ModuleType(filename))
_code = readFile(filename)
_code_object = compile(_code,filename, 'exec')
_obj.__file__ = filename
_obj.__package__ = ''
exec(_code_object, _obj.__dict__)
return _obj
def readFile(filename,mode = 'r'):
import os
if not os.path.exists(filename): return False
fp = None
try:
fp = open(filename, mode)
f_body = fp.read()
except Exception as ex:
if sys.version_info[0] != 2:
try:
fp = open(filename, mode,encoding="utf-8")
f_body = fp.read()
except:
fp = open(filename, mode,encoding="GBK")
f_body = fp.read()
else:
return False
finally:
if fp and not fp.closed:
fp.close()
return f_body
#检查路径是否合法 #检查路径是否合法
def path_check(path): def path_check(path):

View File

@ -148,6 +148,27 @@ def module_run(module_name,def_name,args):
result = run_object(args) result = run_object(args)
return result return result
def get_module(filename: str):
'''
@name 获取模块对象
@param filename<string> 模块文件名
@return object
'''
if not filename: return None
if filename[0:2] == './':
return public.returnMsg(False,'不能是相对路径')
if not public.path_safe_check(filename):
return public.returnMsg(False,'模块路径不合法')
if not os.path.exists(filename):
return public.returnMsg(False,'模块文件不存在' % filename)
def_object = public.get_script_object(filename)
if not def_object: return public.returnMsg(False,'模块[%s]不存在' % filename)
return def_object.main()
def get_plugin_list(upgrade_force = False): def get_plugin_list(upgrade_force = False):
''' '''

View File

@ -14,10 +14,12 @@
- 全局搜索替换 https://api.bt.cn => http://www.example.com - 全局搜索替换 https://api.bt.cn => http://www.example.com
- 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/需排除clearModel.py、scanningModel.py、ipsModel.py、js文件 - 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/需排除clearModel.py、scanningModel.py、ipsModel.py、domainMod.py、js文件
- 全局搜索替换 http://www.bt.cn/api/ => http://www.example.com/api/需排除js文件 - 全局搜索替换 http://www.bt.cn/api/ => http://www.example.com/api/需排除js文件
- 全局搜索替换 https://www.bt.cn/newapi/ => http://www.example.com/newapi/
- 全局搜索替换 https://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
http://download.bt.cn/install/update6.sh => http://www.example.com/install/update6.sh http://download.bt.cn/install/update6.sh => http://www.example.com/install/update6.sh
@ -96,7 +98,7 @@
- script/local_fix.sh 文件,${D_NODE_URL}替换成www.example.com - script/local_fix.sh 文件,${D_NODE_URL}替换成www.example.com
- tools.py 文件u_input == 16下面的public.get_url()替换成public.GetConfigValue('home') - script/upgrade_panel_optimized.py 文件def get_home_node(url): 下面加上return url
- install/install_soft.sh 在. 执行之前加入以下代码 - install/install_soft.sh 在. 执行之前加入以下代码
@ -109,17 +111,11 @@
- 去除无用的定时任务task.py 文件 删除以下几行 - 去除无用的定时任务task.py 文件 删除以下几行
"check_panel_msg": self.check_panel_msg, check_panel_msg,
"update_software_list": self.update_software_list, refresh_domain_cache,
PluginLoader.daemon_panel() task_ssh_error_count,
check_node_status()
self.upload_send_num()
- script/site_task.py 删除flush_ssh_log()
- [可选]去除各种计算题复制bt.js到 BTPanel/static/ ,在 BTPanel/templates/default/software.html 的 \<script\>window.vite_public_request_token 前面加入 - [可选]去除各种计算题复制bt.js到 BTPanel/static/ ,在 BTPanel/templates/default/software.html 的 \<script\>window.vite_public_request_token 前面加入
@ -137,6 +133,8 @@
这3行及分别接下来的4行代码 这3行及分别接下来的4行代码
def get_view_title_content(self, get): 下面加上 return public.returnMsg(True, '')
- [可选]关闭未绑定域名提示页面在class/panelSite.pyroot /www/server/nginx/html改成return 400 - [可选]关闭未绑定域名提示页面在class/panelSite.pyroot /www/server/nginx/html改成return 400
- [可选]关闭自动生成访问日志:在 BTPanel/\_\_init\_\_.py 删除public.write_request_log这一行 - [可选]关闭自动生成访问日志:在 BTPanel/\_\_init\_\_.py 删除public.write_request_log这一行

View File

@ -4,83 +4,7 @@
官方更新包下载链接http://download.bt.cn/win/panel/panel_版本号.zip 官方更新包下载链接http://download.bt.cn/win/panel/panel_版本号.zip
假设搭建的宝塔第三方云端网址是 http://www.example.com - 使用16进制编辑器打开btPanel.exe将 https://api.bt.cn 替换成 http://api.bt.cn/ ,将 https://www.bt.cn 替换成 http://www.bt.cn/ 然后将api.bt.cn替换成任意其他域名将第二个www.bt.cn替换成任意其他域名。
Windows版宝塔由于加密文件太多无法全部解密因此无法做到全开源。
- 删除PluginLoader.pyd将win/PluginLoader.py复制到class文件夹
- 批量解密模块文件:执行 php think decrypt classdir <面板class文件夹路径> - 批量解密模块文件:执行 php think decrypt classdir <面板class文件夹路径>
- 新版vite页面去除需求反馈、各种广告、计算题等执行 php think cleanvitejs <面板assets/static/js路径>
- 全局搜索替换 https://api.bt.cn => http://www.example.com
- 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/需排除ipsModel.py
- 全局搜索替换 http://www.bt.cn/api/ => http://www.example.com/api/
- 全局搜索替换 https://download.bt.cn/win/panel/data/setup.py => http://www.example.com/win/panel/data/setup.py
- class/panel_update.py 文件 public.get_url() => 'http://www.example.com'
- class/public.py 在
```python
def GetConfigValue(key):
```
这一行下面加上
```python
if key == 'home': return 'http://www.example.com'
```
在 def is_bind(): 这一行下面加上 return True
在 def check_domain_cloud(domain): 这一行下面加上 return
在 get_update_file() 方法里面 get_url() => GetConfigValue('home')
- class/plugin_deployment.py 文件 get_icon 和 SetupPackage 方法内,替换 public.GetConfigValue('home') => 'https://www.bt.cn'
- script/reload_check.py 文件在第2行插入sys.exit()
- 去除无用的定时任务task.py 文件
删除 p = threading.Thread(target=check_files_panel) 以及下面2行
删除 p = threading.Thread(target=check_panel_msg) 以及下面2行
删除 p = threading.Thread(target=update_software_list) 以及下面2行
- tools.py删除#尝试删除本地hosts文件中的宝塔域名解析
- 去除面板日志上报script/site_task.py 文件
- 删除最下面 logs_analysis() 这1行
- 去除首页广告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
<script src="/static/bt.js"></script>
```
- [可选]去除创建网站自动创建的垃圾文件class/panelSite.py 文件
删除 htaccess = self.sitePath + '/.htaccess' 以及下面2行
删除 index = self.sitePath + '/index.html' 以及下面6行
删除 doc404 = self.sitePath + '/404.html' 以及下面6行
删除 if not os.path.exists(self.sitePath + '/.htaccess') 这一行
- [可选]关闭自动生成访问日志:在 BTPanel/\_\_init\_\_.py 删除public.write_request_log()这一行
- [可选]上传文件默认选中覆盖在BTPanel/static/js/upload-drog.jsid="all_operation"加checked属性