mirror of
https://github.com/midoks/mdserver-web.git
synced 2026-10-18 23:45:52 +08:00
@@ -138,6 +138,7 @@ data/ipv6.pl
|
||||
data/restart.pl
|
||||
data/ssl.pl
|
||||
data/edate.pl
|
||||
data/osname.pl
|
||||
|
||||
plugins/l2tp
|
||||
plugins/openlitespeed
|
||||
@@ -146,3 +147,4 @@ plugins/mtproxy
|
||||
debug.out
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class config_api:
|
||||
|
||||
# 进行中.
|
||||
# 兼容主流Linux系统
|
||||
__version = '0.8.6.11'
|
||||
__version = '0.8.6.12'
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import sqlite3
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
class Sql():
|
||||
@@ -31,6 +32,14 @@ class Sql():
|
||||
except Exception as ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
def autoTextFactory(self):
|
||||
if sys.version_info[0] == 3:
|
||||
self.__DB_CONN.text_factory = lambda x: str(
|
||||
x, encoding="utf-8", errors='ignore')
|
||||
else:
|
||||
self.__DB_CONN.text_factory = lambda x: unicode(
|
||||
x, "utf-8", "ignore")
|
||||
|
||||
def dbfile(self, name):
|
||||
self.__DB_FILE = 'data/' + name + '.db'
|
||||
return self
|
||||
|
||||
+11
-1
@@ -733,7 +733,7 @@ def makeConf():
|
||||
file = getRunDir() + '/data/json/config.json'
|
||||
if not os.path.exists(file):
|
||||
c = {}
|
||||
c['title'] = 'Linux面板'
|
||||
c['title'] = 'mdserver-web | linux面板'
|
||||
c['home'] = 'http://github/midoks/mdserver-web'
|
||||
c['recycle_bin'] = True
|
||||
c['template'] = 'default'
|
||||
@@ -1022,3 +1022,13 @@ def getMyORM():
|
||||
import orm
|
||||
o = orm.ORM()
|
||||
return o
|
||||
|
||||
|
||||
def getMyORMDb():
|
||||
'''
|
||||
获取MySQL资源的ORM pip install mysqlclient==2.0.3 | pip install mysql-python
|
||||
'''
|
||||
sys.path.append(os.getcwd() + "/class/plugin")
|
||||
import ormDb
|
||||
o = ormDb.ORM()
|
||||
return o
|
||||
|
||||
+13
-3
@@ -387,9 +387,19 @@ class site_api:
|
||||
os.system('mkdir -p ' + vpath)
|
||||
data = []
|
||||
for d in os.listdir(vpath):
|
||||
|
||||
# keyPath = self.sslDir + siteName + '/privkey.pem'
|
||||
# certPath = self.sslDir + siteName + '/fullchain.pem'
|
||||
|
||||
keyPath = vpath + '/' + d + '/privkey.pem'
|
||||
certPath = vpath + '/' + d + '/fullchain.pem'
|
||||
if os.path.exists(keyPath) and os.path.exists(certPath):
|
||||
self.saveCert(keyPath, certPath)
|
||||
|
||||
mpath = vpath + '/' + d + '/info.json'
|
||||
if not os.path.exists(mpath):
|
||||
continue
|
||||
|
||||
tmp = mw.readFile(mpath)
|
||||
if not tmp:
|
||||
continue
|
||||
@@ -479,8 +489,8 @@ class site_api:
|
||||
mw.execShell('\\cp -a /tmp/backup2.conf ' + csrpath)
|
||||
return mw.returnJson(False, 'ERROR: <br><a style="color:red;">' + isError.replace("\n", '<br>') + '</a>')
|
||||
|
||||
mw.restartWeb()
|
||||
mw.writeLog('网站管理', '证书已保存!')
|
||||
mw.restartWeb()
|
||||
return mw.returnJson(True, '证书已保存!')
|
||||
|
||||
def setCertToSiteApi(self):
|
||||
@@ -2023,7 +2033,7 @@ location ^~ {from} {
|
||||
|
||||
def getPhpVersion(self):
|
||||
phpVersions = ('00', '52', '53', '54', '55',
|
||||
'56', '70', '71', '72', '73', '74', '80', '81')
|
||||
'56', '70', '71', '72', '73', '74', '80', '81', '82')
|
||||
data = []
|
||||
for val in phpVersions:
|
||||
tmp = {}
|
||||
@@ -2280,7 +2290,7 @@ location /{
|
||||
certInfo = self.getCertName(certPath)
|
||||
if not certInfo:
|
||||
return mw.returnData(False, '证书解析失败!')
|
||||
vpath = self.sslDir + certInfo['subject']
|
||||
vpath = self.sslDir + certInfo['subject'].strip()
|
||||
if not os.path.exists(vpath):
|
||||
os.system('mkdir -p ' + vpath)
|
||||
mw.writeFile(vpath + '/privkey.pem',
|
||||
|
||||
+9
-4
@@ -18,6 +18,8 @@ class ORM:
|
||||
__DB_CNF = '/etc/my.cnf'
|
||||
__DB_SOCKET = '/www/server/mysql/mysql.sock'
|
||||
|
||||
__DB_CHARSET = "utf8"
|
||||
|
||||
def __Conn(self):
|
||||
'''连接MYSQL数据库'''
|
||||
try:
|
||||
@@ -25,19 +27,19 @@ class ORM:
|
||||
if os.path.exists(self.__DB_SOCKET):
|
||||
try:
|
||||
self.__DB_CONN = connector.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
|
||||
port=self.__DB_PORT, charset="utf8", connect_timeout=1, unix_socket=self.__DB_SOCKET)
|
||||
port=self.__DB_PORT, charset=self.__DB_CHARSET, connect_timeout=1, unix_socket=self.__DB_SOCKET)
|
||||
except Exception as e:
|
||||
self.__DB_HOST = '127.0.0.1'
|
||||
self.__DB_CONN = connector.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
|
||||
port=self.__DB_PORT, charset="utf8", connect_timeout=1, unix_socket=self.__DB_SOCKET)
|
||||
port=self.__DB_PORT, charset=self.__DB_CHARSET, connect_timeout=1, unix_socket=self.__DB_SOCKET)
|
||||
else:
|
||||
try:
|
||||
self.__DB_CONN = connector.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
|
||||
port=self.__DB_PORT, charset="utf8", connect_timeout=1)
|
||||
port=self.__DB_PORT, charset=self.__DB_CHARSET, connect_timeout=1)
|
||||
except Exception as e:
|
||||
self.__DB_HOST = '127.0.0.1'
|
||||
self.__DB_CONN = connector.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
|
||||
port=self.__DB_PORT, charset="utf8", connect_timeout=1)
|
||||
port=self.__DB_PORT, charset=self.__DB_CHARSET, connect_timeout=1)
|
||||
|
||||
self.__DB_CUR = self.__DB_CONN.cursor()
|
||||
return True
|
||||
@@ -51,6 +53,9 @@ class ORM:
|
||||
def setSocket(self, sock):
|
||||
self.__DB_SOCKET = sock
|
||||
|
||||
def setCharset(self, charset):
|
||||
self.__DB_CHARSET = charset
|
||||
|
||||
def setPort(self, port):
|
||||
self.__DB_PORT = port
|
||||
|
||||
|
||||
Executable
+109
@@ -0,0 +1,109 @@
|
||||
# coding: utf-8
|
||||
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
class ORM:
|
||||
__DB_PASS = None
|
||||
__DB_USER = 'root'
|
||||
__DB_PORT = 3306
|
||||
__DB_HOST = 'localhost'
|
||||
__DB_CONN = None
|
||||
__DB_CUR = None
|
||||
__DB_ERR = None
|
||||
__DB_CNF = '/etc/my.cnf'
|
||||
|
||||
__DB_SOCKET = '/www/server/mysql/mysql.sock'
|
||||
__DB_CHARSET = 'utf8'
|
||||
|
||||
def __Conn(self):
|
||||
'''连接MYSQL数据库'''
|
||||
try:
|
||||
|
||||
try:
|
||||
import MySQLdb
|
||||
except Exception as ex:
|
||||
self.__DB_ERR = ex
|
||||
return False
|
||||
|
||||
# print(self.__DB_HOST)
|
||||
# print(self.__DB_USER)
|
||||
# print(self.__DB_PASS)
|
||||
# print(self.__DB_PORT)
|
||||
# print(self.__DB_CHARSET)
|
||||
# print(self.__DB_SOCKET)
|
||||
if os.path.exists(self.__DB_SOCKET):
|
||||
try:
|
||||
self.__DB_CONN = MySQLdb.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
|
||||
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=1, unix_socket=self.__DB_SOCKET)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.__DB_HOST = '127.0.0.1'
|
||||
self.__DB_CONN = MySQLdb.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
|
||||
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=1, unix_socket=self.__DB_SOCKET)
|
||||
else:
|
||||
try:
|
||||
self.__DB_CONN = MySQLdb.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
|
||||
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=1)
|
||||
except Exception as e:
|
||||
self.__DB_HOST = '127.0.0.1'
|
||||
self.__DB_CONN = MySQLdb.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
|
||||
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=1)
|
||||
|
||||
self.__DB_CUR = self.__DB_CONN.cursor()
|
||||
|
||||
return True
|
||||
except MySQLdb.Error as e:
|
||||
self.__DB_ERR = e
|
||||
return False
|
||||
|
||||
def setDbConf(self, conf):
|
||||
self.__DB_CNF = conf
|
||||
|
||||
def setSocket(self, sock):
|
||||
self.__DB_SOCKET = sock
|
||||
|
||||
def setCharset(self, charset):
|
||||
self.__DB_CHARSET = charset
|
||||
|
||||
def setPort(self, port):
|
||||
self.__DB_PORT = port
|
||||
|
||||
def setPwd(self, pwd):
|
||||
self.__DB_PASS = pwd
|
||||
|
||||
def getPwd(self):
|
||||
return self.__DB_PASS
|
||||
|
||||
def execute(self, sql):
|
||||
# 执行SQL语句返回受影响行
|
||||
if not self.__Conn():
|
||||
return self.__DB_ERR
|
||||
try:
|
||||
result = self.__DB_CUR.execute(sql)
|
||||
self.__DB_CONN.commit()
|
||||
self.__Close()
|
||||
return result
|
||||
except Exception as ex:
|
||||
return ex
|
||||
|
||||
def query(self, sql):
|
||||
# 执行SQL语句返回数据集
|
||||
if not self.__Conn():
|
||||
return self.__DB_ERR
|
||||
try:
|
||||
self.__DB_CUR.execute(sql)
|
||||
result = self.__DB_CUR.fetchall()
|
||||
# 将元组转换成列表
|
||||
data = map(list, result)
|
||||
self.__Close()
|
||||
return data
|
||||
except Exception as ex:
|
||||
return ex
|
||||
|
||||
# 关闭连接
|
||||
def __Close(self):
|
||||
self.__DB_CUR.close()
|
||||
self.__DB_CONN.close()
|
||||
-248
File diff suppressed because one or more lines are too long
@@ -144,10 +144,12 @@ def pSqliteDb(dbname='databases'):
|
||||
|
||||
|
||||
def pMysqlDb():
|
||||
db = mw.getMyORM()
|
||||
# mysql.connector
|
||||
# db = mw.getMyORM()
|
||||
# MySQLdb |
|
||||
db = mw.getMyORMDb()
|
||||
|
||||
db.setDbConf(getConf())
|
||||
|
||||
db.setPort(getDbPort())
|
||||
db.setSocket(getSocketFile())
|
||||
|
||||
|
||||
@@ -132,7 +132,12 @@ def pSqliteDb(dbname='databases'):
|
||||
|
||||
|
||||
def pMysqlDb():
|
||||
db = mw.getMyORM()
|
||||
# mysql.connector
|
||||
# db = mw.getMyORM()
|
||||
# MySQLdb |
|
||||
db = mw.getMyORMDb()
|
||||
|
||||
# db = mw.getMyORM()
|
||||
db.__DB_CNF = getConf()
|
||||
db.setPort(getDbPort())
|
||||
db.setSocket(getSocketFile())
|
||||
|
||||
@@ -35,6 +35,7 @@ open_files_limit = 65535
|
||||
#skip-external-locking
|
||||
#loose-skip-innodb
|
||||
#skip-grant-tables
|
||||
skip-ssl
|
||||
|
||||
|
||||
log-bin=mysql-bin
|
||||
|
||||
@@ -37,6 +37,7 @@ max_allowed_packet = 128M
|
||||
#loose-skip-innodb
|
||||
#skip-networking
|
||||
#skip-name-resolve
|
||||
skip-ssl
|
||||
|
||||
log-bin=mysql-bin
|
||||
binlog_format=mixed
|
||||
|
||||
@@ -38,6 +38,8 @@ max_allowed_packet = 128M
|
||||
#loose-skip-innodb
|
||||
#skip-networking
|
||||
#skip-name-resolve
|
||||
skip-ssl
|
||||
|
||||
|
||||
log-bin=mysql-bin
|
||||
binlog_format=mixed
|
||||
|
||||
@@ -134,9 +134,14 @@ def pSqliteDb(dbname='databases'):
|
||||
|
||||
|
||||
def pMysqlDb():
|
||||
db = mw.getMyORM()
|
||||
# mysql.connector
|
||||
# db = mw.getMyORM()
|
||||
# MySQLdb |
|
||||
db = mw.getMyORMDb()
|
||||
|
||||
db.setPort(getDbPort())
|
||||
db.setSocket(getSocketFile())
|
||||
# db.setCharset("utf8")
|
||||
db.setPwd(pSqliteDb('config').where('id=?', (1,)).getField('mysql_root'))
|
||||
return db
|
||||
|
||||
@@ -1495,6 +1500,7 @@ def getMasterStatus(version=''):
|
||||
|
||||
db = pMysqlDb()
|
||||
dlist = db.query('show slave status')
|
||||
dlist = list(dlist)
|
||||
# print(dlist, len(dlist))
|
||||
if len(dlist) > 0 and (dlist[0][10] == 'Yes' or dlist[0][11] == 'Yes'):
|
||||
data['slave_status'] = True
|
||||
|
||||
@@ -10,6 +10,10 @@ sourcePath=${serverPath}/source
|
||||
sysName=`uname`
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl
|
||||
|
||||
function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
|
||||
function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" == "$1"; }
|
||||
function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
|
||||
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
|
||||
|
||||
version=7.3.33
|
||||
PHP_VER=73
|
||||
@@ -49,6 +53,12 @@ if [ "$IS_64BIT" == "64" ];then
|
||||
OPTIONS="${OPTIONS} --with-libdir=lib64"
|
||||
fi
|
||||
|
||||
ZIP_OPTION='--enable-zip'
|
||||
libzip_version=`pkg-config libzip --modversion`
|
||||
if version_lt "$libzip_version" "0.11.0" ;then
|
||||
export PKG_CONFIG_PATH=$serverPath/lib/libzip/lib/pkgconfig
|
||||
ZIP_OPTION="--with-libzip=$serverPath/lib/libzip"
|
||||
fi
|
||||
|
||||
if [ ! -d $serverPath/php/73 ];then
|
||||
cd $sourcePath/php/php${PHP_VER} && ./configure \
|
||||
@@ -60,7 +70,7 @@ if [ ! -d $serverPath/php/73 ];then
|
||||
--with-pdo-mysql=mysqlnd \
|
||||
--with-zlib-dir=$serverPath/lib/zlib \
|
||||
--enable-ftp \
|
||||
--enable-zip \
|
||||
$ZIP_OPTION\
|
||||
--enable-sockets \
|
||||
--enable-simplexml \
|
||||
--enable-mbstring \
|
||||
|
||||
@@ -11,6 +11,11 @@ sysName=`uname`
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl
|
||||
|
||||
|
||||
function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
|
||||
function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" == "$1"; }
|
||||
function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
|
||||
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
|
||||
|
||||
version=7.4.26
|
||||
PHP_VER=74
|
||||
Install_php()
|
||||
@@ -22,6 +27,7 @@ mkdir -p $serverPath/php
|
||||
|
||||
cd $serverPath/mdserver-web/plugins/php/lib && /bin/bash freetype_new.sh
|
||||
cd $serverPath/mdserver-web/plugins/php/lib && /bin/bash zlib.sh
|
||||
cd $serverPath/mdserver-web/plugins/php/lib && /bin/bash libzip.sh
|
||||
|
||||
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
|
||||
|
||||
@@ -49,9 +55,7 @@ if [ $sysName == 'Darwin' ]; then
|
||||
export LDFLAGS="-L/usr/local/opt/libxml2/lib"
|
||||
else
|
||||
OPTIONS='--without-iconv'
|
||||
# OPTIONS="--with-iconv=${serverPath}/lib/libiconv"
|
||||
OPTIONS="${OPTIONS} --with-curl"
|
||||
# OPTIONS="${OPTIONS} --with-zip=${serverPath}/lib/libzip"
|
||||
fi
|
||||
|
||||
IS_64BIT=`getconf LONG_BIT`
|
||||
@@ -61,6 +65,14 @@ fi
|
||||
|
||||
echo "$sourcePath/php/php${PHP_VER}"
|
||||
|
||||
ZIP_OPTION='--with-zip'
|
||||
libzip_version=`pkg-config libzip --modversion`
|
||||
if version_lt "$libzip_version" "0.11.0" ;then
|
||||
export PKG_CONFIG_PATH=$serverPath/lib/libzip/lib/pkgconfig
|
||||
ZIP_OPTION="--with-zip=$serverPath/lib/libzip"
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -d $serverPath/php/${PHP_VER} ];then
|
||||
cd $sourcePath/php/php${PHP_VER} && make clean
|
||||
./buildconf --force
|
||||
@@ -72,7 +84,7 @@ if [ ! -d $serverPath/php/${PHP_VER} ];then
|
||||
--with-mysqli=mysqlnd \
|
||||
--with-pdo-mysql=mysqlnd \
|
||||
--with-zlib-dir=$serverPath/lib/zlib \
|
||||
--with-zip \
|
||||
$ZIP_OPTION \
|
||||
--enable-ftp \
|
||||
--enable-mbstring \
|
||||
--enable-sockets \
|
||||
|
||||
@@ -10,6 +10,11 @@ sourcePath=${serverPath}/source
|
||||
sysName=`uname`
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl
|
||||
|
||||
function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
|
||||
function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" == "$1"; }
|
||||
function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
|
||||
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
|
||||
|
||||
|
||||
version=8.0.21
|
||||
PHP_VER=80
|
||||
@@ -55,6 +60,13 @@ if [ "$IS_64BIT" == "64" ];then
|
||||
OPTIONS="${OPTIONS} --with-libdir=lib64"
|
||||
fi
|
||||
|
||||
ZIP_OPTION='--with-zip'
|
||||
libzip_version=`pkg-config libzip --modversion`
|
||||
if version_lt "$libzip_version" "0.11.0" ;then
|
||||
export PKG_CONFIG_PATH=$serverPath/lib/libzip/lib/pkgconfig
|
||||
ZIP_OPTION="--with-zip=$serverPath/lib/libzip"
|
||||
fi
|
||||
|
||||
echo "$sourcePath/php/php${PHP_VER}"
|
||||
|
||||
if [ ! -d $serverPath/php/${PHP_VER} ];then
|
||||
@@ -68,7 +80,7 @@ if [ ! -d $serverPath/php/${PHP_VER} ];then
|
||||
--with-mysqli=mysqlnd \
|
||||
--with-pdo-mysql=mysqlnd \
|
||||
--with-zlib-dir=$serverPath/lib/zlib \
|
||||
--with-zip \
|
||||
$ZIP_OPTION \
|
||||
--enable-ftp \
|
||||
--enable-mbstring \
|
||||
--enable-sockets \
|
||||
|
||||
@@ -10,6 +10,11 @@ sourcePath=${serverPath}/source
|
||||
sysName=`uname`
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl
|
||||
|
||||
function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
|
||||
function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" == "$1"; }
|
||||
function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
|
||||
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
|
||||
|
||||
|
||||
version=8.1.8
|
||||
PHP_VER=81
|
||||
@@ -49,6 +54,13 @@ else
|
||||
OPTIONS="${OPTIONS} --with-curl"
|
||||
fi
|
||||
|
||||
ZIP_OPTION='--with-zip'
|
||||
libzip_version=`pkg-config libzip --modversion`
|
||||
if version_lt "$libzip_version" "0.11.0" ;then
|
||||
export PKG_CONFIG_PATH=$serverPath/lib/libzip/lib/pkgconfig
|
||||
ZIP_OPTION="--with-zip=$serverPath/lib/libzip"
|
||||
fi
|
||||
|
||||
|
||||
echo "$sourcePath/php/php${PHP_VER}"
|
||||
|
||||
@@ -63,7 +75,7 @@ if [ ! -d $serverPath/php/${PHP_VER} ];then
|
||||
--with-mysqli=mysqlnd \
|
||||
--with-pdo-mysql=mysqlnd \
|
||||
--with-zlib-dir=$serverPath/lib/zlib \
|
||||
--with-zip \
|
||||
$ZIP_OPTION \
|
||||
--enable-ftp \
|
||||
--enable-mbstring \
|
||||
--enable-sockets \
|
||||
|
||||
@@ -10,6 +10,11 @@ sourcePath=${serverPath}/source
|
||||
sysName=`uname`
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl
|
||||
|
||||
function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
|
||||
function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" == "$1"; }
|
||||
function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
|
||||
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
|
||||
|
||||
|
||||
version=8.2.0alpha2
|
||||
PHP_VER=82
|
||||
@@ -50,6 +55,14 @@ if [ "$IS_64BIT" == "64" ];then
|
||||
OPTIONS="${OPTIONS} --with-libdir=lib64"
|
||||
fi
|
||||
|
||||
ZIP_OPTION='--with-zip'
|
||||
libzip_version=`pkg-config libzip --modversion`
|
||||
if version_lt "$libzip_version" "0.11.0" ;then
|
||||
export PKG_CONFIG_PATH=$serverPath/lib/libzip/lib/pkgconfig
|
||||
ZIP_OPTION="--with-zip=$serverPath/lib/libzip"
|
||||
fi
|
||||
|
||||
|
||||
echo "$sourcePath/php/php${PHP_VER}"
|
||||
|
||||
if [ ! -d $serverPath/php/${PHP_VER} ];then
|
||||
@@ -63,7 +76,7 @@ if [ ! -d $serverPath/php/${PHP_VER} ];then
|
||||
--with-mysqli=mysqlnd \
|
||||
--with-pdo-mysql=mysqlnd \
|
||||
--with-zlib-dir=$serverPath/lib/zlib \
|
||||
--with-zip \
|
||||
$ZIP_OPTION \
|
||||
--enable-mbstring \
|
||||
--enable-ftp \
|
||||
--enable-sockets \
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"receive":{
|
||||
"default":{
|
||||
"uid": "root",
|
||||
"use chroot": "no",
|
||||
"dont compress": "*.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2 *.mp4 *.avi *.swf *.rar",
|
||||
"hosts allow": "",
|
||||
"max connections": 200,
|
||||
"gid": "root",
|
||||
"timeout": 600,
|
||||
"pid file": "/var/run/rsyncd.pid",
|
||||
"log file": "/var/log/rsyncd.log",
|
||||
"port": 873
|
||||
},
|
||||
"list":[]
|
||||
},
|
||||
"send":{
|
||||
"default":{
|
||||
"logfile": "/www/server/rsyncd/lsyncd.log",
|
||||
"inotifyMode": "CloseWrite",
|
||||
"maxProcesses": 8,
|
||||
"statusFile": "/www/server/rsyncd/lsyncd.status"
|
||||
},
|
||||
"list":[]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
settings {
|
||||
logfile = "{$SERVER_PATH}/rsyncd/lsyncd.log",
|
||||
inotifyMode = "CloseWrite",
|
||||
maxProcesses = 8,
|
||||
statusFile = "{$SERVER_PATH}/rsyncd/lsyncd.status"
|
||||
}
|
||||
@@ -5,5 +5,4 @@ max connections = 100
|
||||
log file = /var/log/rsyncd.log
|
||||
pid file = /var/run/rsyncd.pid
|
||||
list = false
|
||||
hosts allow = *
|
||||
secrets file = /etc/rsyncd.passwd
|
||||
hosts allow = *
|
||||
@@ -1,12 +1,79 @@
|
||||
<style type="text/css">
|
||||
.overflow_hide {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.lsyncd_exclude label {
|
||||
font-weight: normal;
|
||||
margin-right: 20px
|
||||
}
|
||||
|
||||
.lsyncd_exclude button {
|
||||
vertical-align: 0
|
||||
}
|
||||
|
||||
.lsyncd_exclude {
|
||||
overflow: hidden;
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
.lsyncd_exclude span {
|
||||
margin-right: 5px
|
||||
}
|
||||
|
||||
.lsyncd_exclude fieldset {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 3px;
|
||||
float: left;
|
||||
padding-bottom: 0;
|
||||
/* width: 240px; */
|
||||
}
|
||||
|
||||
.wafConf fieldset:nth-of-type(2) {
|
||||
margin: 0 10px
|
||||
}
|
||||
|
||||
.lsyncd_exclude legend {
|
||||
border: 0 none;
|
||||
font-size: 14px;
|
||||
margin: 0 6px;
|
||||
padding: 3px;
|
||||
width: auto
|
||||
}
|
||||
|
||||
.lsyncd_exclude fieldset input {
|
||||
margin-left: 4px
|
||||
}
|
||||
|
||||
.lsyncd_exclude fieldset .table {
|
||||
margin-top: -1px;
|
||||
margin-bottom: 0
|
||||
}
|
||||
|
||||
.lsyncd_exclude fieldset .table tr td:nth-of-type(2) {
|
||||
width: 42px
|
||||
}
|
||||
|
||||
.lsyncd_exclude fieldset .table-overflow {
|
||||
height: 210px;
|
||||
overflow: auto;
|
||||
margin-top: 10px;
|
||||
border-top: #ddd 1px solid
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="pluginService('rsyncd');">服务</p>
|
||||
<p onclick="pluginInitD('rsyncd');">自启动</p>
|
||||
<p onclick="pluginConfig('rsyncd');">配置修改</p>
|
||||
<p onclick="pluginConfig('rsyncd','','conf_pwd');">密钥配置</p>
|
||||
<p onclick="lsyncdSend();">发送配置</p>
|
||||
<p onclick="rsyncdReceive();">接收配置</p>
|
||||
<p onclick="pluginLogs('rsyncd','','run_log');">日志</p>
|
||||
<p onclick="rsRead()">说明</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
@@ -16,8 +83,12 @@
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
resetPluginWinWidth(700);
|
||||
$.getScript( "/plugins/file?name=rsyncd&f=js/rsyncd.js", function() {
|
||||
// $.getScript("/plugins/file?name=rsyncd&f=js/base64.js", function() {
|
||||
// console.log('base64 load');
|
||||
// });
|
||||
$.getScript("/plugins/file?name=rsyncd&f=js/rsyncd.js", function() {
|
||||
pluginService('rsyncd');
|
||||
});
|
||||
</script>
|
||||
+633
-84
@@ -73,18 +73,24 @@ def status():
|
||||
"ps -ef|grep rsync |grep -v grep | grep -v python | awk '{print $2}'")
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
|
||||
# data = mw.execShell(
|
||||
# "ps -ef|grep lsyncd |grep -v grep | grep -v python | awk '{print $2}'")
|
||||
# if data[0] == '':
|
||||
# return 'stop'
|
||||
|
||||
return 'start'
|
||||
|
||||
|
||||
def appConf():
|
||||
return getServerDir() + '/rsyncd.conf'
|
||||
# return '/etc/rsyncd.conf'
|
||||
|
||||
|
||||
def appConfPwd():
|
||||
# if mw.isAppleSystem():
|
||||
return getServerDir() + '/rsyncd.passwd'
|
||||
# return '/etc/rsyncd.passwd'
|
||||
def appAuthPwd(name):
|
||||
nameDir = getServerDir() + '/receive/' + name
|
||||
if not os.path.exists(nameDir):
|
||||
mw.execShell("mkdir -p " + nameDir)
|
||||
return nameDir + '/auth.db'
|
||||
|
||||
|
||||
def getLog():
|
||||
@@ -97,8 +103,17 @@ def getLog():
|
||||
return tmp.groups()[0]
|
||||
|
||||
|
||||
def initDreplace():
|
||||
def getLsyncdLog():
|
||||
path = getServerDir() + "/lsyncd.conf"
|
||||
conf = mw.readFile(path)
|
||||
rep = 'logfile\s*=\s*\"(.*)\"'
|
||||
tmp = re.search(rep, conf)
|
||||
if not tmp:
|
||||
return ''
|
||||
return tmp.groups()[0]
|
||||
|
||||
|
||||
def initDReceive():
|
||||
# conf
|
||||
conf_path = appConf()
|
||||
conf_tpl_path = getPluginDir() + '/conf/rsyncd.conf'
|
||||
@@ -106,18 +121,13 @@ def initDreplace():
|
||||
content = mw.readFile(conf_tpl_path)
|
||||
mw.writeFile(conf_path, content)
|
||||
|
||||
# pwd
|
||||
confpwd_path = appConfPwd()
|
||||
if not os.path.exists(confpwd_path):
|
||||
mw.writeFile(confpwd_path, '')
|
||||
mw.execShell('chmod 0600 ' + confpwd_path)
|
||||
|
||||
initD_path = getServerDir() + '/init.d'
|
||||
if not os.path.exists(initD_path):
|
||||
os.mkdir(initD_path)
|
||||
file_bin = initD_path + '/' + getPluginName()
|
||||
|
||||
file_bin = initD_path + '/' + getPluginName()
|
||||
file_tpl = getInitDTpl()
|
||||
# print(file_bin, file_tpl)
|
||||
# initd replace
|
||||
if not os.path.exists(file_bin):
|
||||
content = mw.readFile(file_tpl)
|
||||
@@ -132,14 +142,14 @@ def initDreplace():
|
||||
if os.path.exists(systemDir) and not os.path.exists(systemService):
|
||||
rsync_bin = mw.execShell('which rsync')[0].strip()
|
||||
if rsync_bin == '':
|
||||
print('rsync缺失!')
|
||||
print('rsync missing!')
|
||||
exit(0)
|
||||
|
||||
service_path = mw.getServerDir()
|
||||
se_content = mw.readFile(systemServiceTpl)
|
||||
se_content = se_content.replace('{$SERVER_PATH}', service_path)
|
||||
se_content = se_content.replace('{$RSYNC_BIN}', rsync_bin)
|
||||
mw.writeFile(systemService, se_content)
|
||||
se = mw.readFile(systemServiceTpl)
|
||||
se = se.replace('{$SERVER_PATH}', service_path)
|
||||
se = se.replace('{$RSYNC_BIN}', rsync_bin)
|
||||
mw.writeFile(systemService, se)
|
||||
mw.execShell('systemctl daemon-reload')
|
||||
|
||||
rlog = getLog()
|
||||
@@ -148,6 +158,89 @@ def initDreplace():
|
||||
return file_bin
|
||||
|
||||
|
||||
def initDSend():
|
||||
|
||||
service_path = mw.getServerDir()
|
||||
|
||||
conf_path = getServerDir() + '/lsyncd.conf'
|
||||
conf_tpl_path = getPluginDir() + '/conf/lsyncd.conf'
|
||||
if not os.path.exists(conf_path):
|
||||
content = mw.readFile(conf_tpl_path)
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
mw.writeFile(conf_path, content)
|
||||
|
||||
initD_path = getServerDir() + '/init.d'
|
||||
if not os.path.exists(initD_path):
|
||||
os.mkdir(initD_path)
|
||||
|
||||
# initd replace
|
||||
file_bin = initD_path + '/lsyncd'
|
||||
file_tpl = getPluginDir() + "/init.d/lsyncd.tpl"
|
||||
if not os.path.exists(file_bin):
|
||||
content = mw.readFile(file_tpl)
|
||||
content = contentReplace(content)
|
||||
mw.writeFile(file_bin, content)
|
||||
mw.execShell('chmod +x ' + file_bin)
|
||||
|
||||
lock_file = getServerDir() + "/installed.pl"
|
||||
# systemd
|
||||
systemDir = mw.systemdCfgDir()
|
||||
systemService = systemDir + '/lsyncd.service'
|
||||
systemServiceTpl = getPluginDir() + '/init.d/lsyncd.service.tpl'
|
||||
if not os.path.exists(lock_file):
|
||||
lsyncd_bin = mw.execShell('which lsyncd')[0].strip()
|
||||
if lsyncd_bin == '':
|
||||
print('lsyncd missing!')
|
||||
exit(0)
|
||||
|
||||
content = mw.readFile(systemServiceTpl)
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
content = content.replace('{$LSYNCD_BIN}', lsyncd_bin)
|
||||
mw.writeFile(systemService, content)
|
||||
mw.execShell('systemctl daemon-reload')
|
||||
|
||||
mw.writeFile(lock_file, "ok")
|
||||
|
||||
lslog = getLsyncdLog()
|
||||
if os.path.exists(lslog):
|
||||
mw.writeFile(lslog, '')
|
||||
|
||||
return file_bin
|
||||
|
||||
|
||||
def getDefaultConf():
|
||||
path = getServerDir() + "/config.json"
|
||||
data = mw.readFile(path)
|
||||
data = json.loads(data)
|
||||
return data
|
||||
|
||||
|
||||
def setDefaultConf(data):
|
||||
path = getServerDir() + "/config.json"
|
||||
mw.writeFile(path, json.dumps(data))
|
||||
return True
|
||||
|
||||
|
||||
def initConfigJson():
|
||||
path = getServerDir() + "/config.json"
|
||||
tpl = getPluginDir() + "/conf/config.json"
|
||||
if not os.path.exists(path):
|
||||
data = mw.readFile(tpl)
|
||||
data = json.loads(data)
|
||||
mw.writeFile(path, json.dumps(data))
|
||||
|
||||
|
||||
def initDreplace():
|
||||
|
||||
initDSend()
|
||||
|
||||
# conf
|
||||
file_bin = initDReceive()
|
||||
initConfigJson()
|
||||
|
||||
return file_bin
|
||||
|
||||
|
||||
def rsyncOp(method):
|
||||
file = initDreplace()
|
||||
if not mw.isAppleSystem():
|
||||
@@ -186,6 +279,12 @@ def initdStatus():
|
||||
data = mw.execShell(shell_cmd)
|
||||
if data[0] == '':
|
||||
return 'fail'
|
||||
|
||||
shell_cmd = 'systemctl status lsyncd | grep loaded | grep "enabled;"'
|
||||
data = mw.execShell(shell_cmd)
|
||||
if data[0] == '':
|
||||
return 'fail'
|
||||
|
||||
return 'ok'
|
||||
|
||||
|
||||
@@ -193,6 +292,7 @@ def initdInstall():
|
||||
if mw.isAppleSystem():
|
||||
return "Apple Computer does not support"
|
||||
|
||||
mw.execShell('systemctl enable lsyncd')
|
||||
mw.execShell('systemctl enable rsyncd')
|
||||
return 'ok'
|
||||
|
||||
@@ -202,6 +302,7 @@ def initdUinstall():
|
||||
if mw.isAppleSystem():
|
||||
return "Apple Computer does not support"
|
||||
|
||||
mw.execShell('systemctl diable lsyncd')
|
||||
mw.execShell('systemctl diable rsyncd')
|
||||
return 'ok'
|
||||
|
||||
@@ -211,6 +312,7 @@ def getRecListData():
|
||||
content = mw.readFile(path)
|
||||
|
||||
flist = re.findall("\[(.*)\]", content)
|
||||
|
||||
flist_len = len(flist)
|
||||
ret_list = []
|
||||
for i in range(flist_len):
|
||||
@@ -226,31 +328,27 @@ def getRecListData():
|
||||
t1 = re.search(reg, content, re.S)
|
||||
if t1:
|
||||
args = t1.groups()[0]
|
||||
# print 'args start', args, 'args_end'
|
||||
t2 = re.findall('\s*(.*)\s*=\s*(.*)', args, re.M)
|
||||
# print('args start', args, 'args_end')
|
||||
t2 = re.findall('\s*(.*)\s*\=\s*?(.*)?', args, re.M | re.I)
|
||||
for i in range(len(t2)):
|
||||
tmp[t2[i][0].strip()] = t2[i][1]
|
||||
tmp[t2[i][0].strip()] = t2[i][1].strip()
|
||||
ret_list.append(tmp)
|
||||
|
||||
return ret_list
|
||||
|
||||
|
||||
def getRecListDataBy(name):
|
||||
l = getRecListData()
|
||||
for x in range(len(l)):
|
||||
if name == l[x]["name"]:
|
||||
return l[x]
|
||||
|
||||
|
||||
def getRecList():
|
||||
ret_list = getRecListData()
|
||||
return mw.returnJson(True, 'ok', ret_list)
|
||||
|
||||
|
||||
def getUPwdList():
|
||||
pwd_path = appConfPwd()
|
||||
pwd_content = mw.readFile(pwd_path)
|
||||
plist = pwd_content.strip().split('\n')
|
||||
plist_len = len(plist)
|
||||
data = {}
|
||||
for x in range(plist_len):
|
||||
tmp = plist[x].split(':')
|
||||
data[tmp[0]] = tmp[1]
|
||||
return data
|
||||
|
||||
|
||||
def addRec():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name', 'path', 'pwd', 'ps'])
|
||||
@@ -262,10 +360,12 @@ def addRec():
|
||||
args_path = args['path']
|
||||
args_ps = args['ps']
|
||||
|
||||
pwd_path = appConfPwd()
|
||||
pwd_content = mw.readFile(pwd_path)
|
||||
pwd_content += args_name + ':' + args_pwd + "\n"
|
||||
mw.writeFile(pwd_path, pwd_content)
|
||||
delRecBy(args_name)
|
||||
|
||||
auth_path = appAuthPwd(args_name)
|
||||
pwd_content = args_name + ':' + args_pwd + "\n"
|
||||
mw.writeFile(auth_path, pwd_content)
|
||||
mw.execShell("chmod 600 " + auth_path)
|
||||
|
||||
path = appConf()
|
||||
content = mw.readFile(path)
|
||||
@@ -274,71 +374,498 @@ def addRec():
|
||||
con += 'path = ' + args_path + "\n"
|
||||
con += 'comment = ' + args_ps + "\n"
|
||||
con += 'auth users = ' + args_name + "\n"
|
||||
con += 'ignore errors' + "\n"
|
||||
con += 'secrets file = ' + auth_path + "\n"
|
||||
con += 'read only = false'
|
||||
|
||||
content = content + con
|
||||
content = content.strip() + "\n" + con
|
||||
mw.writeFile(path, content)
|
||||
return mw.returnJson(True, '添加成功')
|
||||
|
||||
|
||||
def getRec():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
name = args['name']
|
||||
|
||||
if name == "":
|
||||
tmp = {}
|
||||
tmp["name"] = ""
|
||||
tmp["comment"] = ""
|
||||
tmp["path"] = mw.getWwwDir()
|
||||
tmp["pwd"] = mw.getRandomString(16)
|
||||
return mw.returnJson(True, 'OK', tmp)
|
||||
|
||||
data = getRecListDataBy(name)
|
||||
|
||||
content = mw.readFile(data['secrets file'])
|
||||
pwd = content.strip().split(":")
|
||||
data['pwd'] = pwd[1]
|
||||
return mw.returnJson(True, 'OK', data)
|
||||
|
||||
|
||||
def delRecBy(name):
|
||||
try:
|
||||
path = appConf()
|
||||
content = mw.readFile(path)
|
||||
|
||||
reclist = getRecListData()
|
||||
ret_list_len = len(reclist)
|
||||
is_end = False
|
||||
next_name = ''
|
||||
for x in range(ret_list_len):
|
||||
tmp = reclist[x]
|
||||
if tmp['name'] == name:
|
||||
|
||||
secrets_file = tmp['secrets file']
|
||||
tp = os.path.dirname(secrets_file)
|
||||
if os.path.exists(tp):
|
||||
mw.execShell("rm -rf " + tp)
|
||||
|
||||
if x + 1 == ret_list_len:
|
||||
is_end = True
|
||||
else:
|
||||
next_name = reclist[x + 1]['name']
|
||||
reg = ''
|
||||
if is_end:
|
||||
reg = '\[' + name + '\]\s*(.*)'
|
||||
else:
|
||||
reg = '\[' + name + '\]\s*(.*)\s*\[' + next_name + '\]'
|
||||
|
||||
conre = re.search(reg, content, re.S)
|
||||
content = content.replace(
|
||||
"[" + name + "]\n" + conre.groups()[0], '')
|
||||
mw.writeFile(path, content)
|
||||
except Exception as e:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def delRec():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
args_name = args['name']
|
||||
|
||||
cmd = "sed -i '_bak' '/" + args_name + "/d' " + appConfPwd()
|
||||
mw.execShell(cmd)
|
||||
|
||||
try:
|
||||
|
||||
path = appConf()
|
||||
content = mw.readFile(path)
|
||||
|
||||
ret_list = getRecListData()
|
||||
ret_list_len = len(ret_list)
|
||||
is_end = False
|
||||
next_name = ''
|
||||
for x in range(ret_list_len):
|
||||
tmp = ret_list[x]
|
||||
if tmp['name'] == args_name:
|
||||
if x + 1 == ret_list_len:
|
||||
is_end = True
|
||||
else:
|
||||
next_name = ret_list[x + 1]['name']
|
||||
reg = ''
|
||||
if is_end:
|
||||
reg = '\[' + args_name + '\]\s*(.*)'
|
||||
else:
|
||||
reg = '\[' + args_name + '\]\s*(.*)\s*\[' + next_name + '\]'
|
||||
|
||||
conre = re.search(reg, content, re.S)
|
||||
content = content.replace(
|
||||
"[" + args_name + "]\n" + conre.groups()[0], '')
|
||||
mw.writeFile(path, content)
|
||||
name = args['name']
|
||||
ok = delRecBy(name)
|
||||
if ok:
|
||||
return mw.returnJson(True, '删除成功!')
|
||||
except Exception as e:
|
||||
return mw.returnJson(False, '删除失败!')
|
||||
return mw.returnJson(False, '删除失败!')
|
||||
|
||||
|
||||
def cmdRec():
|
||||
def cmdRecSecretKey():
|
||||
import base64
|
||||
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
an = args['name']
|
||||
pwd_list = getUPwdList()
|
||||
ip = mw.getLocalIp()
|
||||
name = args['name']
|
||||
info = getRecListDataBy(name)
|
||||
|
||||
cmd = 'echo "' + pwd_list[an] + '" > /tmp/p.pass' + "<br>"
|
||||
cmd += 'chmod 600 /tmp/p.pass' + "<br>"
|
||||
cmd += 'rsync -arv --password-file=/tmp/p.pass --progress --delete /project ' + \
|
||||
an + '@' + ip + '::' + an
|
||||
secrets_file = info['secrets file']
|
||||
content = mw.readFile(info['secrets file'])
|
||||
pwd = content.strip().split(":")
|
||||
|
||||
m = {"A": info['name'], "B": pwd[1], "C": "873"}
|
||||
m = json.dumps(m)
|
||||
m = m.encode("utf-8")
|
||||
m = base64.b64encode(m)
|
||||
cmd = m.decode("utf-8")
|
||||
return mw.returnJson(True, 'OK!', cmd)
|
||||
|
||||
# rsyncdReceive
|
||||
|
||||
def cmdRecCmd():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
name = args['name']
|
||||
info = getRecListDataBy(name)
|
||||
ip = mw.getLocalIp()
|
||||
|
||||
content = mw.readFile(info['secrets file'])
|
||||
pwd = content.strip().split(":")
|
||||
|
||||
tmp_name = '/tmp/' + name + '.pass'
|
||||
|
||||
cmd = 'echo "' + pwd[1] + '" > ' + tmp_name + '<br>'
|
||||
cmd += 'chmod 600 ' + tmp_name + ' <br>'
|
||||
cmd += 'rsync -arv --password-file=' + tmp_name + \
|
||||
' --progress --delete /project ' + name + '@' + ip + '::' + name
|
||||
return mw.returnJson(True, 'OK!', cmd)
|
||||
|
||||
|
||||
# ----------------------------- rsyncdSend start -------------------------
|
||||
|
||||
|
||||
def lsyncdReload():
|
||||
mw.execShell('systemctl reload lsyncd')
|
||||
|
||||
|
||||
def makeLsyncdConf(data):
|
||||
# print(data)
|
||||
|
||||
lsyncd_data = data['send']
|
||||
lsyncd_setting = lsyncd_data['default']
|
||||
|
||||
content = "settings {\n"
|
||||
for x in lsyncd_setting:
|
||||
v = lsyncd_setting[x]
|
||||
# print(v, type(v))
|
||||
if type(v) == str:
|
||||
content += "\t" + x + ' = "' + v + "\",\n"
|
||||
elif type(v) == int:
|
||||
content += "\t" + x + ' = ' + str(v) + ",\n"
|
||||
content += "}\n\n"
|
||||
|
||||
lsyncd_list = lsyncd_data['list']
|
||||
|
||||
rsync_bin = mw.execShell('which rsync')[0].strip()
|
||||
send_dir = getServerDir() + "/send"
|
||||
|
||||
if len(lsyncd_list) > 0:
|
||||
for x in range(len(lsyncd_list)):
|
||||
|
||||
t = lsyncd_list[x]
|
||||
name_dir = send_dir + "/" + t["name"]
|
||||
if not os.path.exists(name_dir):
|
||||
mw.execShell("mkdir -p " + name_dir)
|
||||
|
||||
cmd_exclude = name_dir + "/exclude"
|
||||
cmd_exclude_txt = ""
|
||||
for x in t['exclude']:
|
||||
cmd_exclude_txt += x + "\n"
|
||||
mw.writeFile(cmd_exclude, cmd_exclude_txt)
|
||||
cmd_pass = name_dir + "/pass"
|
||||
mw.writeFile(cmd_pass, t['password'])
|
||||
mw.execShell("chmod 600 " + cmd_pass)
|
||||
|
||||
delete_ok = ' '
|
||||
if t['delete'] == "true":
|
||||
delete_ok = ' --delete '
|
||||
|
||||
remote_addr = t['name'] + '@' + t['ip'] + "::" + t['name']
|
||||
cmd = rsync_bin + " -avzP " + "--port=" + str(t['rsync']['port']) + " --bwlimit=" + t['rsync'][
|
||||
'bwlimit'] + delete_ok + " --exclude-from=" + cmd_exclude + " --password-file=" + cmd_pass + " " + t["path"] + " " + remote_addr
|
||||
mw.writeFile(name_dir + "/cmd", cmd)
|
||||
mw.execShell("cmod +x " + name_dir + "/cmd")
|
||||
|
||||
if t['realtime'] == "false":
|
||||
continue
|
||||
|
||||
# print(x, t)
|
||||
content += "sync {\n"
|
||||
content += "\tdefault.rsync,\n"
|
||||
content += "\tsource = \"" + t['path'] + "\",\n"
|
||||
content += "\ttarget = \"" + remote_addr + "\",\n"
|
||||
content += "\tdelete = " + t['delete'] + ",\n"
|
||||
content += "\tdelay = " + t['delay'] + ",\n"
|
||||
content += "\tinit = false,\n"
|
||||
|
||||
exclude_str = json.dumps(t['exclude'])
|
||||
exclude_str = exclude_str.replace("[", "{")
|
||||
exclude_str = exclude_str.replace("]", "}")
|
||||
# print(exclude_str)
|
||||
content += "\texclude = " + exclude_str + ",\n"
|
||||
|
||||
# rsync
|
||||
content += "\trsync = {\n"
|
||||
content += "\t\tbinary = \"" + rsync_bin + "\",\n"
|
||||
content += "\t\tarchive = true,\n"
|
||||
content += "\t\tverbose = true,\n"
|
||||
content += "\t\tcompress = " + t['rsync']['compress'] + ",\n"
|
||||
content += "\t\tpassword_file = \"" + cmd_pass + "\",\n"
|
||||
|
||||
content += "\t\t_extra = {\"--bwlimit=" + t['rsync'][
|
||||
'bwlimit'] + "\", \"--port=" + str(t['rsync']['port']) + "\"},\n"
|
||||
|
||||
content += "\t}\n"
|
||||
content += "}\n"
|
||||
|
||||
path = getServerDir() + "/lsyncd.conf"
|
||||
mw.writeFile(path, content)
|
||||
|
||||
lsyncdReload()
|
||||
|
||||
import tool_task
|
||||
tool_task.createBgTask(lsyncd_list)
|
||||
|
||||
|
||||
def lsyncdListFindIp(slist, ip):
|
||||
for x in range(len(slist)):
|
||||
if slist[x]["ip"] == ip:
|
||||
return (True, x)
|
||||
return (False, -1)
|
||||
|
||||
|
||||
def lsyncdListFindName(slist, name):
|
||||
for x in range(len(slist)):
|
||||
if slist[x]["name"] == name:
|
||||
return (True, x)
|
||||
return (False, -1)
|
||||
|
||||
|
||||
def lsyncdList():
|
||||
data = getDefaultConf()
|
||||
send = data['send']
|
||||
return mw.returnJson(True, "设置成功!", send)
|
||||
|
||||
|
||||
def lsyncdGet():
|
||||
import base64
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
name = args['name']
|
||||
data = getDefaultConf()
|
||||
|
||||
slist = data['send']["list"]
|
||||
res = lsyncdListFindName(slist, name)
|
||||
|
||||
rsync = {
|
||||
'bwlimit': "1024",
|
||||
"compress": "true",
|
||||
"archive": "true",
|
||||
"verbose": "true"
|
||||
}
|
||||
|
||||
info = {
|
||||
"secret_key": '',
|
||||
"ip": '',
|
||||
"path": mw.getServerDir(),
|
||||
'rsync': rsync,
|
||||
'realtime': "true",
|
||||
'delete': "false",
|
||||
}
|
||||
if res[0]:
|
||||
list_index = res[1]
|
||||
info = slist[list_index]
|
||||
m = {"A": info['name'], "B": info["password"], "C": "873"}
|
||||
m = json.dumps(m)
|
||||
m = m.encode("utf-8")
|
||||
m = base64.b64encode(m)
|
||||
info['secret_key'] = m.decode("utf-8")
|
||||
return mw.returnJson(True, "OK", info)
|
||||
|
||||
|
||||
def lsyncdDelete():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
name = args['name']
|
||||
data = getDefaultConf()
|
||||
slist = data['send']["list"]
|
||||
res = lsyncdListFindName(slist, name)
|
||||
retdata = {}
|
||||
if res[0]:
|
||||
list_index = res[1]
|
||||
slist.pop(list_index)
|
||||
|
||||
data['send']["list"] = slist
|
||||
setDefaultConf(data)
|
||||
makeLsyncdConf(data)
|
||||
return mw.returnJson(True, "OK")
|
||||
|
||||
|
||||
def lsyncdAdd():
|
||||
import base64
|
||||
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip', 'conn_type', 'path',
|
||||
'secret_key', 'delay', 'period'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
path = args['path']
|
||||
|
||||
conn_type = args['conn_type']
|
||||
secret_key = args['secret_key']
|
||||
delete = args['delete']
|
||||
realtime = args['realtime']
|
||||
delay = args['delay']
|
||||
bwlimit = args['bwlimit']
|
||||
compress = args['compress']
|
||||
period = args['period']
|
||||
|
||||
hour = args['hour']
|
||||
minute = args['minute']
|
||||
minute_n = args['minute-n']
|
||||
|
||||
info = {
|
||||
"ip": ip,
|
||||
"path": path,
|
||||
"delete": delete,
|
||||
"realtime": realtime,
|
||||
'delay': delay,
|
||||
"conn_type": conn_type,
|
||||
"period": period,
|
||||
"hour": hour,
|
||||
"minute": minute,
|
||||
"minute-n": minute_n,
|
||||
}
|
||||
|
||||
if conn_type == "key":
|
||||
try:
|
||||
m = base64.b64decode(secret_key)
|
||||
m = json.loads(m)
|
||||
info['name'] = m['A']
|
||||
info['password'] = m['B']
|
||||
info['port'] = m['C']
|
||||
except Exception as e:
|
||||
return mw.returnJson(False, "接收密钥格式错误!")
|
||||
else:
|
||||
data = checkArgs(args, ['uname'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
info['name'] = args['uname']
|
||||
info['password'] = args['uname']
|
||||
|
||||
rsync = {
|
||||
'bwlimit': bwlimit,
|
||||
"port": info['port'],
|
||||
"compress": compress,
|
||||
"archive": "true",
|
||||
"verbose": "true"
|
||||
}
|
||||
|
||||
info['rsync'] = rsync
|
||||
|
||||
if not 'exclude' in info:
|
||||
info["exclude"] = [
|
||||
"/**.upload.tmp",
|
||||
"**/*.log",
|
||||
"**/*.tmp",
|
||||
"**/*.temp",
|
||||
".git",
|
||||
".gitignore",
|
||||
".user.ini",
|
||||
]
|
||||
|
||||
data = getDefaultConf()
|
||||
slist = data['send']["list"]
|
||||
res = lsyncdListFindName(slist, info['name'])
|
||||
if res[0]:
|
||||
list_index = res[1]
|
||||
slist[list_index] = info
|
||||
else:
|
||||
slist.append(info)
|
||||
|
||||
data['send']["list"] = slist
|
||||
|
||||
setDefaultConf(data)
|
||||
makeLsyncdConf(data)
|
||||
return mw.returnJson(True, "设置成功!")
|
||||
|
||||
|
||||
def lsyncdRun():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
send_dir = getServerDir() + "/send"
|
||||
name = args['name']
|
||||
app_dir = send_dir + "/" + name
|
||||
|
||||
cmd = "bash " + app_dir + "/cmd >> " + app_dir + "/run.log" + " 2>&1 &"
|
||||
mw.execShell(cmd)
|
||||
return mw.returnJson(True, "执行成功!")
|
||||
|
||||
|
||||
def lsyncdConfLog():
|
||||
logs_path = getServerDir() + "/lsyncd.log"
|
||||
return logs_path
|
||||
|
||||
|
||||
def lsyncdLog():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
send_dir = getServerDir() + "/send"
|
||||
name = args['name']
|
||||
app_dir = send_dir + "/" + name
|
||||
return app_dir + "/run.log"
|
||||
|
||||
|
||||
def lsyncdGetExclude():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
data = getDefaultConf()
|
||||
slist = data['send']["list"]
|
||||
res = lsyncdListFindName(slist, args['name'])
|
||||
i = res[1]
|
||||
info = slist[i]
|
||||
return mw.returnJson(True, "OK!", info['exclude'])
|
||||
|
||||
|
||||
def lsyncdRemoveExclude():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name', 'exclude'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
exclude = args['exclude']
|
||||
|
||||
data = getDefaultConf()
|
||||
slist = data['send']["list"]
|
||||
res = lsyncdListFindName(slist, args['name'])
|
||||
i = res[1]
|
||||
info = slist[i]
|
||||
|
||||
exclude_list = info['exclude']
|
||||
exclude_pop_key = -1
|
||||
for x in range(len(exclude_list)):
|
||||
if exclude_list[x] == exclude:
|
||||
exclude_pop_key = x
|
||||
|
||||
if exclude_pop_key > -1:
|
||||
exclude_list.pop(exclude_pop_key)
|
||||
|
||||
data['send']["list"][i]['exclude'] = exclude_list
|
||||
setDefaultConf(data)
|
||||
makeLsyncdConf(data)
|
||||
return mw.returnJson(True, "OK!", exclude_list)
|
||||
|
||||
|
||||
def lsyncdAddExclude():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name', 'exclude'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
exclude = args['exclude']
|
||||
|
||||
data = getDefaultConf()
|
||||
slist = data['send']["list"]
|
||||
res = lsyncdListFindName(slist, args['name'])
|
||||
i = res[1]
|
||||
info = slist[i]
|
||||
|
||||
exclude_list = info['exclude']
|
||||
exclude_list.append(exclude)
|
||||
|
||||
data['send']["list"][i]['exclude'] = exclude_list
|
||||
setDefaultConf(data)
|
||||
makeLsyncdConf(data)
|
||||
return mw.returnJson(True, "OK!", exclude_list)
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
@@ -359,8 +886,6 @@ if __name__ == "__main__":
|
||||
print(initdUinstall())
|
||||
elif func == 'conf':
|
||||
print(appConf())
|
||||
elif func == 'conf_pwd':
|
||||
print(appConfPwd())
|
||||
elif func == 'run_log':
|
||||
print(getLog())
|
||||
elif func == 'rec_list':
|
||||
@@ -369,7 +894,31 @@ if __name__ == "__main__":
|
||||
print(addRec())
|
||||
elif func == 'del_rec':
|
||||
print(delRec())
|
||||
elif func == 'cmd_rec':
|
||||
print(cmdRec())
|
||||
elif func == 'get_rec':
|
||||
print(getRec())
|
||||
elif func == 'cmd_rec_secret_key':
|
||||
print(cmdRecSecretKey())
|
||||
elif func == 'cmd_rec_cmd':
|
||||
print(cmdRecCmd())
|
||||
elif func == 'lsyncd_list':
|
||||
print(lsyncdList())
|
||||
elif func == 'lsyncd_add':
|
||||
print(lsyncdAdd())
|
||||
elif func == 'lsyncd_get':
|
||||
print(lsyncdGet())
|
||||
elif func == 'lsyncd_delete':
|
||||
print(lsyncdDelete())
|
||||
elif func == 'lsyncd_run':
|
||||
print(lsyncdRun())
|
||||
elif func == 'lsyncd_log':
|
||||
print(lsyncdLog())
|
||||
elif func == 'lsyncd_conf_log':
|
||||
print(lsyncdConfLog())
|
||||
elif func == 'lsyncd_get_exclude':
|
||||
print(lsyncdGetExclude())
|
||||
elif func == 'lsyncd_remove_exclude':
|
||||
print(lsyncdRemoveExclude())
|
||||
elif func == 'lsyncd_add_exclude':
|
||||
print(lsyncdAddExclude())
|
||||
else:
|
||||
print('error')
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"name":"rsyncd",
|
||||
"type":"软件",
|
||||
"ps":"rsyncd同步助手",
|
||||
"versions":"1.0",
|
||||
"versions":"2.0",
|
||||
"shell":"install.sh",
|
||||
"checks":"server/rsyncd",
|
||||
"path": "server/rsyncd",
|
||||
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Lightweight inotify based sync daemon
|
||||
ConditionPathExists={$SERVER_PATH}/rsyncd/lsyncd.conf
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart={$LSYNCD_BIN} -nodaemon {$SERVER_PATH}/rsyncd/lsyncd.conf
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Executable
+108
@@ -0,0 +1,108 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# chkconfig: - 85 15
|
||||
# description: Lightweight inotify based sync daemon
|
||||
#
|
||||
# processname: lsyncd
|
||||
# config: /etc/lsyncd.conf
|
||||
# config: /etc/sysconfig/lsyncd
|
||||
# pidfile: /var/run/lsyncd.pid
|
||||
# Source function library
|
||||
|
||||
if [ -f /etc/init.d/functions ];then
|
||||
. /etc/init.d/functions
|
||||
fi
|
||||
|
||||
if [ -f /lib/lsb/init-functions ];then
|
||||
. /lib/lsb/init-functions
|
||||
fi
|
||||
|
||||
# Source networking configuration.
|
||||
if [ -f /etc/sysconfig/network ];then
|
||||
. /etc/sysconfig/network
|
||||
fi
|
||||
|
||||
LSYNCD_OPTIONS="-pidfile /var/run/lsyncd.pid {$SERVER_PATH}/rsyncd/lsyncd.conf"
|
||||
if [ -e /etc/sysconfig/lsyncd ]; then
|
||||
. /etc/sysconfig/lsyncd
|
||||
fi
|
||||
RETVAL=0
|
||||
prog="lsyncd"
|
||||
thelock=/var/lock/subsys/lsyncd
|
||||
LSYNCD_USER=root
|
||||
|
||||
start() {
|
||||
[ -f {$SERVER_PATH}/rsyncd/lsyncd.conf ] || exit 6
|
||||
echo -n $"Starting $prog: "
|
||||
if [ $UID -ne 0 ]; then
|
||||
RETVAL=1
|
||||
failure
|
||||
else
|
||||
nohup /usr/bin/lsyncd $LSYNCD_OPTIONS > /dev/null &
|
||||
RETVAL=$?
|
||||
[ $RETVAL -eq 0 ] && touch $thelock
|
||||
fi;
|
||||
echo
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
stop() {
|
||||
echo -n $"Stopping $prog: "
|
||||
if [ $UID -ne 0 ]; then
|
||||
RETVAL=1
|
||||
failure
|
||||
else
|
||||
killproc lsyncd
|
||||
RETVAL=$?
|
||||
[ $RETVAL -eq 0 ] && rm -f $thelock
|
||||
fi;
|
||||
echo
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
reload(){
|
||||
echo -n $"Reloading $prog: "
|
||||
killproc lsyncd -HUP
|
||||
RETVAL=$?
|
||||
echo
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
restart(){
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
condrestart(){
|
||||
[ -e $thelock ] && restart
|
||||
return 0
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
|
||||
restart)
|
||||
restart
|
||||
;;
|
||||
reload)
|
||||
reload
|
||||
;;
|
||||
condrestart)
|
||||
condrestart
|
||||
;;
|
||||
|
||||
status)
|
||||
status lsyncd
|
||||
RETVAL=$?
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
|
||||
RETVAL=1
|
||||
esac
|
||||
|
||||
exit $RETVAL
|
||||
@@ -14,25 +14,35 @@ sysName=`uname`
|
||||
# bash /www/server/mdsever-web/scripts/getos.sh
|
||||
bash ${rootPath}/scripts/getos.sh
|
||||
OSNAME=`cat ${rootPath}/data/osname.pl`
|
||||
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
|
||||
|
||||
|
||||
echo $OSNAME
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl
|
||||
Install_rsyncd()
|
||||
{
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
mkdir -p $serverPath/rsyncd
|
||||
|
||||
|
||||
if [ "$OSNAME" == "debian'" ] || [ "$OSNAME" == "ubuntu'" ];then
|
||||
apt install -y rsync
|
||||
apt install -y lsyncd
|
||||
elif [[ "$OSNAME" == "arch" ]]; then
|
||||
echo y | pacman -Sy rsync
|
||||
echo y | pacman -Sy lsyncd
|
||||
elif [[ "$OSNAME" == "macos" ]]; then
|
||||
# brew install rsync
|
||||
# brew install lsyncd
|
||||
echo "ok"
|
||||
else
|
||||
yum install -y rsync
|
||||
yum install -y lsyncd
|
||||
fi
|
||||
|
||||
mkdir -p $serverPath/rsyncd
|
||||
mkdir -p $serverPath/rsyncd/receive
|
||||
mkdir -p $serverPath/rsyncd/send
|
||||
|
||||
echo '1.0' > $serverPath/rsyncd/version.pl
|
||||
echo '2.0' > $serverPath/rsyncd/version.pl
|
||||
echo '安装完成' > $install_tmp
|
||||
cd ${rootPath} && python3 ${rootPath}/plugins/rsyncd/index.py start
|
||||
cd ${rootPath} && python3 ${rootPath}/plugins/rsyncd/index.py initd_install
|
||||
@@ -51,6 +61,7 @@ Uninstall_rsyncd()
|
||||
if [ -f $serverPath/rsyncd/initd/rsyncd ];then
|
||||
$serverPath/rsyncd/initd/rsyncd stop
|
||||
fi
|
||||
|
||||
rm -rf $serverPath/rsyncd
|
||||
echo "卸载完成" > $install_tmp
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
//base64.js
|
||||
function base64_encode(str) {
|
||||
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
var out, i, len;
|
||||
var c1, c2, c3;
|
||||
|
||||
len = str.length;
|
||||
i = 0;
|
||||
out = "";
|
||||
while(i < len) {
|
||||
c1 = str.charCodeAt(i++) & 0xff;
|
||||
if(i == len)
|
||||
{
|
||||
out += base64EncodeChars.charAt(c1 >> 2);
|
||||
out += base64EncodeChars.charAt((c1 & 0x3) << 4);
|
||||
out += "==";
|
||||
break;
|
||||
}
|
||||
c2 = str.charCodeAt(i++);
|
||||
if(i == len)
|
||||
{
|
||||
out += base64EncodeChars.charAt(c1 >> 2);
|
||||
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
|
||||
out += base64EncodeChars.charAt((c2 & 0xF) << 2);
|
||||
out += "=";
|
||||
break;
|
||||
}
|
||||
c3 = str.charCodeAt(i++);
|
||||
out += base64EncodeChars.charAt(c1 >> 2);
|
||||
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
|
||||
out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
|
||||
out += base64EncodeChars.charAt(c3 & 0x3F);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function base64_decode(str) {
|
||||
var base64DecodeChars = new Array(
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
|
||||
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
|
||||
var c1, c2, c3, c4;
|
||||
var i, len, out;
|
||||
|
||||
len = str.length;
|
||||
i = 0;
|
||||
out = "";
|
||||
while(i < len) {
|
||||
/* c1 */
|
||||
do {
|
||||
c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
|
||||
} while(i < len && c1 == -1);
|
||||
if(c1 == -1)
|
||||
break;
|
||||
|
||||
/* c2 */
|
||||
do {
|
||||
c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
|
||||
} while(i < len && c2 == -1);
|
||||
if(c2 == -1)
|
||||
break;
|
||||
|
||||
out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
|
||||
|
||||
/* c3 */
|
||||
do {
|
||||
c3 = str.charCodeAt(i++) & 0xff;
|
||||
if(c3 == 61)
|
||||
return out;
|
||||
c3 = base64DecodeChars[c3];
|
||||
} while(i < len && c3 == -1);
|
||||
if(c3 == -1)
|
||||
break;
|
||||
|
||||
out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
|
||||
|
||||
/* c4 */
|
||||
do {
|
||||
c4 = str.charCodeAt(i++) & 0xff;
|
||||
if(c4 == 61)
|
||||
return out;
|
||||
c4 = base64DecodeChars[c4];
|
||||
} while(i < len && c4 == -1);
|
||||
if(c4 == -1)
|
||||
break;
|
||||
out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function utf16to8(str) {
|
||||
var out, i, len, c;
|
||||
|
||||
out = "";
|
||||
len = str.length;
|
||||
for(i = 0; i < len; i++) {
|
||||
c = str.charCodeAt(i);
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
out += str.charAt(i);
|
||||
} else if (c > 0x07FF) {
|
||||
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
|
||||
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
|
||||
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
|
||||
} else {
|
||||
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
|
||||
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function utf8to16(str) {
|
||||
var out, i, len, c;
|
||||
var char2, char3;
|
||||
|
||||
out = "";
|
||||
len = str.length;
|
||||
i = 0;
|
||||
while(i < len) {
|
||||
c = str.charCodeAt(i++);
|
||||
switch(c >> 4)
|
||||
{
|
||||
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
||||
// 0xxxxxxx
|
||||
out += str.charAt(i-1);
|
||||
break;
|
||||
case 12: case 13:
|
||||
// 110x xxxx 10xx xxxx
|
||||
char2 = str.charCodeAt(i++);
|
||||
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
|
||||
break;
|
||||
case 14:
|
||||
// 1110 xxxx 10xx xxxx 10xx xxxx
|
||||
char2 = str.charCodeAt(i++);
|
||||
char3 = str.charCodeAt(i++);
|
||||
out += String.fromCharCode(((c & 0x0F) << 12) |
|
||||
((char2 & 0x3F) << 6) |
|
||||
((char3 & 0x3F) << 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
+623
-59
@@ -36,6 +36,542 @@ function rsPost(method,args,callback, title){
|
||||
},'json');
|
||||
}
|
||||
|
||||
///////////////// ----------------- 发送配置 ---------------- //////////////
|
||||
|
||||
function createSendTask(name = ''){
|
||||
var args = {};
|
||||
args["name"] = name;
|
||||
rsPost('lsyncd_get', args, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
var data = rdata.data;
|
||||
console.log(data);
|
||||
|
||||
var layerName = '创建';
|
||||
if (name!=''){
|
||||
layerName = '编辑';
|
||||
}
|
||||
|
||||
var compress_true = "";
|
||||
var compress_false = "";
|
||||
if (data['rsync']['compress'] == 'true'){
|
||||
compress_true = "selected";
|
||||
compress_false = "";
|
||||
} else {
|
||||
compress_true = "";
|
||||
compress_false = "selected";
|
||||
}
|
||||
|
||||
|
||||
var delete_true = "";
|
||||
var delete_false = "";
|
||||
if (data['delete'] == 'false'){
|
||||
delete_true = "selected";
|
||||
delete_false = "";
|
||||
} else {
|
||||
delete_true = "";
|
||||
delete_false = "selected";
|
||||
}
|
||||
|
||||
|
||||
var realtime_true = "";
|
||||
var realtime_false = "";
|
||||
if (data['realtime'] == 'true'){
|
||||
realtime_true = "selected";
|
||||
realtime_false = "";
|
||||
} else {
|
||||
realtime_true = "";
|
||||
realtime_false = "selected";
|
||||
}
|
||||
|
||||
|
||||
var period_day = "";
|
||||
var period_minute_n = "";
|
||||
if (data['period'] == 'day'){
|
||||
period_day = "selected";
|
||||
period_minute_n = "";
|
||||
} else {
|
||||
period_day = "";
|
||||
period_minute_n = "selected";
|
||||
}
|
||||
|
||||
|
||||
var layerID = layer.open({
|
||||
type: 1,
|
||||
area: ['600px','500px'],
|
||||
title: layerName+"发送任务",
|
||||
closeBtn: 1,
|
||||
shift: 0,
|
||||
shadeClose: false,
|
||||
btn: ['提交','取消'],
|
||||
content:"<form class='bt-form pd20' id='fromServerPath' accept-charset='utf-8'>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>服务器IP</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input class='bt-input-text' type='text' name='ip' placeholder='请输入接收服务器IP' value='"+data["ip"]+"' style='width:310px' />\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>同步目录</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input id='inputPath' class='bt-input-text mr5' type='text' name='path' value='"+data["path"]+"' placeholder='请选择同步目录' style='width:310px' /><span class='glyphicon glyphicon-folder-open cursor' onclick='changePath(\"inputPath\")'></span>\
|
||||
<span data-toggle='tooltip' data-placement='top' title='【同步目录】若不以/结尾,则表示将数据同步到二级目录,一般情况下目录路径请以/结尾' class='bt-ico-ask' style='cursor: pointer;'>?</span>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>同步方式</span>\
|
||||
<div class='info-r c4'>\
|
||||
<select class='bt-input-text' name='delete' style='width:100px'>\
|
||||
<option value='false' "+delete_true+">增量</option>\
|
||||
<option value='true' "+delete_false+">完全</option>\
|
||||
</select>\
|
||||
<span data-toggle='tooltip' data-placement='top' title='【同步方式】增量: 数据更改/增加时同步,且只追加和替换文件\n【同步方式】完全: 保持两端的数据与目录结构的一致性,会同步删除、追加和替换文件和目录' class='bt-ico-ask' style='cursor: pointer;'>?</span>\
|
||||
<span style='margin-left: 20px;margin-right: 10px;'>同步周期</span>\
|
||||
<select class='bt-input-text synchronization' name='realtime' style='width:100px'>\
|
||||
<option value='true' "+realtime_true+">实时同步</option>\
|
||||
<option value='false' "+realtime_false+">定时同步</option>\
|
||||
</select>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line' id='period' style='height:45px;display:none;'>\
|
||||
<span class='tname'>定时周期</span>\
|
||||
<div class='info-r c4'>\
|
||||
<select class='bt-input-text pull-left mr20' name='period' style='width:100px;'>\
|
||||
<option value='day' "+period_day+">每天</option>\
|
||||
<option value='minute-n' "+period_minute_n+">N分钟</option>\
|
||||
</select>\
|
||||
<div class='plan_hms pull-left mr20 bt-input-text hour'>\
|
||||
<span><input class='bt-input-text' type='number' name='hour' value='"+data["hour"]+"' maxlength='2' max='23' min='0'></span>\
|
||||
<span class='name'>小时</span>\
|
||||
</div>\
|
||||
<div class='plan_hms pull-left mr20 bt-input-text minute'>\
|
||||
<span><input class='bt-input-text' type='number' name='minute' value='"+data["minute"]+"' maxlength='2' max='59' min='0'></span>\
|
||||
<span class='name'>分钟</span>\
|
||||
</div>\
|
||||
<div class='plan_hms pull-left mr20 bt-input-text minute-n' style='display:none;'>\
|
||||
<span><input class='bt-input-text' type='number' name='minute-n' value='"+data["minute-n"]+"' maxlength='2' max='59' min='0'></span>\
|
||||
<span class='name'>分钟</span>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>限速</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input class='bt-input-text' type='number' name='bwlimit' min='0' value='1024' style='width:100px' /> KB\
|
||||
<span data-toggle='tooltip' data-placement='top' title='【限速】限制数据同步任务的速度,防止因同步数据导致带宽跑高' class='bt-ico-ask' style='cursor: pointer;'>?</span>\
|
||||
<span style='margin-left: 29px;margin-right: 10px;'>延迟</span><input class='bt-input-text' min='0' type='number' name='delay' value='3' style='width:100px' /> 秒\
|
||||
<span data-toggle='tooltip' data-placement='top' title='【延迟】在延迟时间周期内仅记录不同步,到达周期后一次性同步数据,以节省开销' class='bt-ico-ask' style='cursor: pointer;'>?</span>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>连接方式</span>\
|
||||
<div class='info-r c4'>\
|
||||
<select class='bt-input-text' name='conn_type' style='width:100px'>\
|
||||
<option value='key'>密钥</option>\
|
||||
<option value='user'>帐号</option>\
|
||||
</select>\
|
||||
<span style='margin-left: 45px;margin-right: 10px;'>压缩传输</span>\
|
||||
<select class='bt-input-text' name='compress' style='width:100px'>\
|
||||
<option value='true' "+compress_true+">开启</option>\
|
||||
<option value='false' "+compress_false+">关闭</option>\
|
||||
</select>\
|
||||
<span data-toggle='tooltip' data-placement='top' title='【压缩传输】开启后可减少带宽开销,但会增加CPU开销,如带宽充足,建议关闭此选项' class='bt-ico-ask' style='cursor: pointer;'>?</span>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line conn-key'>\
|
||||
<span class='tname'>接收密钥</span>\
|
||||
<div class='info-r c4'>\
|
||||
<textarea id='mainDomain' class='bt-input-text' name='secret_key' style='width:310px;height:75px;line-height:22px' placeholder='此密钥为 接收配置[接收账号] 的密钥'>"+data['secret_key']+"</textarea>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line conn-user'>\
|
||||
<span class='tname'>用户名</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input class='bt-input-text' type='text' name='u_user' min='0' value='"+data["name"]+"' style='width:310px' />\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line conn-user'>\
|
||||
<span class='tname'>密码</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input class='bt-input-text' type='text' name='u_pass' min='0' value='"+data["password"]+"' style='width:310px' />\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line conn-user'>\
|
||||
<span class='tname'>端口</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input class='bt-input-text' type='number' name='u_port' min='0' value='"+data["rsync"]["port"]+"' style='width:310px' />\
|
||||
</div>\
|
||||
</div>\
|
||||
<ul class=\"help-info-text c7\">\
|
||||
</ul>\
|
||||
</form>",
|
||||
success:function(){
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
$(".conn-user").hide();
|
||||
$("select[name='conn_type']").change(function(){
|
||||
if($(this).val() == 'key'){
|
||||
$(".conn-user").hide();
|
||||
$(".conn-key").show();
|
||||
}else{
|
||||
$(".conn-user").show();
|
||||
$(".conn-key").hide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var selVal = $('.synchronization option:selected').val();
|
||||
if (selVal == "false"){
|
||||
$('#period').show();
|
||||
}else{
|
||||
$('#period').hide();
|
||||
$('.hour input,.minute input').val('0');
|
||||
$('.minute-n input').val('1');
|
||||
}
|
||||
$('.synchronization').change(function(event) {
|
||||
var selVal = $('.synchronization option:selected').val();
|
||||
if (selVal == "false"){
|
||||
$('#period').show();
|
||||
}else{
|
||||
$('#period').hide();
|
||||
$('.hour input,.minute input').val('0');
|
||||
$('.minute-n input').val('1');
|
||||
}
|
||||
});
|
||||
|
||||
$("select[name='delete']").change(function(){
|
||||
if($(this).val() == 'true'){
|
||||
var mpath = $('input[name="path"]').val();
|
||||
var msg = '<div><span style="color:orangered;">警告:您选择了完全同步,将会使本机同步与目标机器指定目录的文件保持一致,'
|
||||
+'<br />请确认目录设置是否有误,一但设置错误,可能导致目标机器的目录文件被删除!</span>'
|
||||
+'<br /><br /> <span style="color:red;">注意: 同步程序将本机目录:'
|
||||
+mpath+'的所有数据同步到目标服务器,若目标服务器的同步目录存在其它文件将被删除!</span> <br /><br /> 已了解风险,请按确定继续</div>';
|
||||
|
||||
layer.confirm(msg,{title:'数据安全风险警告',icon:2,closeBtn: 1,shift: 5,
|
||||
btn2:function(){
|
||||
setTimeout(function(){$($("select[name='delete']").children("option")[0]).prop('selected',true);},100);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var selVal = $('#period select option:selected').val();
|
||||
if (selVal == 'day'){
|
||||
$('.hour,.minute').show();
|
||||
if ($('.hour input').val() == ''){
|
||||
$('.hour input,.minute input').val('0');
|
||||
}
|
||||
$('.minute-n').hide();
|
||||
}else{
|
||||
$('.hour,.minute').hide();
|
||||
$('.minute-n').show();
|
||||
if ($('.minute-n input').val() == ''){
|
||||
$('.minute-n input').val('1');
|
||||
}
|
||||
}
|
||||
$('#period').change(function(event) {
|
||||
var selVal = $('#period select option:selected').val();
|
||||
if (selVal == 'day'){
|
||||
$('.hour,.minute').show();
|
||||
if ($('.hour input').val() == ''){
|
||||
$('.hour input,.minute input').val('0');
|
||||
}
|
||||
$('.minute-n').hide();
|
||||
}else{
|
||||
$('.hour,.minute').hide();
|
||||
$('.minute-n').show();
|
||||
if ($('.minute-n input').val() == ''){
|
||||
$('.minute-n input').val('1');
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
yes:function(index){
|
||||
var args = {};
|
||||
var conn_type = $("select[name='conn_type']").val();
|
||||
|
||||
if(conn_type == 'key'){
|
||||
if ( $('textarea[name="secret_key"]').val() != ''){
|
||||
args['secret_key'] = $('textarea[name="secret_key"]').val();
|
||||
} else {
|
||||
layer.msg('请输入接收密钥!');
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
args['sname'] = $("input[name='u_user']").val();
|
||||
args['password'] = $("input[name='u_pass']").val();
|
||||
var port = Number($("input[name='u_port']").val());
|
||||
args['port'] = port;
|
||||
if (!args['sname'] || !args['password'] || !args['port']){
|
||||
layer.msg('请输入帐号、密码、端口信息');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($('input[name="ip"]').val() == ''){
|
||||
layer.msg('请输入服务器IP地址!');
|
||||
return false;
|
||||
}
|
||||
|
||||
args['sname'] = $("input[name='u_user']").val();
|
||||
args['password'] = $("input[name='u_pass']").val();
|
||||
var port = Number($("input[name='u_port']").val());
|
||||
args['port'] = port;
|
||||
|
||||
|
||||
args['ip'] = $('input[name="ip"]').val();
|
||||
args['path'] = $('input[name="path"]').val();
|
||||
args['delete'] = $('select[name="delete"]').val();
|
||||
args['realtime'] = $('select[name="realtime"]').val();
|
||||
args['delay'] = $('input[name="delay"]').val();
|
||||
|
||||
args['bwlimit'] = $('input[name="bwlimit"]').val();
|
||||
args['conn_type'] = $('select[name="conn_type"]').val();
|
||||
args['compress'] = $('select[name="compress"]').val();
|
||||
|
||||
args['period'] = $('select[name="period"]').val();
|
||||
args['hour'] = $('input[name="hour"]').val();
|
||||
args['minute'] = $('input[name="minute"]').val();
|
||||
args['minute-n'] = $('input[name="minute-n"]').val();
|
||||
|
||||
rsPost('lsyncd_add', args, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2,time:2000,shade: [0.3, '#000']});
|
||||
|
||||
if (rdata.status){
|
||||
setTimeout(function(){layer.close(index);},2000);
|
||||
return;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function lsyncdDelete(name){
|
||||
safeMessage('删除['+name+']', '您真的要删除['+name+']吗?', function(){
|
||||
var args = {};
|
||||
args['name'] = name;
|
||||
rsPost('lsyncd_delete', args, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2,time:2000,shade: [0.3, '#000']});
|
||||
setTimeout(function(){lsyncdSend();},2000);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function lsyncdRun(name){
|
||||
var args = {};
|
||||
args["name"] = name;
|
||||
rsPost('lsyncd_run', args, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2,time:2000,shade: [0.3, '#000']});
|
||||
});
|
||||
}
|
||||
|
||||
function lsyncdLog(name){
|
||||
var args = {};
|
||||
args["name"] = name;
|
||||
pluginStandAloneLogs("rsyncd", '', "lsyncd_log", JSON.stringify(args));
|
||||
}
|
||||
|
||||
|
||||
function lsyncdExclude(name){
|
||||
layer.open({
|
||||
type:1,
|
||||
title:'过滤器',
|
||||
area: '400px',
|
||||
shadeClose:false,
|
||||
closeBtn:2,
|
||||
content:'<div class="lsyncd_exclude">\
|
||||
<div style="overflow:hidden;">\
|
||||
<fieldset>\
|
||||
<legend>排除的文件和目录</legend>\
|
||||
<input type="text" class="bt-input-text mr5" data-type="exclude" title="例如:/home/www/" placeholder="例如:*.log" style="width:305px;">\
|
||||
<button data-type="exclude" class=" addList btn btn-default btn-sm">添加</button>\
|
||||
<div class="table-overflow">\
|
||||
<table class="table table-hover BlockList"><tbody></tbody></table>\
|
||||
</div>\
|
||||
</fieldset>\
|
||||
</div>\
|
||||
<div>\
|
||||
<ul class="help-info-text c7" style="list-style-type:decimal;">\
|
||||
<li>排除的文件和目录是指当前目录下不需要同步的目录或者文件</li>\
|
||||
<li>如果规则以斜线 <code>/</code>开头,则从头开始要匹配全部</li>\
|
||||
<li>如果规则以 <code>/</code>结尾,则要匹配监控路径的末尾</li>\
|
||||
<li><code>?</code> 匹配任何字符,但不包括<code>/</code></li>\
|
||||
<li><code>*</code> 匹配0或多个字符,但不包括<code>/</code></li>\
|
||||
<li><code>**</code> 匹配0或多个字符,可以是<code>/</code></li>\
|
||||
</ul>\
|
||||
</div>\
|
||||
</div>'
|
||||
});
|
||||
|
||||
function getIncludeExclude(mName){
|
||||
loadT = layer.msg('正在获取数据...',{icon:16,time:0,shade: [0.3, '#000']});
|
||||
rsPost('lsyncd_get_exclude',{"name":mName}, function(rdata) {
|
||||
layer.close(loadT);
|
||||
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
var res = rdata.data;
|
||||
|
||||
var list=''
|
||||
for (var i = 0; i < res.length; i++) {
|
||||
list += '<tr><td>'+ res[i] +'</td><td><a href="javascript:;" data-type='+ mName +' class="delList">删除</a></td></tr>';
|
||||
}
|
||||
$('.lsyncd_exclude .BlockList tbody').empty().append(list);
|
||||
});
|
||||
}
|
||||
getIncludeExclude(name);
|
||||
|
||||
|
||||
function addArgs(name,exclude){
|
||||
loadT = layer.msg('正在添加...',{icon:16,time:0,shade: [0.3, '#000']});
|
||||
rsPost('lsyncd_add_exclude', {name:name,exclude:exclude}, function(res){
|
||||
layer.close(loadT);
|
||||
|
||||
console.log('addArgs:',res);
|
||||
|
||||
if (res.status){
|
||||
getIncludeExclude(name);
|
||||
$('.lsyncd_exclude input').val('');
|
||||
layer.msg(res.msg);
|
||||
}else{
|
||||
layer.msg(res.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
$('.addList').click(function(event) {
|
||||
var val = $(this).prev().val();
|
||||
if(val == ''){
|
||||
layer.msg('当前输入内容为空,请输入');
|
||||
return false;
|
||||
}
|
||||
addArgs(name,val);
|
||||
});
|
||||
$('.lsyncd_exclude input').keyup(function(event){
|
||||
if (event.which == 13){
|
||||
var val = $(this).val();
|
||||
if(val == ''){
|
||||
layer.msg('当前输入内容为空,请输入');
|
||||
return false;
|
||||
}
|
||||
addArgs(name,val);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$('.lsyncd_exclude').on('click', '.delList', function(event) {
|
||||
loadT = layer.msg('正在删除...',{icon:16,time:0,shade: [0.3, '#000']});
|
||||
var val = $(this).parent().prev().text();
|
||||
rsPost('lsyncd_remove_exclude',{"name":name,exclude:val}, function(rdata) {
|
||||
layer.close(loadT);
|
||||
|
||||
console.log(rdata)
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
var res = rdata.data;
|
||||
|
||||
var list=''
|
||||
for (var i = 0; i < res.length; i++) {
|
||||
list += '<tr><td>'+ res[i] +'</td><td><a href="javascript:;" data-type='+ name +' class="delList">删除</a></td></tr>';
|
||||
}
|
||||
$('.lsyncd_exclude .BlockList tbody').empty().append(list);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function lsyncdConfLog(){
|
||||
pluginStandAloneLogs("rsyncd","","lsyncd_conf_log");;
|
||||
}
|
||||
|
||||
function lsyncdSend(){
|
||||
rsPost('lsyncd_list', '', function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
console.log(rdata);
|
||||
if (!rdata.status){
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
var list = rdata.data.list;
|
||||
var con = '';
|
||||
|
||||
con += '<div style="padding-top:1px;">\
|
||||
<button class="btn btn-success btn-sm" onclick="createSendTask();">创建发送任务</button>\
|
||||
<button class="btn btn-success btn-sm" onclick="lsyncdConfLog();">日志</button>\
|
||||
</div>';
|
||||
|
||||
con += '<div class="divtable" style="margin-top:5px;"><table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">';
|
||||
con += '<thead><tr>';
|
||||
con += '<th>名称(标识)</th>';
|
||||
con += '<th>源目录</th>';
|
||||
con += '<th>同步到</th>';
|
||||
con += '<th>模式</th>';
|
||||
con += '<th>周期</th>';
|
||||
con += '<th>操作</th>';
|
||||
con += '</tr></thead>';
|
||||
|
||||
con += '<tbody>';
|
||||
|
||||
|
||||
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var mode = '增量';
|
||||
if (list[i]['delete'] == 'true'){
|
||||
mode = '完全';
|
||||
} else {
|
||||
mode = '增量';
|
||||
}
|
||||
|
||||
var period = "实时";
|
||||
if (list[i]['realtime'] == 'true'){
|
||||
period = '实时';
|
||||
} else {
|
||||
period = '定时';
|
||||
}
|
||||
|
||||
con += '<tr>'+
|
||||
'<td>' + list[i]['name']+'</td>' +
|
||||
'<td><a class="btlink overflow_hide" style="width:40px;" onclick="openPath(\''+list[i]['path']+'\')">' + list[i]['path']+'</a></td>' +
|
||||
'<td>' + list[i]['ip']+":"+"cc"+'</td>' +
|
||||
'<td>' + mode+'</td>' +
|
||||
'<td>' + period +'</td>' +
|
||||
'<td>\
|
||||
<a class="btlink" onclick="lsyncdRun(\''+list[i]['name']+'\')">同步</a>\
|
||||
| <a class="btlink" onclick="lsyncdLog(\''+list[i]['name']+'\')">日志</a>\
|
||||
| <a class="btlink" onclick="lsyncdExclude(\''+list[i]['name']+'\')">过滤器</a>\
|
||||
| <a class="btlink" onclick="createSendTask(\''+list[i]['name']+'\')">编辑</a>\
|
||||
| <a class="btlink" onclick="lsyncdDelete(\''+list[i]['name']+'\')">删除</a>\
|
||||
</td>\
|
||||
</tr>';
|
||||
}
|
||||
|
||||
con += '</tbody>';
|
||||
con += '</table></div>';
|
||||
|
||||
$(".soft-man-con").html(con);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////// ----------------- 接收配置 ---------------- //////////////
|
||||
function rsyncdConf(){
|
||||
rsPost('conf', {}, function(rdata){
|
||||
rpath = rdata['data'];
|
||||
if (rdata['status']){
|
||||
onlineEditFile(0, rpath);
|
||||
} else {
|
||||
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function rsyncdLog(){
|
||||
pluginStandAloneLogs("rsyncd","","run_log");
|
||||
}
|
||||
|
||||
|
||||
function rsyncdReceive(){
|
||||
rsPost('rec_list', '', function(data){
|
||||
@@ -47,6 +583,12 @@ function rsyncdReceive(){
|
||||
// console.log(rdata);
|
||||
var list = rdata.data;
|
||||
var con = '';
|
||||
|
||||
con += '<div style="padding-top:1px;">\
|
||||
<button class="btn btn-success btn-sm" onclick="rsyncdConf();">配置</button>\
|
||||
<button class="btn btn-success btn-sm" onclick="rsyncdLog();">日志</button>\
|
||||
</div>';
|
||||
|
||||
con += '<div class="divtable" style="margin-top:5px;"><table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">';
|
||||
con += '<thead><tr>';
|
||||
con += '<th>服务名</th>';
|
||||
@@ -61,10 +603,12 @@ function rsyncdReceive(){
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
con += '<tr>'+
|
||||
'<td>' + list[i]['name']+'</td>' +
|
||||
'<td>' + list[i]['path']+'</td>' +
|
||||
'<td><a class="btlink overflow_hide" onclick="openPath(\''+list[i]['path']+'\')">' + list[i]['path']+'</a></td>' +
|
||||
'<td>' + list[i]['comment']+'</td>' +
|
||||
'<td>\
|
||||
<a class="btlink" onclick="cmdReceive(\''+list[i]['name']+'\')">命令</a>\
|
||||
<a class="btlink" onclick="cmdRecCmd(\''+list[i]['name']+'\')">命令</a>\
|
||||
| <a class="btlink" onclick="cmdRecSecretKey(\''+list[i]['name']+'\')">密钥</a>\
|
||||
| <a class="btlink" onclick="addReceive(\''+list[i]['name']+'\')">编辑</a>\
|
||||
| <a class="btlink" onclick="delReceive(\''+list[i]['name']+'\')">删除</a></td>\
|
||||
</tr>';
|
||||
}
|
||||
@@ -76,61 +620,67 @@ function rsyncdReceive(){
|
||||
});
|
||||
}
|
||||
|
||||
function addReceive(){
|
||||
var loadOpen = layer.open({
|
||||
type: 1,
|
||||
title: '创建接收',
|
||||
area: '400px',
|
||||
content:"<div class='bt-form pd20 pb70 c6'>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>项目名</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input id='name' class='bt-input-text' type='text' name='name' placeholder='项目名' style='width:200px' />\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>密钥</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input id='MyPassword' class='bt-input-text' type='text' name='pwd' placeholder='密钥' style='width:200px' />\
|
||||
<span title='随机密码' class='glyphicon glyphicon-repeat cursor' onclick='repeatPwd(16)'></span>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>同步到</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input id='inputPath' class='bt-input-text' type='text' name='path' placeholder='/' style='width:200px' />\
|
||||
<span class='glyphicon glyphicon-folder-open cursor' onclick=\"changePath('inputPath')\"></span>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>备注</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input id='ps' class='bt-input-text' type='text' name='ps' placeholder='备注' style='width:200px' />\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='bt-form-submit-btn'>\
|
||||
<button type='button' id='add_ok' class='btn btn-success btn-sm btn-title bi-btn'>确认</button>\
|
||||
</div>\
|
||||
</div>",
|
||||
success:function(layero, index){
|
||||
repeatPwd(16);
|
||||
}
|
||||
});
|
||||
|
||||
$('#add_ok').click(function(){
|
||||
_data = {};
|
||||
_data['name'] = $('#name').val();
|
||||
_data['pwd'] = $('#MyPassword').val();
|
||||
_data['path'] = $('#inputPath').val();
|
||||
_data['ps'] = $('#ps').val();
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
rsPost('add_rec', _data, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
layer.close(loadOpen);
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2,time:2000,shade: [0.3, '#000']});
|
||||
setTimeout(function(){rsyncdReceive();},2000);
|
||||
function addReceive(name = ""){
|
||||
rsPost('get_rec',{"name":name},function(rdata) {
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
var data = rdata.data;
|
||||
|
||||
var readonly = "";
|
||||
if (name !=""){
|
||||
readonly = 'readonly="readonly"'
|
||||
}
|
||||
|
||||
var loadOpen = layer.open({
|
||||
type: 1,
|
||||
title: '创建接收',
|
||||
area: '400px',
|
||||
btn:['确认','取消'],
|
||||
content:"<div class='bt-form pd20 c6'>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>项目名</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input id='name' value='"+data["name"]+"' class='bt-input-text' type='text' name='name' placeholder='项目名' style='width:200px' "+readonly+"/>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>密钥</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input id='MyPassword' value='"+data["pwd"]+"' class='bt-input-text' type='text' name='pwd' placeholder='密钥' style='width:200px'/>\
|
||||
<span title='随机密码' class='glyphicon glyphicon-repeat cursor' onclick='repeatPwd(16)'></span>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>同步到</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input id='inputPath' value='"+data["path"]+"' class='bt-input-text' type='text' name='path' placeholder='/' style='width:200px'/>\
|
||||
<span class='glyphicon glyphicon-folder-open cursor' onclick=\"changePath('inputPath')\"></span>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>备注</span>\
|
||||
<div class='info-r c4'>\
|
||||
<input id='ps' class='bt-input-text' type='text' name='ps' value='"+data["comment"]+"' placeholder='备注' style='width:200px'/>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>",
|
||||
success:function(layero, index){},
|
||||
yes:function(){
|
||||
var args = {};
|
||||
args['name'] = $('#name').val();
|
||||
args['pwd'] = $('#MyPassword').val();
|
||||
args['path'] = $('#inputPath').val();
|
||||
args['ps'] = $('#ps').val();
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
rsPost('add_rec', args, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
layer.close(loadOpen);
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2,time:2000,shade: [0.3, '#000']});
|
||||
setTimeout(function(){rsyncdReceive();},2000);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -146,20 +696,34 @@ function delReceive(name){
|
||||
});
|
||||
}
|
||||
|
||||
function cmdReceive(name){
|
||||
function cmdRecSecretKey(name){
|
||||
var _data = {};
|
||||
_data['name'] = name;
|
||||
rsPost('cmd_rec', _data, function(data){
|
||||
rsPost('cmd_rec_secret_key', _data, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: '命令事例',
|
||||
title: '接收密钥',
|
||||
area: '400px',
|
||||
content:"<div class='bt-form pd20 pb70 c6'>"+rdata.data+"</div>"
|
||||
content:"<div class='bt-form pd20 pb70 c6'><textarea class='form-control' rows='6' readonly='readonly'>"+rdata.data+"</textarea></div>"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function cmdRecCmd(name){
|
||||
var _data = {};
|
||||
_data['name'] = name;
|
||||
rsPost('cmd_rec_cmd', _data, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: '接收命令例子',
|
||||
area: '400px',
|
||||
content:"<div class='bt-form pd20 pb70 c6'>"+rdata.data+"</div>"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function rsRead(){
|
||||
var readme = '<ul class="help-info-text c7">';
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
# coding:utf-8
|
||||
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import mw
|
||||
|
||||
|
||||
app_debug = False
|
||||
if mw.isAppleSystem():
|
||||
app_debug = True
|
||||
|
||||
|
||||
def getPluginName():
|
||||
return 'rsyncd'
|
||||
|
||||
|
||||
def getPluginDir():
|
||||
return mw.getPluginDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getServerDir():
|
||||
return mw.getServerDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getTaskConf():
|
||||
conf = getServerDir() + "/task_config.json"
|
||||
return conf
|
||||
|
||||
|
||||
def getConfigData():
|
||||
try:
|
||||
return json.loads(mw.readFile(getTaskConf()))
|
||||
except:
|
||||
pass
|
||||
return []
|
||||
|
||||
|
||||
def getConfigTpl():
|
||||
tpl = {
|
||||
"name": "",
|
||||
"task_id": -1,
|
||||
}
|
||||
return tpl
|
||||
|
||||
|
||||
def createBgTask(data):
|
||||
removeBgTask()
|
||||
for d in data:
|
||||
if d['realtime'] == "false":
|
||||
createBgTaskByName(d['name'], d)
|
||||
|
||||
|
||||
def createBgTaskByName(name, args):
|
||||
cfg = getConfigTpl()
|
||||
_name = "[勿删]同步插件定时任务[" + name + "]"
|
||||
res = mw.M("crontab").field("id, name").where("name=?", (_name,)).find()
|
||||
if res:
|
||||
return True
|
||||
|
||||
if "task_id" in cfg.keys() and cfg["task_id"] > 0:
|
||||
res = mw.M("crontab").field("id, name").where(
|
||||
"id=?", (cfg["task_id"],)).find()
|
||||
if res and res["id"] == cfg["task_id"]:
|
||||
print("计划任务已经存在!")
|
||||
return True
|
||||
import crontab_api
|
||||
api = crontab_api.crontab_api()
|
||||
|
||||
period = args['period']
|
||||
_hour = ''
|
||||
_minute = ''
|
||||
_where1 = ''
|
||||
_type_day = "day"
|
||||
if period == 'day':
|
||||
_type_day = 'day'
|
||||
_hour = args['hour']
|
||||
_minute = args['minute']
|
||||
elif period == 'minute-n':
|
||||
_type_day = 'minute-n'
|
||||
_where1 = args['minute-n']
|
||||
_minute = ''
|
||||
|
||||
cmd = '''
|
||||
rname=%s
|
||||
plugin_path=%s
|
||||
logs_file=$plugin_path/send/${rname}/run.log
|
||||
''' % (name, getServerDir())
|
||||
cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT" >> $logs_file' + "\n"
|
||||
cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n"
|
||||
cmd += 'bash $plugin_path/send/${rname}/cmd >> $logs_file 2>&1' + "\n"
|
||||
cmd += 'echo "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n"
|
||||
cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n"
|
||||
|
||||
params = {
|
||||
'name': _name,
|
||||
'type': _type_day,
|
||||
'week': "",
|
||||
'where1': _where1,
|
||||
'hour': _hour,
|
||||
'minute': _minute,
|
||||
'save': "",
|
||||
'backup_to': "",
|
||||
'stype': "toShell",
|
||||
'sname': '',
|
||||
'sbody': cmd,
|
||||
'urladdress': '',
|
||||
}
|
||||
|
||||
task_id = api.add(params)
|
||||
if task_id > 0:
|
||||
cfg["task_id"] = task_id
|
||||
cfg["name"] = name
|
||||
|
||||
_dd = getConfigData()
|
||||
_dd.append(cfg)
|
||||
mw.writeFile(getTaskConf(), json.dumps(_dd))
|
||||
|
||||
|
||||
def removeBgTask():
|
||||
cfg_list = getConfigData()
|
||||
for x in range(len(cfg_list)):
|
||||
cfg = cfg_list[x]
|
||||
if "task_id" in cfg.keys() and cfg["task_id"] > 0:
|
||||
res = mw.M("crontab").field("id, name").where(
|
||||
"id=?", (cfg["task_id"],)).find()
|
||||
if res and res["id"] == cfg["task_id"]:
|
||||
import crontab_api
|
||||
api = crontab_api.crontab_api()
|
||||
data = api.delete(cfg["task_id"])
|
||||
if data[0]:
|
||||
cfg["task_id"] = -1
|
||||
cfg_list[x] = cfg
|
||||
mw.writeFile(getTaskConf(), '[]')
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
action = sys.argv[1]
|
||||
if action == "remove":
|
||||
removeBgTask()
|
||||
elif action == "add":
|
||||
createBgTask()
|
||||
+22
-19
@@ -988,29 +988,32 @@ def getIpStatList():
|
||||
if ip == "127.0.0.1":
|
||||
clist[i]['area'] = "本地"
|
||||
elif geoip_exists:
|
||||
response = reader.city(ip)
|
||||
country = response.country.names["zh-CN"]
|
||||
|
||||
# print(ip, response.subdivisions)
|
||||
_subdivisions = response.subdivisions
|
||||
try:
|
||||
if len(_subdivisions) < 1:
|
||||
response = reader.city(ip)
|
||||
country = response.country.names["zh-CN"]
|
||||
|
||||
# print(ip, response.subdivisions)
|
||||
_subdivisions = response.subdivisions
|
||||
try:
|
||||
if len(_subdivisions) < 1:
|
||||
subdivisions = ""
|
||||
else:
|
||||
subdivisions = "," + response.subdivisions.most_specific.names[
|
||||
"zh-CN"]
|
||||
except Exception as e:
|
||||
subdivisions = ""
|
||||
else:
|
||||
subdivisions = "," + response.subdivisions.most_specific.names[
|
||||
"zh-CN"]
|
||||
except Exception as e:
|
||||
subdivisions = ""
|
||||
|
||||
try:
|
||||
if 'zh-CN' in response.city.names:
|
||||
city = "," + response.city.names["zh-CN"]
|
||||
else:
|
||||
city = "," + response.city.names["en"]
|
||||
except Exception as e:
|
||||
city = ""
|
||||
try:
|
||||
if 'zh-CN' in response.city.names:
|
||||
city = "," + response.city.names["zh-CN"]
|
||||
else:
|
||||
city = "," + response.city.names["en"]
|
||||
except Exception as e:
|
||||
city = ""
|
||||
|
||||
clist[i]['area'] = country + subdivisions + city
|
||||
clist[i]['area'] = country + subdivisions + city
|
||||
except Exception as e:
|
||||
clist[i]['area'] = "内网?"
|
||||
|
||||
return mw.returnJson(True, 'ok', clist)
|
||||
|
||||
|
||||
@@ -1996,8 +1996,8 @@ function wsTableErrorLogRequest(page){
|
||||
list += '<td><span class="overflow_hide" style="width:100px;">' + data[i]['ip'] +'</span></td>';
|
||||
list += '<td>' + toSize(data[i]['body_length']) +'</td>';
|
||||
list += '<td>' + toSecond(data[i]['request_time']) +'</td>';
|
||||
list += '<td><span class="overflow_hide" style="width:150px;">' + data[i]['uri'] +'</span></td>';
|
||||
list += '<td>' + data[i]['status_code']+'/' + data[i]['method'] +'</td>';
|
||||
list += '<td><span class="overflow_hide" style="width:130px;">' + data[i]['uri'] +'</span></td>';
|
||||
list += '<td><span class="overflow_hide" style="width:60px;">' + data[i]['status_code']+'/' + data[i]['method'] +'</span></td>';
|
||||
list += '<td><a data-id="'+i+'" href="javascript:;" class="btlink details" title="详情">详情</a></td>';
|
||||
list += '</tr>';
|
||||
}
|
||||
@@ -2205,8 +2205,8 @@ function wsTableLogRequest(page){
|
||||
list += '<td><span class="overflow_hide" style="width:100px;">' + data[i]['ip'] +'</span></td>';
|
||||
list += '<td>' + toSize(data[i]['body_length']) +'</td>';
|
||||
list += '<td>' + toSecond(data[i]['request_time']) +'</td>';
|
||||
list += '<td><span class="overflow_hide" style="width:150px;">' + data[i]['uri'] +'</span></td>';
|
||||
list += '<td>' + data[i]['status_code']+'/' + data[i]['method'] +'</td>';
|
||||
list += '<td><span class="overflow_hide" style="width:130px;">' + data[i]['uri'] +'</span></td>';
|
||||
list += '<td><span class="overflow_hide" style="width:60px;">' + data[i]['status_code']+'/' + data[i]['method'] +'</span></td>';
|
||||
list += '<td><a data-id="'+i+'" href="javascript:;" class="btlink details" title="详情">详情</a></td>';
|
||||
list += '</tr>';
|
||||
}
|
||||
|
||||
@@ -174,6 +174,12 @@ log_by_lua_block {
|
||||
return count
|
||||
end
|
||||
|
||||
local function split_bylog(str,reps )
|
||||
local resultStrList = {}
|
||||
string.gsub(str,'[^'..reps..']+',function(w) table.insert(resultStrList,w) end)
|
||||
return resultStrList
|
||||
end
|
||||
|
||||
local function is_ipaddr_bylog(client_ip)
|
||||
local cipn = split_bylog(client_ip,'.')
|
||||
if arrlen_bylog(cipn) < 4 then return false end
|
||||
@@ -186,12 +192,6 @@ log_by_lua_block {
|
||||
return true
|
||||
end
|
||||
|
||||
local function split_bylog(str,reps )
|
||||
local resultStrList = {}
|
||||
string.gsub(str,'[^'..reps..']+',function(w) table.insert(resultStrList,w) end)
|
||||
return resultStrList
|
||||
end
|
||||
|
||||
local function get_client_ip_bylog()
|
||||
local client_ip = "unknown"
|
||||
local cdn = auto_config['cdn']
|
||||
|
||||
@@ -66,7 +66,9 @@ def pSqliteDb(dbname='web_logs', site_name='unset', fn="logs"):
|
||||
conn.execute("PRAGMA page_size = 4096", ())
|
||||
conn.execute("PRAGMA journal_mode = wal", ())
|
||||
|
||||
conn.text_factory = lambda x: str(x, encoding="utf-8", errors='ignore')
|
||||
conn.autoTextFactory()
|
||||
|
||||
# conn.text_factory = lambda x: str(x, encoding="utf-8", errors='ignore')
|
||||
# conn.text_factory = lambda x: unicode(x, "utf-8", "ignore")
|
||||
return conn
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ def createBgTask():
|
||||
import crontab_api
|
||||
api = crontab_api.crontab_api()
|
||||
|
||||
cmd = "nice -n 10 python3 " + getPluginDir() + "/tool_task.py execute"
|
||||
cmd = "cd " + mw.getServerDir() + "/mdserver-web && nice -n 10 python3 " + \
|
||||
getPluginDir() + "/tool_task.py execute"
|
||||
params = {
|
||||
'name': name,
|
||||
'type': 'day',
|
||||
|
||||
@@ -6,7 +6,7 @@ server
|
||||
root {$SERVER_PATH}/xhprof/xhprof_html;
|
||||
|
||||
#error_page 404 /404.html;
|
||||
include enable-php-{$PHP_VER}.conf;
|
||||
include {$SERVER_PATH}/web_conf/php/conf/enable-php-{$PHP_VER}.conf;
|
||||
|
||||
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
|
||||
{
|
||||
|
||||
@@ -2031,6 +2031,50 @@ function pluginRollingLogs(_name, version, func, _args, line){
|
||||
},1000);
|
||||
},'json');
|
||||
}
|
||||
|
||||
|
||||
function pluginStandAloneLogs(_name, version, func, _args, line){
|
||||
if ( typeof(version) == 'undefined' ){
|
||||
version = '';
|
||||
}
|
||||
|
||||
var func_name = 'error_log';
|
||||
if ( typeof(func) != 'undefined' ){
|
||||
func_name = func;
|
||||
}
|
||||
|
||||
var file_line = 100;
|
||||
if ( typeof(line) != 'undefined' ){
|
||||
file_line = line;
|
||||
}
|
||||
|
||||
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: _name + '日志',
|
||||
area: '640px',
|
||||
content:'<div class="change-default pd20" id="plugins_stand_alone_logs">\
|
||||
<textarea readonly="readonly" style="margin: 0px;width: 100%;height: 360px;background-color: #333;color:#fff; padding:0 5px"></textarea>\
|
||||
</div>'
|
||||
});
|
||||
|
||||
$.post('/plugins/run', {name:_name, func:func_name, version:version,args:_args},function (data) {
|
||||
var fileName = data.data;
|
||||
$.post('/files/get_last_body', 'path=' + fileName+'&line='+file_line, function(rdata) {
|
||||
if (!rdata.status){
|
||||
return;
|
||||
}
|
||||
|
||||
if(rdata.data == '') {
|
||||
rdata.data = '当前没有日志!';
|
||||
}
|
||||
var ebody = '<textarea readonly="" style="margin: 0px;width: 100%;height: 360px;background-color: #333;color:#fff; padding:0 5px">'+rdata.data+'</textarea>';
|
||||
$("#plugins_stand_alone_logs").html(ebody);
|
||||
var ob = document.getElementById('plugins_stand_alone_logs');
|
||||
ob.scrollTop = ob.scrollHeight;
|
||||
},'json');
|
||||
},'json');
|
||||
}
|
||||
/*** 其中功能,针对插件通过库使用 end ***/
|
||||
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div class="ss-text pull-left mr50">
|
||||
<em class="btlink" style="color: #20a53a;" onclick="getPanelSSL()" title="点击自定义面板证书">面板SSL</em>
|
||||
<div class='ssh-item'>
|
||||
@@ -33,6 +34,7 @@
|
||||
<label class='btswitch-btn' for='panelSSL' onclick="setPanelSSL()"></label>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="setbox bgw mtb15">
|
||||
@@ -60,11 +62,14 @@
|
||||
<input id="admin_path" name="admin_path" class="inputtxt bt-input-text disable" type="text" value="{{data['admin_path']}}"><span class="modify btn btn-xs btn-success" onclick="modifyAuthPath();">修改</span>
|
||||
<span class="set-info c7">面板管理入口,设置后只能通过指定安全入口登录面板,如: /abc</span>
|
||||
</p>
|
||||
|
||||
<!--
|
||||
<p class="mtb15">
|
||||
<span class="set-tit text-right">域名</span>
|
||||
<input name="domain" class="inputtxt bt-input-text" type="text" value="">
|
||||
<span class="set-info c7">为面板绑定一个访问域名;注意:一旦绑定域名,只能通过域名访问面板!</span>
|
||||
</p>
|
||||
-->
|
||||
|
||||
<p class="mtb15">
|
||||
<span class="set-tit text-right" title="默认建站目录">默认建站目录</span>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="renderer" content="webkit">
|
||||
<title>mdserver-web|linux面板</title>
|
||||
<title>{{data['title']}}</title>
|
||||
<link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon" />
|
||||
<link href="/static/bootstrap-3.3.5/css/bootstrap.min.css?v={{config.version}}" rel="stylesheet">
|
||||
<link href="/static/css/site.css?v={{config.version}}" rel="stylesheet">
|
||||
|
||||
+2
-2
@@ -115,7 +115,7 @@ pip3 install gevent-websocket==0.10.1
|
||||
pip3 install flask-caching==1.10.1
|
||||
pip3 install flask-session==0.3.2
|
||||
pip3 install flask-socketio==5.2.0
|
||||
# pip3 install mysqlclient
|
||||
pip3 install mysqlclient
|
||||
|
||||
|
||||
if [ ! -f /www/server/mdserver-web/bin/activate ];then
|
||||
@@ -133,5 +133,5 @@ pip3 install gevent-websocket==0.10.1
|
||||
pip3 install flask-caching==1.10.1
|
||||
pip3 install flask-session==0.3.2
|
||||
pip3 install flask-socketio==5.2.0
|
||||
# pip3 install mysqlclient
|
||||
pip3 install mysqlclient
|
||||
|
||||
|
||||
Reference in New Issue
Block a user