manage.py 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. #啟動和管理項目
  2. from distutils.log import error
  3. from encodings import utf_8
  4. from multiprocessing import Value
  5. from app import create_app
  6. from flask import render_template, request, session
  7. import paramiko
  8. import git
  9. import shutil
  10. from time import sleep as sl
  11. from threading import Lock
  12. import threading
  13. from concurrent.futures import ThreadPoolExecutor
  14. import csv
  15. import os
  16. import stat
  17. import time
  18. # app, db, mqtt, socketio = create_app() # Rita 0428
  19. app, db, mqtt = create_app()
  20. thread = None
  21. thread_lock = Lock()
  22. # Rita 0428
  23. # @socketio.on('connect_event', namespace='/test_conn')
  24. # def connected_msg(msg):
  25. # print("connect success")
  26. # print(msg)
  27. # socketio.emit('stdout', 'success', namespace='/test_conn')
  28. # print(socketio)
  29. D = {"item_name":0, "command":0}
  30. # 0411 shutil-rmtree 刪除 .get 唯讀檔
  31. # https://stackoverflow.com/questions/21261132/shutil-rmtree-to-remove-readonly-files
  32. def remove_readonly(func, path, _):
  33. os.chmod(path, stat.S_IWRITE)
  34. func(path)
  35. # # 建置伺服器的訪問路徑 -- 舊 保留 0413 測試
  36. # @app.route('/add_server', methods=['POST', 'GET'])
  37. # def add_server_views():
  38. # username = session['uname']
  39. # L = []
  40. # if request.method == 'GET':
  41. # # 0407 測試註解一下
  42. # # repo = git.Repo.init(path='.')
  43. # # new_repo = git.Repo.clone_from(url='http://60.250.156.230:3000/benson/TestSSH.git', to_path='../new')
  44. # # new_repo = git.Repo.clone_from(url='http://60.250.156.230:3000/rita/CoffeeProject.git', to_path='../new')
  45. # os.system('git clone -b sh --single-branch http://60.250.156.230:3000/Automatic_build_system/Automatically_install_files.git C:\\Users\\USER\\Rita\\operating\\sixthproject\\new')
  46. # # with open('/home/benson/Project/new/All_installv3.2.sh') as f:
  47. # with open('../new/coffeesystem.sh', encoding='utf-8') as f:
  48. # # content = f.read().split('-Dividing line-')
  49. # # D['item_name'] = content[0].split('\n')[1:]
  50. # # D['command'] = content[1].split('\n')
  51. # D['command'] = f.read().split('\n')
  52. # # print("D['command']: ", D['command'])
  53. # # # 0407 測試中暫時註解
  54. # # # with open('/home/benson/Project/new/Item.txt') as f:
  55. # # with open('../new/Item.txt') as f:
  56. # # D['item_name'] = f.read().split('\n')
  57. # # for item in D['item_name']:
  58. # # L.append('.'.join(item.split('.')[1:])) # 拿掉 '.'.join 的話會變成 [['python3', '8'], ['python3-pip'],
  59. # # os.remove('C:/Users/USER/Rita/operating/sixthproject/new/.git')
  60. # # os.system('rm -rf ../new/.git')
  61. # # os.chmod('../new/.git', stat.S_IWRITE)
  62. # # os.unlink('../new/.git')
  63. # # sl(6)
  64. # # shutil.rmtree('../new', ignore_errors=True, onerror=del_rw)
  65. # sl(3)
  66. # shutil.rmtree('../new', onerror=remove_readonly)
  67. # sl(3)
  68. # # os.rmdir('../new')
  69. # # sl(6)
  70. # # #刪除非空資料夾
  71. # # try:
  72. # # shutil.rmtree('../new', ignore_errors=True, onerror=del_rw)
  73. # # # os.remove('../new')
  74. # # print("=== DELETE ===")
  75. # # sl(1)
  76. # # except OSError as e:
  77. # # print(f"OSError:{e.strerror}") # Error:存取被拒。
  78. # # # print("L: ", L) # L: ['python3.8', 'python3-pip', 'git', ... , 'ROS-ubuntu-18.04-melodic']
  79. # # 0407 測試註解一下
  80. # # for i in range(0, len(D['item_name'])):
  81. # # item = D['item_name'][i].split('=')[-1].replace('"','')
  82. # # L.append(item)
  83. # # L = L[:-1]
  84. # # # 0411 測試
  85. # # D['command'] = [
  86. # # # 'cd /tmp/; pwd; sudo wget https://files.phpmyadmin.net/phpMyAdmin/5.1.0/phpMyAdmin-5.1.0-all-languages.tar.gz;tar -zxvf phpMyAdmin-5.1.0-all-languages.tar.gz;sudo rm phpMyAdmin-5.1.0-all-languages.tar.gz; sudo mv phpMyAdmin-5.1.0-all-languages /var/www/html/phpmyadmin;',
  87. # # 'cd /var/www/html/phpmyadmin; pwd; mkdir tmp;',
  88. # # 'cd /var/www/html/phpmyadmin; pwd; mkdir tmp;',
  89. # # 'cd; pwd;',
  90. # # 'pwd']
  91. # L2= []
  92. # for i in range(0, len(D['command'])):
  93. # if D['command'][i] == "'" or D['command'][i] == '' or "#" in D['command'][i] or D['command'][i] == ' ':
  94. # continue
  95. # L2.append(D['command'][i])
  96. # D['command'] = L2
  97. # # print("D['command'] = L2: ", D['command'])
  98. # # print("=============== D['item_name'] ===============")
  99. # # print(D['item_name'])
  100. # # print("=============== D['command'] ===============")
  101. # # print(D['command'])
  102. # # print("=============== CODE CHECK 3 ===============")
  103. # # content = D['item_name'] + D['command']
  104. # # for i in content:
  105. # # print(i)
  106. # return render_template('add_server.html', params=locals())
  107. # else:
  108. # item_install_fail = 0
  109. # d = request.form.to_dict()
  110. # ip = d['ip']
  111. # loginname = d['loginname']
  112. # username = d['username']
  113. # password = d['password']
  114. # print(ip)
  115. # print(loginname)
  116. # print(username)
  117. # print(password)
  118. # try:
  119. # # 建立一個sshclient物件
  120. # ssh = paramiko.SSHClient()
  121. # # 允許將信任的主機自動加入到host_allow 列表,此方法必須放在connect方法的前面
  122. # ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  123. # # 指定本地的RSA私鑰檔案,如果建立金鑰對時設定的有密碼,password為設定的密碼,如無不用指定password引數
  124. # # pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345')
  125. # # pkey = paramiko.RSAKey.from_private_key_file('/home/ptop/topicjie/scripts/keys/id_rsa')
  126. # # 建立連線
  127. # # ssh.connect(hostname=ip,
  128. # # port=22,
  129. # # username='gs1801',
  130. # # pkey=pkey)
  131. # # with open('/home/benson/test11.sh') as f:
  132. # # content = f.read().split('\n')[0:-1]
  133. # # print(content)
  134. # # L = []
  135. # # for i in range(0, len(D['ssh_content'])):
  136. # # if "#" in D['ssh_content'][i] or D['ssh_content'][i] == '' or D['ssh_content'][i] == ' ':
  137. # # continue
  138. # # L.append(D['ssh_content'][i])
  139. # # for i in L:
  140. # # print(i)
  141. # ssh.connect(hostname=ip,
  142. # port=22,
  143. # username=loginname,
  144. # password=password)
  145. # # 假如帳號密碼正確沒有被捕捉到異常,傳送訊息給前端
  146. # socketio.emit('user-confirm', 'pass', namespace='/test_conn')
  147. # # os.system("scp /home/benson/test10.sh gs1801@" + ip + ":/home/gs1801/")
  148. # # 執行命令
  149. # # stdin, stdout, stderr = ssh.exec_command("ls -l /home/gs1801;touch test7.py")
  150. # # stdin, stdout, stderr = ssh.exec_command("touch test10.sh;echo '" + content + "' >> test10.sh;bash test10.sh")
  151. # # print('test1')
  152. # # print(stdout.read().decode())
  153. # # print('test2')
  154. # # print(stderr.read().decode())
  155. # # content = D['item_name'] + D['command']
  156. # with open('ItemFile.csv', 'w', newline='') as csvFile:
  157. # csvWriter = csv.writer(csvFile)
  158. # csvWriter.writerow(['Command', 'Install Content', 'Time', 'Status'])
  159. # # # Rita 0406 TEST
  160. # D['command'] = [
  161. # # 'sudo pip3 install cryptography==3.3.2',
  162. # # 'sudo -H pip3 install --upgrade pip',
  163. # # 'sudo pip3 install gitpython',
  164. # # 'cd /tmp/;pwd;sudo wget https://files.phpmyadmin.net/phpMyAdmin/5.1.0/phpMyAdmin-5.1.0-all-languages.tar.gz -q;tar -zxvf phpMyAdmin-5.1.0-all-languages.tar.gz;sudo rm phpMyAdmin-5.1.0-all-languages.tar.gz;sudo mv phpMyAdmin-5.1.0-all-languages /var/www/html/phpmyadmin',
  165. # # 'cd /var/www/html/phpmyadmin;pwd;mkdir tmp;',
  166. # # # 'sudo mysql -u root -e \"ALTER USER \'root\'@\'localhost\' IDENTIFIED WITH mysql_native_password BY \'Gold@53743001\';\"',
  167. # # 'sudo -H pip3 install paho-mqtt',
  168. # # 'cd /home/gs1802;sudo git clone -b mosquitto --single-branch http://60.250.156.230:3000/fatwolf/mqtt_server_setting.git /home/gs1802/mosquitto/;sudo git clone -b passwd --single-branch http://60.250.156.230:3000/fatwolf/mqtt_server_setting.git /home/gs1802/passwd/;sudo mv /mosquitto/mosquitto.conf /etc/mosquitto/;sudo mv /passwd/passwd /etc/mosquitto/;sudo rm -rf /mosquitto/;sudo rm -rf /passwd/',
  169. # # 'cd /home/gs1802;pwd;sudo git clone -b procwdtdconf --single-branch http://60.250.156.230:3000/fatwolf/proc.git /home/gs1802/procwdtdconf/;sudo git clone -b procwdtd --single-branch http://60.250.156.230:3000/fatwolf/proc.git /home/gs1802/procwdtd/;sudo git clone -b rclocal --single-branch http://60.250.156.230:3000/fatwolf/proc.git /home/gs1802/rclocal/;sudo mv /procwdtdconf/proc-wdtd.conf /etc/;sudo mv /procwdtd/proc-wdtd /usr/sbin/;sudo mv /rclocal/rc.local /etc/;sudo rm -rf /procwdtdconf/;sudo rm -rf /procwdtd/;sudo rm -rf /rclocal/',
  170. # # 'cd /home/gs1802;pwd;git clone http://60.250.156.230:3000/fatwolf/gogsfile.git /home/gs1802/gogs;mv gogs/gogs_0.12.3_linux_amd64.tar.gz /home/gs1802/;rm -rf gogs/;tar -C /home/gs1802 -zxvf gogs_0.12.3_linux_amd64.tar.gz',
  171. # # 'cd /home/gs1802;pwd;git clone -b package --single-branch http://60.250.156.230:3000/Automatic_build_system/Automatically_install_files.git;cd Automatically_install_files/;pwd;sudo pip3 install -r requirements.txt',
  172. # # 'cd /home/gs1802;pwd;sudo git clone http://60.250.156.230:3000/rita/CoffeeProject.git /home/gs1802/CoffeeProject/',
  173. # # 'sudo apt-key adv --keyserver "hkp://keyserver.ubuntu.com:80" --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654',
  174. # # 'sudo apt install ros-melodic-desktop-full -y',
  175. # # 'rosdep update',
  176. # # 'cd /home/gs1802;pwd;mkdir -p ~/catkin_ws/src;pwd;cd ~/catkin_ws/;pwd;catkin_make',
  177. # # 'source ~/catkin_ws/devel/setup.bash'
  178. # # 'cd /tmp/;pwd;sudo wget https://files.phpmyadmin.net/phpMyAdmin/5.1.0/phpMyAdmin-5.1.0-all-languages.tar.gz -q;tar -zxvf phpMyAdmin-5.1.0-all-languages.tar.gz;sudo rm phpMyAdmin-5.1.0-all-languages.tar.gz;sudo mv phpMyAdmin-5.1.0-all-languages /var/www/html/phpmyadmin'
  179. # 'sudo apt install python3-catkin-tools -y',
  180. # 'cd /home/使用者;pwd;mkdir -p ~/catkin_ws/src;pwd;cd /home/使用者/catkin_ws/;pwd;catkin_make'
  181. # # 'cd /home/使用者;pwd;catkin_make',
  182. # # 'cd ~/catkin_ws/src;pwd;catkin_make '
  183. # ]
  184. # for command in D['command']:
  185. # if '使用者' in command :
  186. # command = command.replace('使用者', username)
  187. # print(command)
  188. # stdin, stdout, stderr = ssh.exec_command(command)
  189. # command_start_time = time.time()
  190. # # sl(6) # Rita 原本為 sl(6) 增加後觀察是否 clone 輸出會改變
  191. # # Rita 0406 stdout(success)、stderr(error) 每次只會輸出其中一個, 以此做為判斷, 例如:
  192. # # print('=========================================')
  193. # # print('stdout: ', stdout.read().decode())
  194. # # print('stderr: ', stderr.read().decode())
  195. # # print('=========================================')
  196. # # 輸出為:
  197. # # =========================================
  198. # # stdout: 正在讀取套件清單...
  199. # # 正在重建相依關係...
  200. # # 正在讀取狀態資料...
  201. # # python3.8 is already the newest version (3.8.0-3ubuntu1~18.04.2).
  202. # # 升級 0 個,新安裝 0 個,移除 0 個,有 208 個未被升級。
  203. # # stderr:
  204. # # =========================================
  205. # error = stderr.read().decode()
  206. # success = stdout.read().decode()
  207. # # print('error: ', error, '\nlen(error): ', len(error))
  208. # print('error: ', error, '\nlen(error): ')
  209. # print('success: ', success, '\nlen(success): ')
  210. # if len(success) > 200000:
  211. # success = success[0:20000] + '... etc'
  212. # execution_time = round(time.time() - command_start_time, 3)
  213. # if error:
  214. # print('error')
  215. # print(error)
  216. # if item_install_fail == 0:
  217. # item_install_fail = 1
  218. # with open('ItemFile.csv', 'a', newline='') as csvFile:
  219. # csvWriter = csv.writer(csvFile)
  220. # csvWriter.writerow([command.replace(';', ';\n'),
  221. # 'success: \n' + success + '\n' + 'error: \n' + error,
  222. # # 'success: \n' + success,
  223. # # 'error: \n' + error,
  224. # execution_time,
  225. # 'error'])
  226. # socketio.emit('stderr', error, namespace='/test_conn')
  227. # else:
  228. # print('success')
  229. # print(success)
  230. # with open('ItemFile.csv', 'a', newline='') as csvFile:
  231. # csvWriter = csv.writer(csvFile)
  232. # csvWriter.writerow([command.replace(';', ';\n'),
  233. # 'success: \n' + success + '\nerror: \n' + error,
  234. # execution_time,
  235. # 'success'])
  236. # socketio.emit('stdout', success, namespace='/test_conn')
  237. # sl(1)
  238. # print('-----------------------------------------------------------------------------')
  239. # # Rita 0406 本來就註解
  240. # # def sshJob():
  241. # # for command in content:
  242. # # stdin, stdout, stderr = ssh.exec_command(command)
  243. # # #
  244. # # # # print(stdout.read().decode())
  245. # # # # print('----------------------------------------')
  246. # # # # print(stderr.read().decode())
  247. # # #
  248. # # print(stdin)
  249. # # if stderr.read().decode():
  250. # # L.append(0)
  251. # # print('error')
  252. # # socketio.emit('stderr', stderr.read().decode())
  253. # # else:
  254. # # L.append(1)
  255. # # print('success')
  256. # # socketio.emit('stdout', stdout.read().decode())
  257. # # sl(5)
  258. # # ssh.close()
  259. # # Rita 0406 本來就註解
  260. # # def sshJob():
  261. # # sl(5)
  262. # # i = 0
  263. # # total = len(content)
  264. # # while True:
  265. # # stdin, stdout, stderr = ssh.exec_command(content[i])
  266. # # #
  267. # # # # print(stdout.read().decode())
  268. # # # # print('----------------------------------------')
  269. # # # # print(stderr.read().decode())
  270. # # #
  271. # # if stderr.read().decode():
  272. # # L.append(0)
  273. # # print('error')
  274. # # socketio.emit('stderr', stderr.read().decode())
  275. # # else:
  276. # # L.append(1)
  277. # # print('success')
  278. # # socketio.emit('stdout', stdout.read().decode())
  279. # # sl(5)
  280. # # i += 1
  281. # # if i == total:
  282. # # break
  283. # # ssh.close()
  284. # # ssh_thread = threading.Thread(target=sshJob)
  285. # # ssh_thread.daemon = True
  286. # # ssh_thread.start()
  287. # # global thread
  288. # # with thread_lock:
  289. # # if thread is None:
  290. # # thread = socketio.start_background_task(target=sshJob)
  291. # # print(L)
  292. # #
  293. # # item_list = ItemList()
  294. # # item_list.ip = ip
  295. # # item_list.pymysql = L[0]
  296. # # item_list.eventlet = L[1]
  297. # # datetime = dt.now()
  298. # # item_list.datetime = datetime
  299. # # db.session.add(item_list)
  300. # # db.session.commit()
  301. # # 關閉寫入的 CSV 檔案
  302. # csvFile.close()
  303. # # 關閉連線
  304. # ssh.close()
  305. # if item_install_fail:
  306. # res = '有套件未安裝完成!'
  307. # else:
  308. # res = '建置完成!'
  309. # return res
  310. # except Exception as e:
  311. # print(e)
  312. # return str(e)
  313. Automatic_Build_System = {
  314. 'python3.8': '0',
  315. 'python3-pip': '0',
  316. 'cryptography': '0',
  317. 'upgrade': '0',
  318. 'grep': '0',
  319. 'git': '0',
  320. 'gitpython': '0',
  321. 'python3-tk': '0',
  322. 'wget': '0',
  323. 'python3-dev': '0',
  324. 'default-libmysqlclient-dev': '0',
  325. 'build-essential': '0',
  326. 'tasksel': '0',
  327. 'lamp-server': '0',
  328. 'phpMyAdmin-5.1.0-all-languages.tar.gz': '0',
  329. 'openssl': '0',
  330. 'php-common': '0',
  331. 'php-curl': '0',
  332. 'php-json': '0',
  333. 'php-mbstring': '0',
  334. 'php-mysql': '0',
  335. 'php-xml': '0',
  336. 'php-zip': '0',
  337. 'php7.2-mbstring': '0',
  338. 'php7.2-xml': '0',
  339. 'php7.2-mysql': '0',
  340. 'php7.2-common': '0',
  341. 'php7.2-curl': '0',
  342. 'php7.2-json': '0',
  343. 'php7.2-zip': '0',
  344. 'apache2': '0',
  345. 'paho-mqtt': '0',
  346. 'mosquitto': '0',
  347. 'mqtt_server_setting': '0',
  348. 'rclocal/rc.local': '0',
  349. 'golang': '0',
  350. 'gogsfile.git': '0',
  351. 'requirements': '0',
  352. 'CoffeeProject.git': '0',
  353. 'BBend-Test-JWT.git': '0',
  354. 'Coffee_MySQL.sql': '0',
  355. 'chrony': '0',
  356. 'ntpdate': '0',
  357. '--keyserver': '0',
  358. 'update': '0',
  359. 'ros-melodic-desktop-full': '0',
  360. 'ros-melodic-rqt*': '0',
  361. 'python-rosdep': '0',
  362. 'python-rosinstall': '0',
  363. 'python-rosinstall-generator': '0',
  364. 'python-wstool': '0',
  365. 'catkin_make': '0'
  366. }
  367. @app.route('/ABS_update', methods=['POST', 'GET'])
  368. def ABS_update():
  369. return Automatic_Build_System
  370. # 0413 測試中, 原版在上方
  371. @app.route('/add_server', methods=['POST', 'GET'])
  372. def add_server_views():
  373. username = session['uname']
  374. L = []
  375. if request.method == 'GET':
  376. # ============================================================================================
  377. # # 232 路徑
  378. Users = os.popen("getent passwd 1000 | cut -d: -f1")
  379. UserFile = Users.read().strip()
  380. print("UserFile:", UserFile)
  381. os.system('git clone -b sh --single-branch http://60.250.156.230:3000/Automatic_build_system/Automatically_install_files.git /home/' + UserFile + '/BBend-Test-JWT/newSH')
  382. with open('/home/' + UserFile + '/BBend-Test-JWT/newSH/coffeesystem.sh', encoding='utf-8') as f:
  383. D['command'] = f.read().split('\n')
  384. sl(3)
  385. shutil.rmtree('/home/' + UserFile + '/BBend-Test-JWT/newSH', onerror=remove_readonly)
  386. with open('/home/' + UserFile + '/BBend-Test-JWT/Item.txt') as f:
  387. D['item_name'] = f.read().split('\n')
  388. for item in D['item_name']:
  389. L.append('.'.join(item.split('.')[1:])) # 拿掉 '.'.join 的話會變成 [['python3', '8'], ['python3-pip'],
  390. # ============================================================================================
  391. # # # 本機 路徑
  392. # os.system('git clone -b sh --single-branch http://60.250.156.230:3000/Automatic_build_system/Automatically_install_files.git C:/Users/USER/Rita/operating/sixthproject/BBend-Test-JWT/newSH')
  393. # with open('C:/Users/USER/Rita/operating/sixthproject/BBend-Test-JWT/newSH/coffeesystem.sh', encoding='utf-8') as f:
  394. # D['command'] = f.read().split('\n')
  395. # # print("D['command']: ", D['command'])
  396. # sl(3)
  397. # shutil.rmtree('newSH', onerror=remove_readonly)
  398. # with open('Item.txt') as f:
  399. # D['item_name'] = f.read().split('\n')
  400. # for item in D['item_name']:
  401. # L.append('.'.join(item.split('.')[1:])) # 拿掉 '.'.join 的話會變成 [['python3', '8'], ['python3-pip'],
  402. # # ============================================================================================
  403. sl(3)
  404. L2= []
  405. for i in range(0, len(D['command'])):
  406. if D['command'][i] == "'" or D['command'][i] == '' or "#" in D['command'][i] or D['command'][i] == ' ':
  407. continue
  408. L2.append(D['command'][i])
  409. D['command'] = L2
  410. # # ===========================================================================================================
  411. return render_template('add_server.html', params=locals())
  412. else:
  413. item_install_fail = 0
  414. d = request.form.to_dict()
  415. ip = d['ip']
  416. loginname = d['loginname']
  417. username = d['username']
  418. password = d['password']
  419. print(ip)
  420. print(loginname)
  421. print(username)
  422. print(password)
  423. try:
  424. # Rita 0428 測試
  425. # 建立一個sshclient物件
  426. ssh = paramiko.SSHClient()
  427. # 允許將信任的主機自動加入到host_allow 列表,此方法必須放在connect方法的前面
  428. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  429. # 指定本地的RSA私鑰檔案,如果建立金鑰對時設定的有密碼,password為設定的密碼,如無不用指定password引數
  430. # pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345')
  431. # pkey = paramiko.RSAKey.from_private_key_file('/home/ptop/topicjie/scripts/keys/id_rsa')
  432. # 建立連線
  433. ssh.connect(hostname=ip,
  434. port=22,
  435. username=loginname,
  436. password=password)
  437. # 假如帳號密碼正確沒有被捕捉到異常,傳送訊息給前端
  438. # socketio.emit('user-confirm', 'pass', namespace='/test_conn')
  439. # content = D['item_name'] + D['command']
  440. with open('../ItemFile.csv', 'w', newline='') as csvFile:
  441. csvWriter = csv.writer(csvFile)
  442. csvWriter.writerow(['Command', 'Install Content', 'Time', 'Status'])
  443. # # # Rita TEST
  444. # D['command'] = [
  445. # "sudo apt-get install tasksel -y",
  446. # "sudo DEBIAN_FRONTEND=noninteractive tasksel install lamp-server",
  447. # "sudo -H pip3 install paho-mqtt",
  448. # "sudo apt-get install mosquitto -y",
  449. # ]
  450. for command in D['command']:
  451. if '使用者' in command :
  452. command = command.replace('使用者', username)
  453. if 'sudo apt-get install' in command :
  454. command = command.replace('sudo apt-get install', "sudo DEBIAN_FRONTEND=noninteractive apt-get install")
  455. print(command)
  456. # 判斷若此 command 符合 Automatic_Build_System 的 Key, 則改變狀態
  457. for key, value in Automatic_Build_System.items():
  458. if key in command and value == '0':
  459. print('key: ', key, ' / command: ', command)
  460. Automatic_Build_System[key] = "Install"
  461. # # 0429 測試用
  462. # import random
  463. # tt = round(random.uniform(10.0,20.0), 3)
  464. # sl(tt)
  465. # Automatic_Build_System[key] = tt
  466. sl(1)
  467. command_start_time = time.time()
  468. # 0504 Rita 測試
  469. stdin, stdout, stderr = ssh.exec_command(command)
  470. error = stderr.read().decode()
  471. success = stdout.read().decode()
  472. # print('error: ', error, '\nlen(error): ', len(error))
  473. print('error: ', error)
  474. print('success: ', success)
  475. if len(success) > 200000:
  476. success = success[0:20000] + '... etc'
  477. execution_time = round(time.time() - command_start_time, 3)
  478. if error:
  479. # 排除 錯誤訊息中的 警告訊息
  480. Warning_list = [
  481. "WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager.",
  482. "Cloning into",
  483. "Warning: apt-key output should not be parsed (stdout is not a terminal)",
  484. "gpg",
  485. "Warning: running 'rosdep update' as root is not recommended.",
  486. "You should run",
  487. "[Warning] Using a password on the command line interface can be insecure."
  488. ]
  489. error_command_list = error.split('\n')
  490. for_error_command_list = error_command_list.copy()
  491. # print("a: ", a)
  492. # print("a[0]: ", a[0])
  493. for cl in range(0, len(error_command_list)):
  494. # print("=================================")
  495. # print("error_command_list[cl]: ", error_command_list[cl])
  496. for W in range(len(Warning_list)):
  497. # for W in range(len(error_command_list)):
  498. try:
  499. if Warning_list[W] in error_command_list[cl]:
  500. # print("AA: ", Warning_list[W])
  501. # print("BB: ", error_command_list[cl])
  502. # # and error_command_list.index(Warning_list[W]) != -1
  503. # # command_index = error_command_list[0].index(Warning_list[W])
  504. # # print(command_index)
  505. for_error_command_list.remove(error_command_list[cl])
  506. # print(error_command_list)
  507. # print(for_error_command_list)
  508. except IndexError:
  509. pass
  510. if for_error_command_list == [''] or for_error_command_list == []:
  511. print('=== Warning ===')
  512. with open('../ItemFile.csv', 'a', newline='') as csvFile:
  513. csvWriter = csv.writer(csvFile)
  514. csvWriter.writerow([command.replace(';', ';\n'),
  515. 'success: \n' + success + '\n' + 'error: \n' + error,
  516. # 'success: \n' + success,
  517. # 'error: \n' + error,
  518. execution_time,
  519. 'warning'])
  520. # socketio.emit('stderr', error, namespace='/test_conn')
  521. # 判斷若此 command 符合 Automatic_Build_System 的 Key, 則改變狀態
  522. for key, value in Automatic_Build_System.items():
  523. if key in command:
  524. Automatic_Build_System[key] = execution_time
  525. else:
  526. print('for_error_command_list: ', for_error_command_list)
  527. print('=== error ===')
  528. if item_install_fail == 0:
  529. item_install_fail = 1
  530. with open('../ItemFile.csv', 'a', newline='') as csvFile:
  531. csvWriter = csv.writer(csvFile)
  532. csvWriter.writerow([command.replace(';', ';\n'),
  533. 'success: \n' + success + '\n' + 'error: \n' + error,
  534. # 'success: \n' + success,
  535. # 'error: \n' + error,
  536. execution_time,
  537. 'error'])
  538. # socketio.emit('stderr', error, namespace='/test_conn')
  539. # 判斷若此 command 符合 Automatic_Build_System 的 Key, 則改變狀態
  540. for key, value in Automatic_Build_System.items():
  541. if key in command:
  542. Automatic_Build_System[key] = "Error"
  543. else:
  544. print('=== success ===')
  545. with open('../ItemFile.csv', 'a', newline='') as csvFile:
  546. csvWriter = csv.writer(csvFile)
  547. csvWriter.writerow([command.replace(';', ';\n'),
  548. 'success: \n' + success + '\nerror: \n' + error,
  549. execution_time,
  550. 'success'])
  551. # socketio.emit('stdout', success, namespace='/test_conn')
  552. # 判斷若此 command 符合 Automatic_Build_System 的 Key, 則改變狀態
  553. for key, value in Automatic_Build_System.items():
  554. if key in command:
  555. Automatic_Build_System[key] = execution_time
  556. sl(5) # Rita 原本為 sl(6) 增加後觀察是否 clone 輸出會改變
  557. print('-----------------------------------------------------------------------------')
  558. # print("Automatic_Build_System: ")
  559. # print(Automatic_Build_System)
  560. with open('../ItemFile.csv', 'a', newline='') as csvFile:
  561. csvWriter = csv.writer(csvFile)
  562. csvWriter.writerow(['',
  563. 'Automatic_Build_System: \n' + str(Automatic_Build_System),
  564. '',
  565. ''])
  566. # 關閉連線
  567. ssh.close()
  568. if item_install_fail:
  569. res = '有套件未安裝完成!'
  570. else:
  571. res = '建置完成!'
  572. return res
  573. except Exception as e:
  574. print(e)
  575. return str(e)
  576. #mqtt發布
  577. @app.route('/mqtt', methods=['GET','POST'])
  578. def mqtt_views():
  579. import json
  580. dict = request.args.to_dict()
  581. json = json.dumps(dict)
  582. print(json)
  583. mqtt.publish('AISKY/AppleFarm/MK-G/b8:27:eb:f8:24:92', json)
  584. return "Publish done"
  585. #mqtt訂閱
  586. @mqtt.on_connect()
  587. def handle_connect(client, userdata, flags, rc):
  588. mqtt.subscribe('AISKY/AppleFarm/MK-G/b8:27:eb:f8:24:92/Log')
  589. #處理mqtt訂閱的信息
  590. @mqtt.on_message()
  591. def handle_mqtt_message(client, userdata, message):
  592. payload = message.payload.decode()
  593. # p = json.loads(payload)
  594. # print("-------msg-------")
  595. # print('name :', p['name'])
  596. # print('email :', p['email'])
  597. print(payload)
  598. #調用日誌訊息
  599. @mqtt.on_log()
  600. def handle_logging(client, userdata, level, buf):
  601. print(level, buf)
  602. #自動關閉所有未使用、掛著的連接
  603. @app.teardown_appcontext
  604. def shutdown_session(exception=None):
  605. db.session.remove()
  606. if __name__ == '__main__':
  607. # Rita 0406 socketio.run(app, debug=True, host='0.0.0.0', port=5014)
  608. # Rita 0406 app.run(debug=True, host='0.0.0.0', port=5014)
  609. # print("===== BBend =====")
  610. # socketio.run(app, debug=True, host='0.0.0.0', port=5014)
  611. app.run(debug=True, host='0.0.0.0', port=5014)