@@ -16,8 +83,12 @@
\ No newline at end of file
diff --git a/plugins/rsyncd/index.py b/plugins/rsyncd/index.py
index d5be125c5..d1fb9f91e 100755
--- a/plugins/rsyncd/index.py
+++ b/plugins/rsyncd/index.py
@@ -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 delRec():
+def getRec():
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)
+ name = args['name']
- try:
+ 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)
- ret_list = getRecListData()
- ret_list_len = len(ret_list)
+ reclist = getRecListData()
+ ret_list_len = len(reclist)
is_end = False
next_name = ''
for x in range(ret_list_len):
- tmp = ret_list[x]
- if tmp['name'] == args_name:
+ 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 = ret_list[x + 1]['name']
+ next_name = reclist[x + 1]['name']
reg = ''
if is_end:
- reg = '\[' + args_name + '\]\s*(.*)'
+ reg = '\[' + name + '\]\s*(.*)'
else:
- reg = '\[' + args_name + '\]\s*(.*)\s*\[' + next_name + '\]'
+ reg = '\[' + name + '\]\s*(.*)\s*\[' + next_name + '\]'
conre = re.search(reg, content, re.S)
content = content.replace(
- "[" + args_name + "]\n" + conre.groups()[0], '')
+ "[" + name + "]\n" + conre.groups()[0], '')
mw.writeFile(path, content)
- return mw.returnJson(True, '删除成功!')
except Exception as e:
- return mw.returnJson(False, '删除失败!')
+ return False
+ return True
-def cmdRec():
+def delRec():
args = getArgs()
data = checkArgs(args, ['name'])
if not data[0]:
return data[1]
+ name = args['name']
+ ok = delRecBy(name)
+ if ok:
+ return mw.returnJson(True, '删除成功!')
+ return mw.returnJson(False, '删除失败!')
- an = args['name']
- pwd_list = getUPwdList()
+
+def cmdRecSecretKey():
+ import base64
+
+ args = getArgs()
+ data = checkArgs(args, ['name'])
+ if not data[0]:
+ return data[1]
+
+ name = args['name']
+ info = getRecListDataBy(name)
+
+ 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)
+
+
+def cmdRecCmd():
+ args = getArgs()
+ data = checkArgs(args, ['name'])
+ if not data[0]:
+ return data[1]
+
+ name = args['name']
+ info = getRecListDataBy(name)
ip = mw.getLocalIp()
- cmd = 'echo "' + pwd_list[an] + '" > /tmp/p.pass' + "
"
- cmd += 'chmod 600 /tmp/p.pass' + "
"
- cmd += 'rsync -arv --password-file=/tmp/p.pass --progress --delete /project ' + \
- an + '@' + ip + '::' + an
+ content = mw.readFile(info['secrets file'])
+ pwd = content.strip().split(":")
+
+ tmp_name = '/tmp/' + name + '.pass'
+
+ cmd = 'echo "' + pwd[1] + '" > ' + tmp_name + '
'
+ cmd += 'chmod 600 ' + tmp_name + '
'
+ cmd += 'rsync -arv --password-file=' + tmp_name + \
+ ' --progress --delete /project ' + name + '@' + ip + '::' + name
return mw.returnJson(True, 'OK!', cmd)
-# rsyncdReceive
+
+# ----------------------------- 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')
diff --git a/plugins/rsyncd/info.json b/plugins/rsyncd/info.json
index c23d4247b..3ab33843a 100755
--- a/plugins/rsyncd/info.json
+++ b/plugins/rsyncd/info.json
@@ -5,7 +5,7 @@
"name":"rsyncd",
"type":"软件",
"ps":"rsyncd同步助手",
- "versions":"1.0",
+ "versions":"2.0",
"shell":"install.sh",
"checks":"server/rsyncd",
"path": "server/rsyncd",
diff --git a/plugins/rsyncd/init.d/lsyncd.service.tpl b/plugins/rsyncd/init.d/lsyncd.service.tpl
new file mode 100755
index 000000000..7c6a03c60
--- /dev/null
+++ b/plugins/rsyncd/init.d/lsyncd.service.tpl
@@ -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
diff --git a/plugins/rsyncd/init.d/lsyncd.tpl b/plugins/rsyncd/init.d/lsyncd.tpl
new file mode 100755
index 000000000..a5ccdcad6
--- /dev/null
+++ b/plugins/rsyncd/init.d/lsyncd.tpl
@@ -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
diff --git a/plugins/rsyncd/install.sh b/plugins/rsyncd/install.sh
index bf574b182..cd46f0902 100755
--- a/plugins/rsyncd/install.sh
+++ b/plugins/rsyncd/install.sh
@@ -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
}
diff --git a/plugins/rsyncd/js/base64.js b/plugins/rsyncd/js/base64.js
new file mode 100644
index 000000000..4a5caa2a7
--- /dev/null
+++ b/plugins/rsyncd/js/base64.js
@@ -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;
+}
\ No newline at end of file
diff --git a/plugins/rsyncd/js/rsyncd.js b/plugins/rsyncd/js/rsyncd.js
index ae8d2d9a8..e70a76e54 100755
--- a/plugins/rsyncd/js/rsyncd.js
+++ b/plugins/rsyncd/js/rsyncd.js
@@ -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:"
",
+ 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 = '
警告:您选择了完全同步,将会使本机同步与目标机器指定目录的文件保持一致,'
+ +'
请确认目录设置是否有误,一但设置错误,可能导致目标机器的目录文件被删除!'
+ +'
注意: 同步程序将本机目录:'
+ +mpath+'的所有数据同步到目标服务器,若目标服务器的同步目录存在其它文件将被删除!
已了解风险,请按确定继续
';
+
+ 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:'
\
+
\
+
\
+
\
+ - 排除的文件和目录是指当前目录下不需要同步的目录或者文件
\
+ - 如果规则以斜线
/
开头,则从头开始要匹配全部 \
+ - 如果规则以
/
结尾,则要匹配监控路径的末尾 \
+ ?
匹配任何字符,但不包括/
\
+ *
匹配0或多个字符,但不包括/
\
+ **
匹配0或多个字符,可以是/
\
+
\
+
\
+
'
+ });
+
+ 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 += '
'+ res[i] +' | 删除 |
';
+ }
+ $('.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 += '
'+ res[i] +' | 删除 |
';
+ }
+ $('.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 += '
\
+ \
+ \
+
';
+
+ con += '
';
+ con += '';
+ con += '名称(标识) | ';
+ con += '源目录 | ';
+ con += '同步到 | ';
+ con += '模式 | ';
+ con += '周期 | ';
+ con += '操作 | ';
+ con += '
';
+
+ con += '';
+
+
+
+ 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 += ''+
+ '' + list[i]['name']+' | ' +
+ '' + list[i]['path']+' | ' +
+ '' + list[i]['ip']+":"+"cc"+' | ' +
+ '' + mode+' | ' +
+ '' + period +' | ' +
+ '\
+ 同步\
+ | 日志\
+ | 过滤器\
+ | 编辑\
+ | 删除\
+ | \
+
';
+ }
+
+ con += '';
+ con += '
';
+
+ $(".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 += '
\
+ \
+ \
+
';
+
con += '
';
con += '';
con += '服务名 | ';
@@ -61,10 +603,12 @@ function rsyncdReceive(){
for (var i = 0; i < list.length; i++) {
con += '
'+
'' + list[i]['name']+' | ' +
- '' + list[i]['path']+' | ' +
+ '' + list[i]['path']+' | ' +
'' + list[i]['comment']+' | ' +
'\
- 命令\
+ 命令\
+ | 密钥\
+ | 编辑\
| 删除 | \
';
}
@@ -76,61 +620,67 @@ function rsyncdReceive(){
});
}
-function addReceive(){
- var loadOpen = layer.open({
- type: 1,
- title: '创建接收',
- area: '400px',
- content:"",
- success:function(layero, index){
- repeatPwd(16);
+
+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"'
}
- });
- $('#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);
+ var loadOpen = layer.open({
+ type: 1,
+ title: '创建接收',
+ area: '400px',
+ btn:['确认','取消'],
+ content:"",
+ 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:""+rdata.data+"
"
+ content:""
});
});
}
+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:""+rdata.data+"
"
+ });
+ });
+}
+
function rsRead(){
var readme = '';
diff --git a/plugins/rsyncd/tool_task.py b/plugins/rsyncd/tool_task.py
new file mode 100644
index 000000000..0d332ea9b
--- /dev/null
+++ b/plugins/rsyncd/tool_task.py
@@ -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()
diff --git a/plugins/webstats/index.py b/plugins/webstats/index.py
index fea2ca39d..fd9d4c44a 100755
--- a/plugins/webstats/index.py
+++ b/plugins/webstats/index.py
@@ -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)
diff --git a/plugins/webstats/js/stats.js b/plugins/webstats/js/stats.js
index 33b8c71e8..8dcb67931 100644
--- a/plugins/webstats/js/stats.js
+++ b/plugins/webstats/js/stats.js
@@ -1996,8 +1996,8 @@ function wsTableErrorLogRequest(page){
list += '' + data[i]['ip'] +' | ';
list += '' + toSize(data[i]['body_length']) +' | ';
list += '' + toSecond(data[i]['request_time']) +' | ';
- list += '' + data[i]['uri'] +' | ';
- list += '' + data[i]['status_code']+'/' + data[i]['method'] +' | ';
+ list += '' + data[i]['uri'] +' | ';
+ list += '' + data[i]['status_code']+'/' + data[i]['method'] +' | ';
list += '详情 | ';
list += '';
}
@@ -2205,8 +2205,8 @@ function wsTableLogRequest(page){
list += '' + data[i]['ip'] +' | ';
list += '' + toSize(data[i]['body_length']) +' | ';
list += '' + toSecond(data[i]['request_time']) +' | ';
- list += '' + data[i]['uri'] +' | ';
- list += '' + data[i]['status_code']+'/' + data[i]['method'] +' | ';
+ list += '' + data[i]['uri'] +' | ';
+ list += '' + data[i]['status_code']+'/' + data[i]['method'] +' | ';
list += '详情 | ';
list += '';
}
diff --git a/plugins/webstats/lua/webstats_log.lua b/plugins/webstats/lua/webstats_log.lua
index 5ece00bf5..78732f005 100644
--- a/plugins/webstats/lua/webstats_log.lua
+++ b/plugins/webstats/lua/webstats_log.lua
@@ -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']
diff --git a/plugins/webstats/tool_migrate.py b/plugins/webstats/tool_migrate.py
index 5d6499f29..88aede22b 100644
--- a/plugins/webstats/tool_migrate.py
+++ b/plugins/webstats/tool_migrate.py
@@ -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
diff --git a/plugins/webstats/tool_task.py b/plugins/webstats/tool_task.py
index d2ab34fdf..fe129ee31 100644
--- a/plugins/webstats/tool_task.py
+++ b/plugins/webstats/tool_task.py
@@ -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',
diff --git a/plugins/xhprof/conf/xhprof.conf b/plugins/xhprof/conf/xhprof.conf
index bdc8095d5..92df8fb24 100755
--- a/plugins/xhprof/conf/xhprof.conf
+++ b/plugins/xhprof/conf/xhprof.conf
@@ -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)$
{
diff --git a/route/static/app/public.js b/route/static/app/public.js
index 5e672e8c9..6063fa656 100755
--- a/route/static/app/public.js
+++ b/route/static/app/public.js
@@ -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:'\
+ \
+
'
+ });
+
+ $.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 = '';
+ $("#plugins_stand_alone_logs").html(ebody);
+ var ob = document.getElementById('plugins_stand_alone_logs');
+ ob.scrollTop = ob.scrollHeight;
+ },'json');
+ },'json');
+}
/*** 其中功能,针对插件通过库使用 end ***/
diff --git a/route/templates/default/config.html b/route/templates/default/config.html
index 5f7e5d7aa..8ada07c7a 100755
--- a/route/templates/default/config.html
+++ b/route/templates/default/config.html
@@ -26,6 +26,7 @@
+
@@ -60,11 +62,14 @@
修改
面板管理入口,设置后只能通过指定安全入口登录面板,如: /abc
+
+
默认建站目录
diff --git a/route/templates/default/layout.html b/route/templates/default/layout.html
index cdb4a7a8b..b14187021 100755
--- a/route/templates/default/layout.html
+++ b/route/templates/default/layout.html
@@ -5,7 +5,7 @@
-
mdserver-web|linux面板
+
{{data['title']}}
diff --git a/scripts/lib.sh b/scripts/lib.sh
index 19e558357..6535b65aa 100755
--- a/scripts/lib.sh
+++ b/scripts/lib.sh
@@ -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