distribute.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import paramiko
  2. import os
  3. class SSHConnect:
  4. # 定义一个私有变量,用来保存ssh连接通道,初始化为None
  5. __transport = None
  6. # 初始化构造函数(主机,用户名,密码,端口,默认22)
  7. def __init__(self, hostname, username, password, port=22):
  8. self.hostname = hostname
  9. self.port = port
  10. self.username = username
  11. self.password = password
  12. # 创建 ssh 连接通道
  13. self.connect()
  14. # 建立ssh 连接通道,并绑定在 __transport 上
  15. def connect(self):
  16. try:
  17. # 设置SSH 连接的远程主机地址和端口
  18. self.__transport = paramiko.Transport((self.hostname, self.port))
  19. # 通过用户名和密码连接SSH服务端
  20. self.__transport.connect(username=self.username, password=self.password)
  21. except Exception as e:
  22. # 连接出错
  23. print(e)
  24. # 执行linux命令
  25. def exec(self, command):
  26. # 创建 ssh 客户端
  27. ssh = paramiko.SSHClient()
  28. # 指定连接的通道
  29. ssh._transport = self.__transport
  30. # 调用 exec_command 方法执行命令
  31. stdin, stdout, stderr = ssh.exec_command(command)
  32. # 获取命令结果,返回是二进制,需要编码一下
  33. res = stdout.read().decode('utf-8')
  34. # 获取错误信息
  35. error = stderr.read().decode('utf-8')
  36. # 如果没出错
  37. if error.strip():
  38. # 返回错误信息
  39. return error
  40. else:
  41. # 返回结果
  42. return res
  43. # 前端打包(入参work_path为项目目录)
  44. def build(self, work_path):
  45. # 开始打包
  46. print('########### run build ############')
  47. # 打包命令
  48. cmd = 'npm run build:prod'
  49. # 切换到需要项目目录
  50. os.chdir(work_path)
  51. # 当前项目目录下执行打包命令
  52. if os.system(cmd) == 0:
  53. # 打包完成
  54. print('########### build complete ############')
  55. # 文件上传
  56. def upload(self, local_path, target_path):
  57. # 判断路径问题
  58. if not os.path.exists(local_path):
  59. return print('local path is not exist')
  60. print('upload...')
  61. # 实例化一个 sftp 对象,指定连接的通道
  62. sftp = paramiko.SFTPClient.from_transport(self.__transport)
  63. # 打包后的文件路径
  64. local_path = os.path.join(local_path, 'dist')
  65. # 本地路径转换,将windows下的 \ 转成 /
  66. local_path = '/'.join(local_path.split('\\'))
  67. # 递归上传文件
  68. self.upload_file(sftp, local_path, target_path)
  69. print('finish upload...')
  70. # 关闭连接
  71. self.close()
  72. # 递归上传文件
  73. def upload_file(self, sftp, local_path, target_path):
  74. # 判断当前路径是否是文件夹
  75. if not os.path.isdir(local_path):
  76. # 如果是文件,获取文件名
  77. file_name = os.path.basename(local_path)
  78. # 检查服务器文件夹是否存在
  79. self.check_remote_dir(sftp, target_path)
  80. # 服务器创建文件
  81. target_file_path = os.path.join(target_path, file_name).replace('\\', '/')
  82. # 上传到服务器
  83. sftp.put(local_path, target_file_path)
  84. else:
  85. # 查看当前文件夹下的子文件
  86. file_list = os.listdir(local_path)
  87. # 遍历子文件
  88. for p in file_list:
  89. # 拼接当前文件路径
  90. current_local_path = os.path.join(local_path, p).replace('\\', '/')
  91. # 拼接服务器文件路径
  92. current_target_path = os.path.join(target_path, p).replace('\\', '/')
  93. # 如果已经是文件,服务器就不需要创建文件夹了
  94. if os.path.isfile(current_local_path):
  95. # 提取当前文件所在的文件夹
  96. current_target_path = os.path.split(current_target_path)[0]
  97. # 递归判断
  98. self.upload_file(sftp, current_local_path, current_target_path)
  99. # 创建服务器文件夹
  100. def check_remote_dir(self, sftp, target_path):
  101. try:
  102. # 判断文件夹是否存在
  103. sftp.stat(target_path)
  104. except IOError:
  105. # 创建文件夹
  106. self.exec(r'mkdir -p %s ' % target_path)
  107. # 自动化打包部署
  108. def auto_deploy(self, local_path, target_path):
  109. # 打包构建
  110. self.build(local_path)
  111. # 清空文件
  112. # self.clear_remote_dir(target_path)
  113. # 文件上传
  114. self.upload(local_path, target_path)
  115. # 清空文件夹
  116. def clear_remote_dir(self, target_path):
  117. if target_path[-1] == '/':
  118. cmd = f'rm -rf {target_path}*'
  119. else:
  120. cmd = f'rm -rf {target_path}/*'
  121. self.exec(cmd)
  122. # 关闭连接
  123. def close(self):
  124. self.__transport.close()
  125. # 销毁实例
  126. def __del__(self):
  127. self.__transport.close()
  128. if __name__ == '__main__':
  129. # 项目目录
  130. project_path = r'd:\Project\P2205-Platform\inspur-ui'
  131. # d:\Project\P2205-Platform\inspur-ui
  132. # 服务器目录
  133. # remote_path = r'/usr/local/tomcat/webapps/'
  134. remote_path = r'/usr/local/tomcat/webapps/inspur-web/'
  135. # 实例化
  136. ssh = SSHConnect(hostname='10.201.10.200', username='root', password='inspur')
  137. # 自动打包部署
  138. ssh.auto_deploy(project_path, remote_path)