mirror of
https://github.com/midoks/mdserver-web.git
synced 2026-10-11 02:09:27 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29a3e606e1 | ||
|
|
d2b837f52c | ||
|
|
8984381ea2 | ||
|
|
ff015b19f7 | ||
|
|
1e71eedc19 | ||
|
|
fbce4a1abc | ||
|
|
d0cdab81d4 | ||
|
|
a69d5367d7 | ||
|
|
8d0ee48aa6 | ||
|
|
c24510e1e7 | ||
|
|
2e1c2e21b7 | ||
|
|
fee8c8c3db | ||
|
|
d94290019c | ||
|
|
27b914a905 | ||
|
|
ded25a7c87 | ||
|
|
5ba5da4cd1 | ||
|
|
cbb2a076e3 | ||
|
|
62df45da6a | ||
|
|
e441d8dc87 | ||
|
|
6d77e923b7 | ||
|
|
17a40802ae | ||
|
|
13bb828a95 | ||
|
|
eaa1a74dd6 | ||
|
|
80b615810c | ||
|
|
23fe4928e0 | ||
|
|
5a37c742e2 | ||
|
|
b94af58524 | ||
|
|
082c90b769 | ||
|
|
5012dc3a7b | ||
|
|
a6619b6e9d | ||
|
|
fe4ab5a013 | ||
|
|
ade3a5621f | ||
|
|
1cadeb3f59 | ||
|
|
05a2ba7f21 | ||
|
|
1759b6bcb1 | ||
|
|
a9e4c1b793 | ||
|
|
650b565fdf | ||
|
|
7ab974e565 | ||
|
|
95f8faf30f | ||
|
|
3d69e3723e | ||
|
|
4420bbc36c | ||
|
|
d5d96f6323 | ||
|
|
0bc9ed9d49 | ||
|
|
95e29d6266 | ||
|
|
207cef200f | ||
|
|
0082bcd159 | ||
|
|
f2a1674247 | ||
|
|
cd1a3de04a | ||
|
|
60a0bd7a65 | ||
|
|
a0696fc974 | ||
|
|
159660815b | ||
|
|
1c5a3f3c13 | ||
|
|
b36fc58839 | ||
|
|
0cd7a7dc9e | ||
|
|
52724dd5b2 | ||
|
|
dccea0e283 | ||
|
|
0f488b26d1 | ||
|
|
c3b60695c7 | ||
|
|
6fe205dbfb | ||
|
|
d8efd3f987 | ||
|
|
4c50e44e2c | ||
|
|
60717c3363 | ||
|
|
48388edcfc | ||
|
|
3c90a0fbe6 | ||
|
|
6eadb548a1 | ||
|
|
204be55c81 | ||
|
|
a44ac7606a | ||
|
|
67505f7aef | ||
|
|
369dc69364 | ||
|
|
1ffe197d69 | ||
|
|
6a584ccf7b | ||
|
|
43aba019c0 | ||
|
|
a0a61d3bbc | ||
|
|
9b008fcff9 | ||
|
|
e80162cfa9 | ||
|
|
30b02aea33 | ||
|
|
1cf49c24ef | ||
|
|
3bb0552ba6 | ||
|
|
b33be2ab84 | ||
|
|
8a4a63c85b | ||
|
|
640e8bbfa0 | ||
|
|
e6463e0286 | ||
|
|
c6cf6fef0b | ||
|
|
a428636e1c | ||
|
|
6fd145fa52 | ||
|
|
6164d462f3 | ||
|
|
d05e72e1d7 | ||
|
|
d9fbfcb184 | ||
|
|
660d95616d | ||
|
|
6160819920 | ||
|
|
c83b2d5bc5 | ||
|
|
44d529d32f | ||
|
|
b81e51c0e8 | ||
|
|
beccfe8519 | ||
|
|
9e774fb629 | ||
|
|
10c7ec8718 | ||
|
|
4bb9d0f002 | ||
|
|
39676d1a37 | ||
|
|
50f44afd82 | ||
|
|
9884bbd0e3 | ||
|
|
39853e39c7 | ||
|
|
894656741d | ||
|
|
93ef3659f2 | ||
|
|
3ccf084a53 | ||
|
|
aaa2b766a3 | ||
|
|
dc1f03b7ae | ||
|
|
36b50d3bf2 | ||
|
|
b9b7081eb4 | ||
|
|
808e65091d | ||
|
|
9b0c30e554 | ||
|
|
ffec30883f | ||
|
|
900dfc6ca7 | ||
|
|
203b4d11a8 | ||
|
|
2ba57ab05f | ||
|
|
4b11415f36 | ||
|
|
1ef0c4b8f0 | ||
|
|
4d85ed4e88 | ||
|
|
6c40e57ff6 | ||
|
|
19a4974537 | ||
|
|
6783e1507d | ||
|
|
8f3e722a0f | ||
|
|
3437d2e484 | ||
|
|
06e654ae2e | ||
|
|
c3103a23c6 | ||
|
|
55b38c2741 | ||
|
|
9f30c1968d | ||
|
|
d2455768ff | ||
|
|
6331155dc7 | ||
|
|
06d9695d33 | ||
|
|
80b35284ed | ||
|
|
27c38153b8 | ||
|
|
db62524dab | ||
|
|
190b858e46 | ||
|
|
be69e5838e | ||
|
|
b12122f53b | ||
|
|
33be35eb60 | ||
|
|
39b3f96ab5 | ||
|
|
7d214f74fd | ||
|
|
10aa140fe9 | ||
|
|
c68eaa9c61 | ||
|
|
3cc6021540 | ||
|
|
bfe7d49e07 | ||
|
|
c02aacb0d5 | ||
|
|
6d0f6fd171 | ||
|
|
712061e814 | ||
|
|
197dfa1b7e | ||
|
|
f21b66ddc0 | ||
|
|
5e086537d6 | ||
|
|
23532cb7e6 | ||
|
|
864ee5caec | ||
|
|
5db6d0332b | ||
|
|
eb9504658a | ||
|
|
a67389d611 |
+15
-15
@@ -115,7 +115,22 @@ tmp/*
|
||||
*.swp
|
||||
*.pem
|
||||
*.zip
|
||||
debug.out
|
||||
mdioks.session-journal
|
||||
*.session
|
||||
|
||||
logs/*
|
||||
|
||||
ssl/local
|
||||
ssl/nginx
|
||||
ssl/choose.pl
|
||||
|
||||
scripts/init.d/mw
|
||||
scripts/mdserver-web
|
||||
|
||||
data/api_login.txt
|
||||
data/sessions
|
||||
|
||||
data/*.db
|
||||
data/iplist.txt
|
||||
data/json/index.json
|
||||
@@ -131,12 +146,6 @@ data/debug.pl
|
||||
data/default_site.pl
|
||||
data/ssl.pl
|
||||
|
||||
scripts/init.d/mw
|
||||
scripts/mdserver-web
|
||||
|
||||
data/api_login.txt
|
||||
data/sessions
|
||||
|
||||
data/port.pl
|
||||
data/ipv6.pl
|
||||
data/restart.pl
|
||||
@@ -153,10 +162,6 @@ data/bind_domain.pl
|
||||
data/unauthorized_status.pl
|
||||
data/auth_secret.pl
|
||||
|
||||
ssl/local
|
||||
ssl/nginx
|
||||
ssl/choose.pl
|
||||
|
||||
plugins/vip_*
|
||||
plugins/own_*
|
||||
plugins/my_*
|
||||
@@ -175,8 +180,3 @@ plugins/frp
|
||||
plugins/file_search
|
||||
plugins/proxysql
|
||||
plugins/tidb
|
||||
debug.out
|
||||
|
||||
|
||||
mdioks.session-journal
|
||||
*.session
|
||||
|
||||
@@ -110,9 +110,9 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
|
||||
```
|
||||
|
||||
|
||||
### 版本更新 0.17.0
|
||||
### 版本更新 0.17.1
|
||||
|
||||
- 面板SSL调整。
|
||||
- 任务管理器-插件。
|
||||
|
||||
### JSDelivr安装地址
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ from flask import request
|
||||
|
||||
class config_api:
|
||||
|
||||
__version = '0.17.0'
|
||||
__version = '0.17.1'
|
||||
__api_addr = 'data/api.json'
|
||||
|
||||
# 统一默认配置文件
|
||||
|
||||
+10
-1
@@ -1466,7 +1466,7 @@ def makeConf():
|
||||
file = getRunDir() + '/data/json/config.json'
|
||||
if not os.path.exists(file):
|
||||
c = {}
|
||||
c['title'] = '老子面板'
|
||||
c['title'] = '后羿面板'
|
||||
c['home'] = 'http://github/midoks/mdserver-web'
|
||||
c['recycle_bin'] = True
|
||||
c['template'] = 'default'
|
||||
@@ -2110,6 +2110,15 @@ def notifyMessage(msg, stype='common', trigger_time=300, is_write_log=True):
|
||||
##################### notify end #########################################
|
||||
|
||||
|
||||
def getGlibcVersion():
|
||||
try:
|
||||
cmd_result = execShell("ldd --version")[0]
|
||||
if not cmd_result: return ''
|
||||
glibc_version = cmd_result.split("\n")[0].split()[-1]
|
||||
except:
|
||||
return ''
|
||||
return glibc_version
|
||||
|
||||
##################### ssh start #########################################
|
||||
def getSshDir():
|
||||
if isAppleSystem():
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
# coding: utf-8
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# MW-Linux面板
|
||||
# ---------------------------------------------------------------------------------
|
||||
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Author: midoks <midoks@163.com>
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# SSH终端操作
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import json
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import socket
|
||||
import threading
|
||||
import re
|
||||
|
||||
from io import BytesIO, StringIO
|
||||
|
||||
import mw
|
||||
import paramiko
|
||||
|
||||
from flask_socketio import SocketIO, emit, send
|
||||
|
||||
|
||||
class ssh_local(object):
|
||||
|
||||
__debug_file = 'logs/ssh_local.log'
|
||||
__log_type = 'SSH终端'
|
||||
|
||||
__ssh = None
|
||||
|
||||
# lock
|
||||
_instance_lock = threading.Lock()
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def instance(cls, *args, **kwargs):
|
||||
if not hasattr(ssh_local, "_instance"):
|
||||
with ssh_local._instance_lock:
|
||||
if not hasattr(ssh_local, "_instance"):
|
||||
ssh_local._instance = ssh_local(*args, **kwargs)
|
||||
return ssh_local._instance
|
||||
|
||||
def debug(self, msg):
|
||||
msg = "{} - {}:{} => {} \n".format(mw.formatDate(),
|
||||
self.__host, self.__port, msg)
|
||||
if not mw.isDebugMode():
|
||||
return
|
||||
mw.writeFile(self.__debug_file, msg, 'a+')
|
||||
|
||||
def returnMsg(self, status, msg):
|
||||
return {'status': status, 'msg': msg}
|
||||
|
||||
|
||||
def connectSsh(self):
|
||||
import paramiko
|
||||
ssh = paramiko.SSHClient()
|
||||
mw.createSshInfo()
|
||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
port = mw.getSSHPort()
|
||||
try:
|
||||
ssh.connect('127.0.0.1', port, timeout=5)
|
||||
except Exception as e:
|
||||
ssh.connect('localhost', port, timeout=5)
|
||||
except Exception as e:
|
||||
ssh.connect(mw.getHostAddr(), port, timeout=30)
|
||||
except Exception as e:
|
||||
return False
|
||||
|
||||
shell = ssh.invoke_shell(term='xterm', width=83, height=21)
|
||||
shell.setblocking(0)
|
||||
return shell
|
||||
|
||||
def send(self):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
try:
|
||||
if self.__ssh:
|
||||
self.__ssh.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
def wsSend(self, recv):
|
||||
try:
|
||||
t = recv.decode("utf-8")
|
||||
return emit('server_response', {'data': t})
|
||||
except Exception as e:
|
||||
return emit('server_response', {'data': recv})
|
||||
|
||||
def wsSendConnect(self):
|
||||
return emit('connect', {'data': 'ok'})
|
||||
|
||||
def wsSendReConnect(self):
|
||||
return emit('reconnect', {'data': 'ok'})
|
||||
|
||||
|
||||
def run(self, info):
|
||||
if not self.__ssh:
|
||||
self.__ssh = self.connectSsh()
|
||||
|
||||
if self.__ssh.exit_status_ready():
|
||||
self.__ssh = self.connectSsh()
|
||||
|
||||
self.__ssh.send(info)
|
||||
try:
|
||||
time.sleep(0.005)
|
||||
recv = self.__ssh.recv(8192)
|
||||
return self.wsSend(recv)
|
||||
except Exception as ex:
|
||||
return self.wsSend('')
|
||||
@@ -28,9 +28,9 @@ import paramiko
|
||||
from flask_socketio import SocketIO, emit, send
|
||||
|
||||
|
||||
class ssh_terminal:
|
||||
class ssh_terminal(object):
|
||||
|
||||
__debug_file = 'logs/terminal.log'
|
||||
__debug_file = 'logs/ssh_terminal.log'
|
||||
__log_type = 'SSH终端'
|
||||
|
||||
# websocketio 唯一标识
|
||||
@@ -55,10 +55,21 @@ class ssh_terminal:
|
||||
__ssh_list = {}
|
||||
__ssh_last_request_time = {}
|
||||
|
||||
# lock
|
||||
_instance_lock = threading.Lock()
|
||||
|
||||
def __init__(self):
|
||||
ht = threading.Thread(target=self.heartbeat)
|
||||
ht.start()
|
||||
|
||||
@classmethod
|
||||
def instance(cls, *args, **kwargs):
|
||||
if not hasattr(ssh_terminal, "_instance"):
|
||||
with ssh_terminal._instance_lock:
|
||||
if not hasattr(ssh_terminal, "_instance"):
|
||||
ssh_terminal._instance = ssh_terminal(*args, **kwargs)
|
||||
return ssh_terminal._instance
|
||||
|
||||
def debug(self, msg):
|
||||
msg = "{} - {}:{} => {} \n".format(mw.formatDate(),
|
||||
self.__host, self.__port, msg)
|
||||
|
||||
@@ -2936,7 +2936,7 @@ def doFullSync(version=''):
|
||||
def doFullSyncUser(version=''):
|
||||
which_pv = mw.execShell('which pv')
|
||||
is_exist_pv = False
|
||||
if not os.path.exists(which_pv[0]):
|
||||
if os.path.exists(which_pv[0]):
|
||||
is_exist_pv = True
|
||||
|
||||
|
||||
|
||||
@@ -3390,7 +3390,7 @@ def doFullSyncUserImportContentForChannel(file, channel_name):
|
||||
def doFullSyncUser(version=''):
|
||||
which_pv = mw.execShell('which pv')
|
||||
is_exist_pv = False
|
||||
if not os.path.exists(which_pv[0]):
|
||||
if os.path.exists(which_pv[0]):
|
||||
is_exist_pv = True
|
||||
|
||||
time_all_s = time.time()
|
||||
|
||||
@@ -2936,10 +2936,10 @@ function masterOrSlaveConf(version=''){
|
||||
getMasterDbList();
|
||||
}
|
||||
|
||||
if (rdata.slave_status){
|
||||
// if (rdata.slave_status){
|
||||
getAsyncMasterDbList();
|
||||
getAsyncDataList()
|
||||
}
|
||||
// }
|
||||
});
|
||||
}
|
||||
getMasterStatus();
|
||||
|
||||
@@ -26,7 +26,7 @@ function phpPost(method, version, args,callback){
|
||||
},'json');
|
||||
}
|
||||
|
||||
function phpPostCallbak(method, version, args,callback){
|
||||
function phpPostCallback(method, version, args,callback){
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
|
||||
var req_data = {};
|
||||
@@ -715,7 +715,7 @@ function getPHPInfo_old(version) {
|
||||
}
|
||||
|
||||
function getPHPInfo(version) {
|
||||
phpPostCallbak('get_php_info', version, {}, function(data){
|
||||
phpPostCallback('get_php_info', version, {}, function(data){
|
||||
if (!data.status){
|
||||
layer.msg(rdata.msg, { icon: 2 });
|
||||
return;
|
||||
@@ -739,7 +739,7 @@ function phpLibConfig(version){
|
||||
// var rdata = $.parseJSON(rdata.data);
|
||||
// });
|
||||
|
||||
phpPostCallbak('get_lib_conf', version, {}, function(rdata){
|
||||
phpPostCallback('get_lib_conf', version, {}, function(rdata){
|
||||
var rdata = rdata.data;
|
||||
|
||||
if (!rdata.status){
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 455 B |
Executable
+553
@@ -0,0 +1,553 @@
|
||||
<style>
|
||||
/*任务管理器*/
|
||||
.man-menu-sub {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #ccc;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.t-mana .table > tbody > tr.active td {
|
||||
background-color: #E4EEE0;
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
}
|
||||
|
||||
.search-bar .search_input {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #ccc;
|
||||
outline: none;
|
||||
padding-left: 8px;
|
||||
vertical-align: top;
|
||||
width: 230px;
|
||||
}
|
||||
|
||||
.search-bar .search_input:focus {
|
||||
border-color: #20a53a;
|
||||
|
||||
span.glyphicon-search {
|
||||
color: #20a53a;
|
||||
}
|
||||
}
|
||||
|
||||
.search-bar .glyphicon {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
display: inline-block;
|
||||
font-family: 'Glyphicons Halflings';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.search-bar .glyphicon-search {
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
padding: 0 10px;
|
||||
color: #888;
|
||||
position: absolute;
|
||||
right: 14px;
|
||||
top: 11px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.r56 {
|
||||
right: 56px !important;
|
||||
}
|
||||
|
||||
.man-menu-sub {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #ccc;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.man-menu-sub span {
|
||||
padding: 14px 15px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.man-menu-sub .on {
|
||||
border-bottom: 2px solid #20a53a;
|
||||
color: #20a53a;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.soft-ico-min {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.soft-ico-min img {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.table-cont {
|
||||
height: 500px;
|
||||
overflow: auto;
|
||||
border: #ddd 1px solid;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ts-line {
|
||||
position: absolute;
|
||||
top: 99px;
|
||||
height: 1px;
|
||||
background-color: #ddd;
|
||||
left: 16px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.t-mana .bt-ico-ask {
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
.mini-info {
|
||||
width: 100%;
|
||||
border-top: #DBDBEA 1px solid;
|
||||
background-color: #f6f6f6;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.mini-info-box {
|
||||
width: 500px;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
border: #DBDBEA 1px solid;
|
||||
border-radius: 6px;
|
||||
height: 66px;
|
||||
box-shadow: 0 0 40px #eee;
|
||||
}
|
||||
|
||||
.mini-info-con {
|
||||
float: left;
|
||||
height: 100%;
|
||||
width: 33%;
|
||||
line-height: 26px;
|
||||
padding: 6px 16px;
|
||||
}
|
||||
|
||||
.mini-info-con:nth-of-type(2) {
|
||||
border-left: #DBDBEA 1px solid;
|
||||
border-right: #DBDBEA 1px solid;
|
||||
width: 34%;
|
||||
}
|
||||
|
||||
.mini-info-con p {
|
||||
text-align: right;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mini-info-con .tname {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.mini-level {
|
||||
border: #ddd 1px solid;
|
||||
width: 166px;
|
||||
background-color: #fff;
|
||||
border-radius: 6px;
|
||||
margin: 0 auto;
|
||||
height: 66px;
|
||||
line-height: 66px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.jc-detail .tname {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.jc-detail h3.tname {
|
||||
margin-bottom: 10px;
|
||||
margin-top: 15px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.jc-detail .jc-info {
|
||||
margin: 10px 0;
|
||||
border-bottom: #ddd 1px solid;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
#TaskManagement .td-pid {
|
||||
/* display: flex; */
|
||||
/* border-top: #ddd 2px solid; */
|
||||
/* height: 38px; */
|
||||
/* height: 100%; */
|
||||
/* margin-top: 1px; */
|
||||
}
|
||||
|
||||
.td-pid img {
|
||||
/* margin-right: 8px; */
|
||||
/* display: inline-block; */
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
/* position: relative;
|
||||
left: -80px;
|
||||
filter: drop-shadow(#fff 80px 0); */
|
||||
/* position: relative;
|
||||
left: -80px;
|
||||
filter: drop-shadow(#238B37 0 80px); */
|
||||
}
|
||||
|
||||
.td-pid svg {
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.td-pid .colp {
|
||||
transform: rotate(-90deg);
|
||||
-moz-transform: rotate(-90deg);
|
||||
-webkit-transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.td-pid .arrow:hover {
|
||||
filter: drop-shadow(#999999 0 0)
|
||||
}
|
||||
|
||||
.td-pid .process-child {
|
||||
margin-left: 50px;
|
||||
/* display: none; */
|
||||
}
|
||||
|
||||
.td-pid span {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.td-pid a {
|
||||
display: block;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
#TaskManagement th: {
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
#TaskManagement tr: {
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
#TaskManagement tr:hover {
|
||||
/* background-color: rgb(245, 247, 250,0.6); */
|
||||
background-color: rgb(246, 246, 246, 0.65);
|
||||
}
|
||||
|
||||
#TaskManagement .process-select {
|
||||
/* background-color: rgb(242, 242, 242); */
|
||||
/* background-color: rgb(245, 247, 250,0.6); */
|
||||
background-color: rgb(246, 246, 246, 0.6);
|
||||
/* background-color: rgb(246, 246, 246,0.65); */
|
||||
}
|
||||
|
||||
#taskResourceTable .process-select {
|
||||
/* background-color: rgb(242, 242, 242); */
|
||||
background-color: #F1F9F3;
|
||||
}
|
||||
|
||||
#TaskManagement .process-select:hover {
|
||||
/* background-color: rgb(211, 210, 210); */
|
||||
/* background-color: rgb(245, 247, 250); */
|
||||
background-color: rgb(246, 246, 246);
|
||||
/* border: 1px solid #ddd;
|
||||
box-sizing: border-box; */
|
||||
}
|
||||
|
||||
#taskResourceTable .process-select:hover {
|
||||
/* background-color: rgb(211, 210, 210); */
|
||||
background-color: #BCE4C4;
|
||||
}
|
||||
|
||||
.resource-panel {
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 700px;
|
||||
/* height: 300px; */
|
||||
}
|
||||
|
||||
.resource-tab {
|
||||
float: left;
|
||||
width: 100px;
|
||||
height: 300px;
|
||||
background-color: thistle;
|
||||
}
|
||||
|
||||
.resource-right {
|
||||
margin-left: 100px;
|
||||
/* width: 100%; */
|
||||
/* background-color: gray; */
|
||||
/* height: 600px; */
|
||||
}
|
||||
|
||||
.resource-panel-show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.divtable-hide {
|
||||
display: none;
|
||||
/* visibility: hidden; */
|
||||
}
|
||||
|
||||
.resource-tab span {
|
||||
display: block;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.resource-tab span:hover {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.plug_menu {
|
||||
display: none;
|
||||
}
|
||||
.plug_menu .setting_ul::after{
|
||||
display: none;
|
||||
}
|
||||
.plug_menu .setting_ul.undisplay::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
color: #fff;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
font-size: 14px;
|
||||
top: -7px;
|
||||
right: 8px;
|
||||
display: inline-block;
|
||||
background: #fff;
|
||||
transform: rotate(-45deg);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.25);
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.set_list_fid_dropdown {
|
||||
display: inline-block;
|
||||
line-height: 30px;
|
||||
margin-left: 10px;
|
||||
position: relative;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.set_list_fid_dropdown .setting_btn {
|
||||
border: 1px solid #ccc;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.set_list_fid_dropdown .setting_btn:hover{
|
||||
background: #e9f6eb;
|
||||
border-color: #bce4c4;
|
||||
}
|
||||
.set_list_fid_dropdown .icon-setting {
|
||||
color: rgb(102, 102, 102);
|
||||
}
|
||||
.set_list_fid_dropdown .setting_btn:hover .icon-setting {
|
||||
color: #20a53a;
|
||||
}
|
||||
.set_list_fid_dropdown .setting_ul {
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
background: #fff;
|
||||
width: 150px;
|
||||
right: 0;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.25);
|
||||
padding: 10px 0;
|
||||
margin-top: 10px;
|
||||
display: none;
|
||||
}
|
||||
.set_list_fid_dropdown .setting_ul::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
color: #fff;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
font-size: 14px;
|
||||
top: -7px;
|
||||
right: 8px;
|
||||
display: inline-block;
|
||||
background: #fff;
|
||||
transform: rotate(-45deg);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.25);
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.setting_ul .setting_ul_li{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 27px;
|
||||
padding: 0 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.setting_ul .setting_ul_li:hover{
|
||||
background: #e9f6eb;
|
||||
}
|
||||
.setting_ul .setting_ul_li.disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.setting_ul .setting_ul_li i {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #fff;
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.setting_ul .setting_ul_li.active i {
|
||||
background-color: #20a53a;
|
||||
border-color: #20a53a;
|
||||
}
|
||||
.setting_ul .setting_ul_li.disabled i {
|
||||
background-color: #edf2fc;
|
||||
border-color: #dcdfe6;
|
||||
}
|
||||
.setting_ul .setting_ul_li.active.disabled i {
|
||||
background-color: #f2f6fc;
|
||||
border-color: #dcdfe6;
|
||||
}
|
||||
.setting_ul .setting_ul_li.active.disabled i::after{
|
||||
border: solid #dcdfe6;
|
||||
border-width: 0 2px 2px 0;
|
||||
}
|
||||
.setting_ul .setting_ul_li.active i::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
display: block;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-left: -2px;
|
||||
margin-top: -6px;
|
||||
width: 5px;
|
||||
height: 10px;
|
||||
border: solid #fff;
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="t-mana TaskManView">
|
||||
<div class="man-menu-sub mlr15">
|
||||
<div>
|
||||
<span class="p_list on">进程</span>
|
||||
<span class="p_run">启动项</span>
|
||||
<span class="p_service">服务</span>
|
||||
<span class="p_network">网络</span>
|
||||
<span class="p_user">用户</span>
|
||||
<span class="p_cron">计划任务</span>
|
||||
<span class="p_session">会话</span>
|
||||
</div>
|
||||
<div style="display: flex;flex-direction: row;align-items: center;justify-content: flex-end;">
|
||||
<div class="search-bar ">
|
||||
<input type="text" class="search_input " style="" placeholder="支持名称、字段模糊搜索">
|
||||
<span class="glyphicon glyphicon-search r56" aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class="table_config set_list_fid_dropdown" title="设置表头">
|
||||
<div class="setting_btn"><i class="glyphicon glyphicon-cog icon-setting"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ts-line"></div>
|
||||
|
||||
<div class="divtable taskdivtable pd15">
|
||||
<div id="table-cont" class="table-cont">
|
||||
<table id="TaskManagement" class="table table-hover" width="100%" style="border:none"></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-panel pd15">
|
||||
<div class="resource-tab">
|
||||
<span>CPU</span>
|
||||
<span>内存</span>
|
||||
<span>磁盘</span>
|
||||
</div>
|
||||
|
||||
<div class="resource-right">
|
||||
<div class="resource-top"></div>
|
||||
<div class="resource-middle divtable">
|
||||
<div id="table-cont" class="table-cont" style="height:100px;">
|
||||
<table id="taskResourceTable" class="table table-hover" width="100%" style="border:none">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-bottom"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mini-info" id="load_average"></div>
|
||||
<div class="plug_menu set_list_fid_dropdown">
|
||||
<ul class="setting_ul" style="display: none;">
|
||||
<li class="setting_ul_li ps active disabled" name="ps">
|
||||
<i></i><span class="ml10">应用名称</span>
|
||||
</li>
|
||||
<li class="setting_ul_li pid active disabled" name="pid">
|
||||
<i></i> <span class="ml10">PID</span>
|
||||
</li>
|
||||
<li class="setting_ul_li threads active" name="threads">
|
||||
<i></i> <span class="ml10">线程</span>
|
||||
</li>
|
||||
<li class="setting_ul_li user active" name="user">
|
||||
<i></i> <span class="ml10">用户</span>
|
||||
</li>
|
||||
<li class="setting_ul_li cpu_percent active disabled" name="cpu_percent">
|
||||
<i></i> <span class="ml10">CPU</span>
|
||||
</li>
|
||||
<li class="setting_ul_li memory_used active disabled" name="memory_used">
|
||||
<i></i> <span class="ml10">内存</span>
|
||||
</li>
|
||||
<li class="setting_ul_li io_read_bytes active" name="io_read_bytes">
|
||||
<i></i> <span class="ml10">io读</span>
|
||||
</li>
|
||||
<li class="setting_ul_li io_write_bytes active" name="io_write_bytes">
|
||||
<i></i> <span class="ml10">io写</span>
|
||||
</li>
|
||||
<li class="setting_ul_li up active" name="up">
|
||||
<i></i> <span class="ml10">上行</span>
|
||||
</li>
|
||||
<li class="setting_ul_li down active" name="down">
|
||||
<i></i> <span class="ml10">下行</span>
|
||||
</li>
|
||||
<li class="setting_ul_li connects active" name="connects">
|
||||
<i></i> <span class="ml10">连接</span>
|
||||
</li>
|
||||
<li class="setting_ul_li status active" name="status">
|
||||
<i></i> <span class="ml10">状态</span>
|
||||
</li>
|
||||
<li class="setting_ul_li active disabled" name="">
|
||||
<i></i> <span class="ml10">操作</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
$('.layui-layer-page').css({'width': '1000px'});
|
||||
$.getScript( "/plugins/file?name=task_manager&f=js/task_manager.js", function(){
|
||||
console.log("load js ok!");
|
||||
});
|
||||
</script>
|
||||
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
# coding:utf-8
|
||||
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
import time
|
||||
import re
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import mw
|
||||
|
||||
app_debug = False
|
||||
if mw.isAppleSystem():
|
||||
app_debug = True
|
||||
|
||||
|
||||
def getPluginName():
|
||||
return 'task_manager'
|
||||
|
||||
|
||||
def getPluginDir():
|
||||
return mw.getPluginDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getServerDir():
|
||||
return mw.getServerDir() + '/' + getPluginName()
|
||||
|
||||
def getArgs():
|
||||
args = sys.argv[3:]
|
||||
tmp = {}
|
||||
args_len = len(args)
|
||||
|
||||
if args_len == 1:
|
||||
t = args[0].strip('{').strip('}')
|
||||
if t.strip() == '':
|
||||
tmp = []
|
||||
else:
|
||||
t = t.split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
tmp[t[0]] = t[1]
|
||||
elif args_len > 1:
|
||||
for i in range(len(args)):
|
||||
t = args[i].split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
return tmp
|
||||
|
||||
def checkArgs(data, ck=[]):
|
||||
for i in range(len(ck)):
|
||||
if not ck[i] in data:
|
||||
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
|
||||
return (True, mw.returnJson(True, 'ok'))
|
||||
|
||||
def status():
|
||||
return 'start'
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
print(status())
|
||||
else:
|
||||
print('error')
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"sort": 7,
|
||||
"ps": "轻松管理进程、流量监控、启动项、用户、服务、计划任务、会话",
|
||||
"name": "task_manager",
|
||||
"title": "任务管理器",
|
||||
"shell": "install.sh",
|
||||
"versions":"1.0",
|
||||
"tip": "soft",
|
||||
"checks": "server/task_manager",
|
||||
"path": "server/task_manager",
|
||||
"display": 1,
|
||||
"author": "task_manager",
|
||||
"date": "2024-06-01",
|
||||
"home": "task_manager",
|
||||
"type": 0,
|
||||
"pid": "4"
|
||||
}
|
||||
Executable
+55
@@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl
|
||||
VERSION=$2
|
||||
|
||||
# python3 plugins/task_manager/task_manager_index.py
|
||||
# /www/server/mdserver-web/bin/python3 /www/server/mdserver-web/plugins/task_manager/process_network_total.py
|
||||
# ps -ef|grep process_network_total| grep -v grep | awk '{print $2}' | xargs kill -9
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
Install_App()
|
||||
{
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
mkdir -p $serverPath/task_manager
|
||||
|
||||
if [ -f /usr/bin/apt ]; then
|
||||
apt install libpcap-dev -y
|
||||
fi
|
||||
|
||||
if [ -f /usr/bin/yum ]; then
|
||||
yum install libpcap-devel -y
|
||||
fi
|
||||
|
||||
if [ -f /usr/bin/dnf ]; then
|
||||
dnf install libpcap-devel -y
|
||||
fi
|
||||
|
||||
pip3 install pypcap
|
||||
|
||||
echo "$VERSION" > $serverPath/task_manager/version.pl
|
||||
echo "安装任务管理器成功"
|
||||
}
|
||||
|
||||
Uninstall_App()
|
||||
{
|
||||
rm -rf $serverPath/task_manager
|
||||
echo "卸载任务管理器成功"
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
fi
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,230 @@
|
||||
#coding: utf-8
|
||||
|
||||
import sys
|
||||
import time
|
||||
import os
|
||||
import struct
|
||||
|
||||
os.chdir('/www/server/mdserver-web')
|
||||
if 'class/' in sys.path: sys.path.insert(0,"class/")
|
||||
import copy
|
||||
try:
|
||||
import pcap
|
||||
except ImportError:
|
||||
if os.path.exists('/usr/bin/apt'):
|
||||
os.system("apt install libpcap-dev -y")
|
||||
elif os.path.exists('/usr/bin/dnf'):
|
||||
red_file = '/etc/redhat-release'
|
||||
if os.path.exists(red_file):
|
||||
f = open(red_file,'r')
|
||||
red_body = f.read()
|
||||
f.close()
|
||||
if red_body.find('CentOS Linux release 8.') != -1:
|
||||
rpm_file = '/root/libpcap-1.9.1.rpm'
|
||||
down_url = "wget -O {} https://repo.almalinux.org/almalinux/8/PowerTools/x86_64/os/Packages/libpcap-devel-1.9.1-5.el8.x86_64.rpm --no-check-certificate -T 10".format(rpm_file)
|
||||
print(down_url)
|
||||
os.system(down_url)
|
||||
os.system("rpm -ivh {}".format(rpm_file))
|
||||
if os.path.exists(rpm_file): os.remove(rpm_file)
|
||||
else:
|
||||
os.system("dnf install libpcap-devel -y")
|
||||
else:
|
||||
os.system("dnf install libpcap-devel -y")
|
||||
elif os.path.exists('/usr/bin/yum'):
|
||||
os.system("yum install libpcap-devel -y")
|
||||
|
||||
os.system("pip install pypcap")
|
||||
try:
|
||||
import pcap
|
||||
except ImportError:
|
||||
print("pypcap module install failed.")
|
||||
sys.exit()
|
||||
|
||||
class process_network_total:
|
||||
__pid_file = 'logs/process_network_total.pid'
|
||||
__inode_list = {}
|
||||
__net_process_list = {}
|
||||
__net_process_size = {}
|
||||
__last_stat = 0
|
||||
__last_write_time = 0
|
||||
__end_time = 0
|
||||
|
||||
def start(self,timeout = 0):
|
||||
stime = time.time()
|
||||
self.__end_time = timeout + stime
|
||||
self.__last_stat = stime
|
||||
try:
|
||||
p = pcap.pcap() # 监听所有网卡
|
||||
p.setfilter('tcp') # 只监听TCP数据包
|
||||
for p_time,p_data in p:
|
||||
self.handle_packet(p_data)
|
||||
# 过期停止监听
|
||||
if timeout > 0:
|
||||
if p_time > self.__end_time:
|
||||
self.rm_pid_file()
|
||||
break
|
||||
|
||||
except:
|
||||
self.rm_pid_file()
|
||||
|
||||
def handle_packet(self, pcap_data):
|
||||
# 获取IP协议头
|
||||
ip_header = pcap_data[14:34]
|
||||
# 解析src/dst地址
|
||||
src_ip = ip_header[12:16]
|
||||
dst_ip = ip_header[16:20]
|
||||
# 解析sport/dport端口
|
||||
src_port = pcap_data[34:36]
|
||||
dst_port = pcap_data[36:38]
|
||||
|
||||
src = src_ip + b':' + src_port
|
||||
dst = dst_ip + b':' + dst_port
|
||||
# 计算数据包长度
|
||||
pack_size = len(pcap_data)
|
||||
# 统计进程流量
|
||||
self.total_net_process(dst,src,pack_size)
|
||||
|
||||
def total_net_process(self,dst,src,pack_size):
|
||||
self.get_tcp_stat()
|
||||
direction = None
|
||||
mtime = time.time()
|
||||
if dst in self.__net_process_list:
|
||||
pid = self.__net_process_list[dst]
|
||||
direction = 'down'
|
||||
elif src in self.__net_process_list:
|
||||
pid = self.__net_process_list[src]
|
||||
direction = 'up'
|
||||
else:
|
||||
if mtime - self.__last_stat > 3:
|
||||
self.__last_stat = mtime
|
||||
self.get_tcp_stat(True)
|
||||
if dst in self.__net_process_list:
|
||||
pid = self.__net_process_list[dst]
|
||||
direction = 'down'
|
||||
elif src in self.__net_process_list:
|
||||
pid = self.__net_process_list[src]
|
||||
direction = 'up'
|
||||
|
||||
if not direction: return False
|
||||
if not pid: return False
|
||||
if not pid in self.__net_process_size:
|
||||
self.__net_process_size[pid] = {}
|
||||
self.__net_process_size[pid]['down'] = 0
|
||||
self.__net_process_size[pid]['up'] = 0
|
||||
self.__net_process_size[pid]['up_package'] = 0
|
||||
self.__net_process_size[pid]['down_package'] = 0
|
||||
|
||||
self.__net_process_size[pid][direction] += pack_size
|
||||
self.__net_process_size[pid][direction + '_package'] += 1
|
||||
|
||||
# 写入到文件
|
||||
if mtime - self.__last_write_time > 1:
|
||||
self.__last_write_time = mtime
|
||||
self.write_net_process()
|
||||
|
||||
def write_net_process(self):
|
||||
w_file = '/dev/shm/mw_net_process'
|
||||
process_size = copy.deepcopy(self.__net_process_size)
|
||||
net_process = []
|
||||
for pid in process_size.keys():
|
||||
net_process.append(str(pid) + " " + str(process_size[pid]['down']) + " " + str(process_size[pid]['up']) + " " + str(process_size[pid]['down_package']) + " " + str(process_size[pid]['up_package']))
|
||||
|
||||
f = open(w_file,'w+',encoding='utf-8')
|
||||
f.write('\n'.join(net_process))
|
||||
f.close()
|
||||
|
||||
def hex_to_ip(self, hex_ip):
|
||||
hex_ip,hex_port = hex_ip.split(':')
|
||||
ip = '.'.join([str(int(hex_ip[i:i+2], 16)) for i in range(0, len(hex_ip), 2)][::-1])
|
||||
port = int(hex_port, 16)
|
||||
return ip,port
|
||||
|
||||
def get_tcp_stat(self,force = False):
|
||||
if not force and self.__net_process_list: return self.__net_process_list
|
||||
self.__net_process_list = {}
|
||||
tcp_stat_file = '/proc/net/tcp'
|
||||
tcp_stat = open(tcp_stat_file, 'rb')
|
||||
tcp_stat_list = tcp_stat.read().decode('utf-8').split('\n')
|
||||
tcp_stat.close()
|
||||
tcp_stat_list = tcp_stat_list[1:]
|
||||
if force: self.get_process_inodes(force)
|
||||
for i in tcp_stat_list:
|
||||
tcp_tmp = i.split()
|
||||
if len(tcp_tmp) < 10: continue
|
||||
inode = tcp_tmp[9]
|
||||
if inode == '0': continue
|
||||
local_ip,local_port = self.hex_to_ip(tcp_tmp[1])
|
||||
if local_ip == '127.0.0.1': continue
|
||||
remote_ip,remote_port = self.hex_to_ip(tcp_tmp[2])
|
||||
if local_ip == remote_ip: continue
|
||||
if remote_ip == '0.0.0.0': continue
|
||||
|
||||
pid = self.inode_to_pid(inode,force)
|
||||
if not pid: continue
|
||||
|
||||
key = self.get_ip_pack(local_ip) + b':' + self.get_port_pack(local_port)
|
||||
self.__net_process_list[key] = pid
|
||||
return self.__net_process_list
|
||||
|
||||
|
||||
def get_port_pack(self,port):
|
||||
return struct.pack('H',int(port))[::-1]
|
||||
|
||||
def get_ip_pack(self,ip):
|
||||
ip_arr = ip.split('.')
|
||||
ip_pack = b''
|
||||
for i in ip_arr:
|
||||
ip_pack += struct.pack('B',int(i))
|
||||
return ip_pack
|
||||
|
||||
def inode_to_pid(self,inode,force = False):
|
||||
inode_list = self.get_process_inodes()
|
||||
if inode in inode_list:
|
||||
return inode_list[inode]
|
||||
return None
|
||||
|
||||
def get_process_inodes(self,force = False):
|
||||
if not force and self.__inode_list: return self.__inode_list
|
||||
proc_path = '/proc'
|
||||
inode_list = {}
|
||||
for pid in os.listdir(proc_path):
|
||||
try:
|
||||
if not pid.isdigit(): continue
|
||||
inode_path = proc_path + '/' + pid + '/fd'
|
||||
for fd in os.listdir(inode_path):
|
||||
try:
|
||||
fd_file = inode_path + '/' + fd
|
||||
fd_link = os.readlink(fd_file)
|
||||
if fd_link.startswith('socket:['):
|
||||
inode = fd_link[8:-1]
|
||||
inode_list[inode] = pid
|
||||
except:
|
||||
continue
|
||||
except:
|
||||
continue
|
||||
self.__inode_list = inode_list
|
||||
return inode_list
|
||||
|
||||
def get_process_name(self,pid):
|
||||
pid_path = '/proc/' + pid + '/comm'
|
||||
if not os.path.exists(pid_path): return ''
|
||||
pid_file = open(pid_path, 'rb')
|
||||
pid_name = pid_file.read().decode('utf-8').strip()
|
||||
pid_file.close()
|
||||
return pid_name
|
||||
|
||||
|
||||
def write_pid(self):
|
||||
self_pid = os.getpid()
|
||||
pid_file = open(self.__pid_file,'w')
|
||||
pid_file.write(str(self_pid))
|
||||
pid_file.close()
|
||||
|
||||
def rm_pid_file(self):
|
||||
if os.path.exists(self.__pid_file):
|
||||
os.remove(self.__pid_file)
|
||||
|
||||
if __name__ == '__main__':
|
||||
p = process_network_total()
|
||||
p.write_pid()
|
||||
p.start(600)
|
||||
Executable
+1630
File diff suppressed because it is too large
Load Diff
@@ -683,8 +683,7 @@ function wsSitesListRequest(page){
|
||||
var stat_length = 0;
|
||||
var stat_req = 0;
|
||||
|
||||
console.log(rdata, data);
|
||||
|
||||
// console.log(rdata, data);
|
||||
var list = '';
|
||||
if (data.length > 0){
|
||||
for(i in data){
|
||||
@@ -2421,8 +2420,9 @@ var html = '<div>\
|
||||
<option value="500">500</option>\
|
||||
<option value="502">502</option>\
|
||||
<option value="503">503</option>\
|
||||
<option value="499">499</option>\
|
||||
<option value="400">400</option>\
|
||||
<option value="404">404</option>\
|
||||
<option value="499">499</option>\
|
||||
<option value="301">301</option>\
|
||||
<option value="302">302</option>\
|
||||
<option value="200">200</option>\
|
||||
|
||||
+7
-24
@@ -595,9 +595,6 @@ def index(reqClass=None, reqAction=None, reqData=None):
|
||||
|
||||
|
||||
##################### ssh start ###########################
|
||||
shell = None
|
||||
shell_client = None
|
||||
|
||||
|
||||
@socketio.on('webssh_websocketio')
|
||||
def webssh_websocketio(data):
|
||||
@@ -605,35 +602,21 @@ def webssh_websocketio(data):
|
||||
emit('server_response', {'data': '会话丢失,请重新登陆面板!\r\n'})
|
||||
return
|
||||
|
||||
global shell_client
|
||||
if not shell_client:
|
||||
import ssh_terminal
|
||||
shell_client = ssh_terminal.ssh_terminal()
|
||||
|
||||
import ssh_terminal
|
||||
shell_client = ssh_terminal.ssh_terminal.instance()
|
||||
shell_client.run(request.sid, data)
|
||||
return
|
||||
|
||||
|
||||
@socketio.on('webssh')
|
||||
def webssh(msg):
|
||||
global shell
|
||||
def webssh(data):
|
||||
if not isLogined():
|
||||
emit('server_response', {'data': '会话丢失,请重新登陆面板!\r\n'})
|
||||
return None
|
||||
|
||||
if not shell:
|
||||
shell = mw.connectSsh()
|
||||
|
||||
if shell.exit_status_ready():
|
||||
shell = mw.connectSsh()
|
||||
|
||||
if shell:
|
||||
shell.send(msg)
|
||||
try:
|
||||
time.sleep(0.005)
|
||||
recv = shell.recv(4096)
|
||||
emit('server_response', {'data': recv.decode("utf-8")})
|
||||
except Exception as ex:
|
||||
emit('server_response', {'data': str(ex)})
|
||||
import ssh_local
|
||||
shell = ssh_local.ssh_local.instance()
|
||||
shell.run(data)
|
||||
return
|
||||
|
||||
##################### ssh end ###########################
|
||||
|
||||
+36
-13
@@ -1032,7 +1032,18 @@ var index = {
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
trigger: 'axis',
|
||||
formatter :function (config) {
|
||||
var _config = config, _tips = "时间:" + _config[0].axisValue + "<br />";
|
||||
for (var i = 0; i < config.length; i++) {
|
||||
if (typeof config[i].data == "undefined") {
|
||||
return false;
|
||||
}
|
||||
_tips += '<span style="display: inline-block;width: 10px;height: 10px;border-radius: 50%;background: ' + config[i].color + ';"></span> <span>' + config[i].seriesName + ':' + config[i].data + ' '+ index.net.default_unit + '</span><br />'
|
||||
}
|
||||
return _tips;
|
||||
}
|
||||
|
||||
},
|
||||
legend: {
|
||||
data: [lan.index.net_up, lan.index.net_down],
|
||||
@@ -1130,19 +1141,31 @@ var index = {
|
||||
if (_net.data.yData.length >= limit) _net.data.yData.splice(0, 1);
|
||||
if (_net.data.zData.length >= limit) _net.data.zData.splice(0, 1);
|
||||
|
||||
|
||||
var upTmpSize = toSize(up).split(' ')[0];
|
||||
var downTmpSize = toSize(down).split(' ')[0];
|
||||
|
||||
var tmp = up;
|
||||
if (down>up){
|
||||
tmp = down;
|
||||
}
|
||||
index.net.default_unit = toSize(tmp).split(' ')[1] + '/s';
|
||||
|
||||
_net.data.zData.push(downTmpSize);
|
||||
_net.data.yData.push(upTmpSize);
|
||||
_net.data.xData.push(d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds());
|
||||
|
||||
if (up>down){
|
||||
var upTmp = toSizePos(up);
|
||||
var upTmpSize = upTmp['name'].split(' ')[0];
|
||||
index.net.default_unit = upTmp['name'].split(' ')[1] + '/s';
|
||||
|
||||
var downTmpSize = toSizePos(down,upTmp['pos'])['name'].split(' ')[0];
|
||||
// console.log('up',upTmp['pos'],toSizePos(down, upTmp['pos']),downTmpSize);
|
||||
|
||||
_net.data.zData.push(downTmpSize);
|
||||
_net.data.yData.push(upTmpSize);
|
||||
} else {
|
||||
|
||||
var downTmp = toSizePos(down);
|
||||
var downTmpSize = downTmp['name'].split(' ')[0];
|
||||
index.net.default_unit = downTmp['name'].split(' ')[1] + '/s';
|
||||
|
||||
var upTmpSize = toSizePos(up, downTmp['pos'])['name'].split(' ')[0];
|
||||
// console.log('down',downTmp['pos'],toSizePos(up, downTmp['pos']),upTmpSize);
|
||||
|
||||
_net.data.zData.push(downTmpSize);
|
||||
_net.data.yData.push(upTmpSize);
|
||||
}
|
||||
|
||||
},
|
||||
renderSelect:function(net){
|
||||
// console.log(net);
|
||||
|
||||
@@ -16,6 +16,28 @@ function toSize(a) {
|
||||
}
|
||||
}
|
||||
|
||||
function toSizePos(a, pos = 0) {
|
||||
var d = [" B", " KB", " MB", " GB", " TB", " PB"];
|
||||
var e = 1024;
|
||||
var r = {};
|
||||
for(var b = 0; b < d.length; b++) {
|
||||
if (pos > 0){
|
||||
if (b == pos){
|
||||
r['name'] = (b == 0 ? a : a.toFixed(2)) + d[b];
|
||||
r['pos'] = b;
|
||||
return r
|
||||
}
|
||||
} else {
|
||||
if( a < e) {
|
||||
r['name'] = (b == 0 ? a : a.toFixed(2)) + d[b];
|
||||
r['pos'] = b;
|
||||
return r
|
||||
}
|
||||
}
|
||||
a /= e;
|
||||
}
|
||||
}
|
||||
|
||||
function toSizeMB(a) {
|
||||
var d = [" KB", " MB"];
|
||||
var e = 1024;
|
||||
@@ -588,7 +610,7 @@ function showMsg(msg, callback ,icon, time){
|
||||
|
||||
function openPath(a) {
|
||||
setCookie("open_dir_path", a);
|
||||
window.location.href = "/files/"
|
||||
window.location.href = "/files/";
|
||||
}
|
||||
|
||||
function onlineEditFile(k, f, callback) {
|
||||
|
||||
@@ -276,6 +276,10 @@ html {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.ml10 {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.mr5 {
|
||||
margin-right: 5px;
|
||||
}
|
||||
@@ -283,6 +287,7 @@ html {
|
||||
.mr20 {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.ml0{
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user