rust.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. import os
  2. import sys
  3. import json
  4. import stat
  5. import time
  6. import socket
  7. import shutil
  8. import base64
  9. import linecache #读取日志文件
  10. import requests
  11. import threading #多线程
  12. import subprocess
  13. import traceback #输出报错
  14. """
  15. 接受Web指令,上传日志
  16. """
  17. def printf(*args):
  18. print('[-]', time.strftime("%H:%M:%S", time.localtime()),'',*args)
  19. """ 判断端口是否开启"""
  20. def is_port_open(ip, port):
  21. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  22. try:
  23. s.connect((ip, int(port)))
  24. s.shutdown(socket.SHUT_RDWR)
  25. return True
  26. except Exception as e:
  27. pass
  28. return False
  29. """ 放入缓存防止内存过载"""
  30. def get_line_count(filename):
  31. count = 0
  32. with open(filename, 'r') as f:
  33. while True:
  34. buffer = f.read(1024 * 1)
  35. if not buffer:
  36. break
  37. count += buffer.count('\n')
  38. return count
  39. """ 每隔N秒实现"""
  40. Log_time = {}
  41. def tlog(data, xsTime, set=0, look=0):
  42. global Log_Time
  43. if data not in Log_time.keys():
  44. Log_time[data] = 0
  45. nowTime = int(time.time())
  46. if nowTime - Log_time[data] >= xsTime:
  47. if not look:
  48. Log_time[data] = nowTime
  49. return 1
  50. elif set:
  51. Log_time[data] = nowTime
  52. return 0
  53. ''' 获取本地ip'''
  54. def get_local_ip_list():
  55. import netifaces as ni
  56. ipList = []
  57. # print('检测服务器网络配置')
  58. for dev in ni.interfaces():
  59. print('dev:',dev)
  60. if 'ens' in dev or 'eth' in dev or 'enp' in dev:
  61. # print(ni.ifaddresses(dev))
  62. for i in ni.ifaddresses(dev)[2]:
  63. ip=i['addr']
  64. print(f"检测到私有ip:{ip}")
  65. if ip not in ipList:
  66. ipList.append(ip)
  67. print(f"当前服务器私有ip为{ipList}")
  68. return ipList
  69. """文件写入内容"""
  70. def write(filePath, data):
  71. if "/" in filePath or "\\" in filePath:
  72. dirPath = os.path.dirname(filePath)
  73. if not os.path.exists(dirPath):
  74. os.makedirs(dirPath)
  75. try:
  76. f = open(filePath, 'wb+') if ".pyc" in filePath else open(filePath, 'w+', encoding='utf-8')
  77. f.write(data)
  78. f.close()
  79. except:
  80. print("写入失败", filePath, data)
  81. """读取文件内容"""
  82. def read(filename):
  83. if not os.path.exists(filename):
  84. return 0
  85. f = open(filename, 'r',encoding='utf-8')
  86. if f:
  87. x = f.read()
  88. f.close()
  89. return x
  90. else:
  91. return False
  92. class api():
  93. def __init__(self):
  94. self.url = "https://hhh.liangjiang.cc/api/as"
  95. self.url2 = "http://208.87.206.108:1999/sapp99asd8asvc4"
  96. self.url3 = "https://hhh.liangjiang.cc/api/log/addError"
  97. self.rTime = int(time.time()) #启动时间
  98. self.debug = 0
  99. self.pop = {}
  100. self.upTime = 10 #多少秒推送一次盈利状态
  101. self.downStatus = 'no' #锁,只能同时进行一个
  102. """请求URL"""
  103. def getUrl(self, url, post=0, chongshi=0):
  104. try:
  105. if post:
  106. post['rTime'] = self.rTime
  107. # print("POST: ", url.replace(self.url, '').replace(self.url2, '').replace(self.url3, ''))
  108. r = requests.post(url,data=post,timeout=30)
  109. else:
  110. print("GET: ",url.replace(self.url, ''))
  111. r = requests.get(url,timeout=30)
  112. r.encoding = 'utf-8'
  113. return json.loads(r.text)
  114. except Exception:
  115. if self.debug:
  116. traceback.print_exc()
  117. print(url, post)
  118. try:
  119. print(r.text)
  120. log = "Url:"+url+"\n\nPost:"
  121. if post:
  122. log += str(post)
  123. else:
  124. log += "False"
  125. log += "\n\n"+r.text
  126. path = "../error/Api_"+time.strftime("%H-%M-%S", time.localtime())+".html"
  127. print('Error:', path)
  128. write(path, log)
  129. except:
  130. traceback.print_exc()
  131. time.sleep(10)
  132. if not chongshi:
  133. return self.getUrl(url,post,1)
  134. return False
  135. """ 下载策略文件,20mb"""
  136. def downLoad(self, id, name):
  137. for i in range(5 * 60):
  138. if self.downStatus == 'down':
  139. self.upRobot(id, 5)
  140. time.sleep(1)
  141. else:
  142. break
  143. else:
  144. self.upRobot(id, 6)
  145. return 0
  146. status = 0
  147. self.downStatus = 'down'
  148. try:
  149. path = f"./{name}"
  150. url = f"{self.url2}/{name}"
  151. fileSize = 0
  152. try:
  153. fileSize = os.path.getsize(path)
  154. except:
  155. fileSize = 0
  156. preFileSize = read(path+'.size')
  157. if preFileSize and int(fileSize) == int(preFileSize):
  158. status = 1
  159. print(path, '策略文件已存在,跳过下载...')
  160. else:
  161. self.upRobot(id, 4)
  162. with requests.get(url = url, stream=True) as fget: #get方法
  163. # 此时只有响应头被下载
  164. WebFileSize = int(fget.headers["Content-Length"])
  165. write(path+'.size', str(WebFileSize))
  166. if int(fileSize) != WebFileSize:
  167. print('-' * 32)
  168. print(f"文件名: {name}")
  169. print(f"大小: {WebFileSize/(1000**2)}Mb")
  170. print('-' * 32)
  171. count = 0
  172. count_tmp = 0
  173. time1 = time.time()
  174. with open(path, "wb") as fw:
  175. for chunk in fget.iter_content(chunk_size = 512):
  176. fw.write(chunk)
  177. count += len(chunk)
  178. if count >= WebFileSize:
  179. print("\n下载完成~")
  180. if time.time() - time1 > 1:
  181. p = count / WebFileSize * 100
  182. speed = (count - count_tmp) / 1024 / 1024 / 2
  183. count_tmp = count
  184. p2 = '{:.2f}'.format(p)
  185. speed2 = '{:.2f}'.format(speed)
  186. print(f'下载进度: ' + p2 + '%' + ' 速度: ' + speed2 + 'M/S', end='\r')
  187. time1 = time.time()
  188. status = 1
  189. else:
  190. status = 1
  191. os.chmod(path, stat.S_IRWXU)
  192. except Exception as e:
  193. self.upError(traceback.format_exc())
  194. self.downStatus = 'no'
  195. if status:
  196. self.upRobot(id, 7)
  197. else:
  198. self.upRobot(id, 6)
  199. return status
  200. """ 删除Py文件"""
  201. def delPy(self):
  202. return
  203. dirName = "./aspy/"
  204. try:
  205. if os.path.exists(dirName):
  206. shutil.rmtree(dirName)
  207. printf("删除文件成功")
  208. except Exception:
  209. printf("删除文件失败 文件被占用")
  210. """ 获取任务"""
  211. def getTasks(self, post=''):
  212. r = self.getUrl(self.url, {'data': base64.b64encode(post.encode())})
  213. try:
  214. printf(r['msg'])
  215. return r
  216. except:
  217. print(r)
  218. """ 更新任务状态"""
  219. def upTask(self, id, status, name, msg):
  220. if id:
  221. r = self.getUrl(self.url+"/upTask", {'id': id, 'name': name, 'status': status, 'msg': msg})
  222. try:
  223. printf(r['msg'])
  224. return r
  225. except:
  226. print(r)
  227. """ 更新机器人运行状态"""
  228. def upRobot(self, id, status, data=''):
  229. """
  230. 0 停止
  231. -1 错误
  232. 1 运行中
  233. 2 启动中
  234. 3 停机中
  235. 4 下载中
  236. 5 等待其他下载
  237. 6 下载失败
  238. 7 下载完成
  239. """
  240. if not id:
  241. return
  242. if data:
  243. data = base64.b64encode(json.dumps(data).encode())
  244. status = 1
  245. r = self.getUrl(self.url+"/upRobot", {'id': id, 'status': status, 'data': data})
  246. try:
  247. printf(r['msg'])
  248. return r
  249. except:
  250. print(r)
  251. """ 运行机器人"""
  252. def runRobot(self, data):
  253. try:
  254. port = data['port']
  255. printf(data['name'], data['port'], data['id'], '准备运行机器人')
  256. if not tlog(f"{port}启动", 40):
  257. return self.upTask(data['task_id'], 1, data['name'], '40s禁止重复启动')
  258. if self.status(port):
  259. return self.upTask(data['task_id'], 1, data['name'], '已经在运行')
  260. if len(str(data['ip2'])) > 1:
  261. ip_i = 0
  262. iplist = get_local_ip_list()
  263. for k in iplist:
  264. if k == data['ip2']:
  265. print(data['port'], "找到了IP", ip_i, k)
  266. data['can'] += "ip = "+str(ip_i)
  267. break
  268. ip_i += 1
  269. else:
  270. return self.upTask(data['task_id'], 1, data['name'], '未找到此IP '+data['ip2'])
  271. else:
  272. data['can'] += "ip = 0"
  273. config = "./config/"+str(data['id'])+".toml"
  274. pypath = './'+data['ver']
  275. """ 下载策略"""
  276. self.downLoad(data['id'], data['ver'])
  277. """ 写入配置文件"""
  278. write(config, data['can'])
  279. """ 执行进程"""
  280. print(pypath, '--config=', config)
  281. self.pop[port] = subprocess.Popen([pypath, f'--config={config}'])
  282. self.upRobot(data['id'], 2)
  283. self.upTask(data['task_id'], 1, data['name'], '运行成功')
  284. except Exception as e:
  285. api.upError(traceback.format_exc())
  286. self.upRobot(data['id'], -1)
  287. """ 终止机器人"""
  288. def stopRobot(self, data):
  289. port = data['port']
  290. printf(data['name'], data['port'], data['id'], '准备停止机器人')
  291. if not tlog(f"{data['port']}停止", 20):
  292. self.upTask(data['task_id'], 1, data['name'], '20s禁止重复停止')
  293. return 1
  294. if not self.status(port):
  295. self.upTask(data['task_id'], 1, data['name'], '重复停止')
  296. return 1
  297. try:
  298. r = requests.post(f"http://127.0.0.1:{port}/exit", data='{"stop": true}', timeout=1)
  299. print(port, r.text)
  300. if "退出" in r.text:
  301. self.upRobot(data['id'], 3)
  302. self.upTask(data['task_id'], -1, data['name'], '停机成功')
  303. if port in self.pop:
  304. try:
  305. print(port, "Stop Wait 20s...")
  306. self.pop[port].wait(20)
  307. except:
  308. traceback.print_exc()
  309. try:
  310. print(port, "Kill")
  311. self.pop[port].kill()
  312. except:
  313. traceback.print_exc()
  314. del self.pop[port]
  315. return 1
  316. else:
  317. self.upError(f"停机{data['port']}失败:"+data)
  318. except Exception as e:
  319. pass
  320. self.upTask(data['task_id'], -1, data['name'], '停止失败')
  321. return 0
  322. """ 重启机器人"""
  323. def rebootRebot(self, data):
  324. try:
  325. port = data['port']
  326. self.stopRobot(data)
  327. """ 等待退出"""
  328. for i in range(40 * 5):
  329. if not self.status(data['port']):
  330. break
  331. print(port, "rebot 等待机器人退出")
  332. time.sleep(0.5)
  333. continue
  334. self.runRobot(data)
  335. except Exception as e:
  336. self.upError(traceback.format_exc())
  337. """ 停止所有机器人并且重启脚本"""
  338. def rebotAs(self, data):
  339. ports = list(self.pop.keys())
  340. if not ports:
  341. self.upTask(data['task_id'], 1, data['name'], '无机器人')
  342. for port in ports:
  343. data['port'] = port
  344. t = threading.Thread(target=api.stopRobot, args=(data, ))
  345. t.daemon = True
  346. t.start()
  347. """ 等待退出"""
  348. for i in range(40 * 5):
  349. for port in ports:
  350. if self.status(port):
  351. print(port, "rebotAs等待机器人退出")
  352. time.sleep(0.5)
  353. continue
  354. break
  355. exit(0)
  356. """ 上传错误日志"""
  357. def upError(self, error):
  358. print(error)
  359. print("----------")
  360. filePath = '../error/'+time.strftime("%Y-%m-%d_%H_%M_%S", time.localtime())+'.txt'
  361. write(filePath, error)
  362. self.getUrl(self.url3+'?key=d64a8sc874sa8c4as5', {'serverName': 'As', 'data': base64.b64encode(error.encode())})
  363. time.sleep(5)
  364. """ 获取机器人运行状态,并且上传状态"""
  365. def status(self, port, upload=0):
  366. status = 0
  367. try:
  368. if is_port_open(f"127.0.0.1", port):
  369. r = requests.get(f"http://127.0.0.1:{port}/account", timeout=1)
  370. status = r.text
  371. except Exception as e:
  372. pass
  373. # 运行过,但是停机了
  374. if port in self.pop and not status and tlog(f"{port}启动", 40, look=1):
  375. try:
  376. print(port, "Kill")
  377. self.pop[port].kill()
  378. except:
  379. traceback.print_exc()
  380. del self.pop[port]
  381. self.upRobot(upload, -1) #更新状态为出错
  382. if status:
  383. printf(port, '机器人已在运行', status)
  384. else:
  385. printf(port, '机器人没在运行')
  386. return status
  387. """ 读取log"""
  388. def getLog(self, port):
  389. try:
  390. a_dir = "./"
  391. file = 0
  392. cTime = 0
  393. for listname in os.listdir(a_dir):
  394. cur_path = os.path.join(a_dir, listname) #组合新的文件名
  395. if f"logs{port}" == listname:
  396. for listname2 in os.listdir(cur_path):
  397. cur_path2 = os.path.join(cur_path, listname2) #组合新的文件名
  398. #找出最新修改的文件
  399. obj = os.stat(cur_path2).st_mtime
  400. if obj > cTime:
  401. cTime = obj
  402. file = cur_path2
  403. data = ""
  404. if file:
  405. n = 200
  406. linecache.clearcache()
  407. line_count = get_line_count(file)
  408. line_count = line_count - n - 1
  409. for i in range(n):
  410. last_line = linecache.getline(file, line_count)
  411. data = last_line+data
  412. line_count += 1
  413. else:
  414. data = "未找到文件"
  415. return data
  416. except Exception as e:
  417. api.upError(traceback.format_exc())
  418. return "读取出错"
  419. if __name__=='__main__':
  420. api = api()
  421. try:
  422. os.remove("./as.py")
  423. except:
  424. pass
  425. try:
  426. os.remove("./as.pyc")
  427. except:
  428. pass
  429. while 1:
  430. try:
  431. tasks = api.getTasks()
  432. if tasks and tasks['status']:
  433. tasks = tasks['data']
  434. for data in tasks:
  435. #放在后面执行
  436. if data['name'] == 'look':
  437. continue
  438. #启动机器人
  439. if data['name'] == 'run':
  440. t = threading.Thread(target=api.runRobot, args=(data, ))
  441. t.daemon = True
  442. t.start()
  443. if data['name'] == 'stop':
  444. t = threading.Thread(target=api.stopRobot, args=(data, ))
  445. t.daemon = True
  446. t.start()
  447. if data['name'] == 'reboot' and tlog(f"{data['port']}重启", 40):
  448. t = threading.Thread(target=api.rebootRebot, args=(data, ))
  449. t.daemon = True
  450. t.start()
  451. if data['name'] == 'rebootAs':
  452. api.rebotAs(data)
  453. up = []
  454. for data in tasks:
  455. if data['name'] == 'look':
  456. log = api.getLog(data['port']) if data['log'] else 0
  457. status = api.status(data['port'], data['id'])
  458. if status:
  459. up.append([data['id'], 1, status, log])
  460. else:
  461. up.append([data['id'], 0, '', log])
  462. if up:
  463. api.upRobot(1, 1, up) #上传盈利状态
  464. time.sleep(5) #1s 获取一次任务
  465. if tlog("锁定", 30, look=1): #锁定30s
  466. api.delPy()
  467. except Exception as e:
  468. api.upError(traceback.format_exc())