作为软件测试人员,经常要发布开发的集成包。本来嘛,更新个服务,没什么大不了。但是集成包打出来,要更新的服务有9个(分别部署在三台服务器上),并且以后还会增加。如果手动更新,每次更新时间都得20分钟以上,长此以往,非常浪费时间。

更新流程背景

1、从一台可用FTP连接的服务器上,下载集成人员集成好的最新包。
2、解压下载的集成包,解压后,生成9个程序包,每个程序包是以.tar.gz格式压缩。
3、将9个包,分别上传至对应服务器(3台linux服务器)
4、关闭服务器上的服务,并备份未更新前的服务程序
5、解压上传的.tar.gz文件至指定目录
6、替换加压后文件中的一个conf文件夹中的配置
7、启动服务。

脚本编写

从FTP服务器下载文件

python 内置ftplib库,可以方便的通过FTP连接服务器

FTP连接

def ftp_connect(host, port, username, password, encoding="UTF-8"):"""Connect server via FTP.If connect sucessfully, return ftp object, else return False!"""try:ftp = FTP()ftp.set_debuglevel(0)   #打开调试级别2,显示详细信息;0为关闭调试信息 ftp.set_pasv(0)#0主动模式 1 #被动模式ftp.encoding = encodingftp.connect(host, port)ftp.login(username, password)   #登录,如果匿名登录则用空串代替即可 return ftpexcept Exception as e:print("Connect FTP Error!")print("Error:", str(e))return False

定义一个函数,传参分别是服务器IP,端口,用户名,密码,编码。

FTP文件下载

def ftp_download():"""Download file via ftp connection!Get the latest file from the dir file_path["DB/Middle"][0],Save the file to the dir file_path["DB/Middle"][1]."""file_path = {"DB":["/省略.../DB", "D:/FTP/DB/"], "Middle":["/省略.../Middle", "D:/FTP/Middle/"]}ftp = ftp_connect()if ftp:for each in file_path:ftp.cwd("/") #改变路径try:ftp.cwd(file_path[each][0]) #改变路径except:print("There is no such [%s] directory!" % file_path[each][0])continue#ftp.dir()#print ftp.getwelcome()#显示ftp服务器欢迎信息 #ftp.cwd('xxx/xxx/') #选择操作目录del_dir(file_path[each][1], isfile=True) #删除当前目录的解压后的文件夹bufsize = 1024 file_name = ftp.nlst()[-1] #取当前路径的文件名列表(按时间顺序排序)try:file_handler = open(file_path[each][1] + file_name,'wb').write #以写模式在本地打开文件except:print("There is no such [%s] directory!" % file_path[each][1])continuetry:print("[%s] will be downloaded!" % file_name)ftp.retrbinary('RETR %s' % os.path.basename(file_name),file_handler,bufsize)#接收服务器上文件并写入本地文件 #ftp.set_debuglevel(0) #file_handler.close()print("[%s] downloads completed!" % file_name)except Exception as e:print("Download file[%s] Error!" % file_name)print("Error:", str(e))ftp.quit()

介绍一下file_path变量:

file_path = {"DB":["/省略.../DB", "D:/FTP/DB/"], "Middle":["/省略.../Middle", "D:/FTP/Middle/"]}
file_path["DB"][0]是FTP服务器上下载的需要执行的sql文件
file_path["DB"][1]是FTP服务器上下载的需要执行的sql文件存放于本地磁盘的路径
file_path["Middle"][0]是FTP服务器上下载的中台程序包(解压后会产生9个.tar.gz包)
file_path["Middle"][1]是FTP服务器上下载的中台程序包存放于本地磁盘的路径

del_dir()是自定义的函数,主要作用是删除当前目录下的所有文件或者文件夹。具体实现如下:

def del_dir(path, isdir=True, isfile=False):"""Delete files or directories!The files or directories whether would be deleted pointing to isdir/isfile is true or false.If true, then will be deleted"""os.chdir(path)for each in os.listdir():if os.path.isdir(each):if isdir:shutil.rmtree(each)print("The dir[%s] was removed!" % each)else:if isfile:os.remove(each)print("The file[%s] was removed!" % each)

此处还用到解压.rar文件,需要安装rarfile库。
解压方法如下:

def un_rar(path):"""Extract rar file!Argue path is the dir, file is the one which will be extract!"""try:os.chdir(path)for each in os.listdir():if os.path.isfile(each):#当前目录只有一个文件file = eachrar = rarfile.RarFile(file) os.mkdir(file[:-4]) #创建rar文件解压后的存放路径rar.extractall(file[:-4]) #解压文件到指定路径print("Un_rar file[%s] Successfully!" % file)except Exception as e:print("Un_rar file[%s] failed!" % file)print("Error:", str(e))finally:rar.close()

SSH连接

python支持ssh连接的库还是比较多的,此处选择paramiko库(关于windows安装paramiko库,我在上一篇文章中做了记录,可供大家参考)

def ssh_connect(host="192.168.226.131", port=22, username="root", password="chenkang0818", encoding="UTF-8"):"""Connect to server via SSH.If connect successfully return ssh object, else return False."""try:ssh = paramiko.SSHClient()ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())   #这行代码的作用是允许连接不在know_hosts文件中的主机。ssh.connect(host, port=port, username=username, password=password)return sshexcept Exception as e:print("SSH Connect Error!")print("Error:", e)return False

SSH连接linux服务器上传文件

连接服务器成功后,接下来就是上传文件。使用sftp.put(file_1,file_2)命令,如果服务器存在file_2,那么该文件会被替换,如果没有则直接拷贝至服务器。

def ssh_upload():"""A ssh upload fuction!"""for ip in SERVER_INFO:ssh = ssh_connect(host=ip, port=SERVER_INFO[ip]["port"], username=SERVER_INFO[ip]["username"], password=SERVER_INFO[ip]["password"]) #以ssh形式连接服务器if not ssh: #如果连接不成功,则跳过print("Connect server[%s] failed!" % ip)continuecall_command(ssh, "cd middle; ./middle_stop")   #连接上服务器后,执行关闭服务脚本print("Preparing for starting...............")sftp = ssh.open_sftp()  #打开一个sftp形式连接服务器os.chdir(SERVER_INFO[ip]["get_path"])try:if len((lambda count=0:[ count+1 for each in os.listdir() if os.path.isdir(each)])()) == 1:  #防止middle文件夹中含有多个解压文件夹,确保上传服务器的文件是最新的for each in os.listdir():if os.path.isdir(each):local_get_path = os.path.join(os.getcwd(), each) #合并路径print("Uploading file on the server [%s]" % (ip))for file in SERVER_INFO[ip]["get_file"]:local_get_file = os.path.join(local_get_path, file) #合并路径sftp.put(local_get_file, "/home/hundsun/middle/" + file) #将本地文件上传至服务器print("Up file[%s] successfully!" % file)call_command(ssh, "cd middle; ./middle_start") #当前服务器所有tar文件替换完毕后,执行启动脚本except Exception as e:print("Upload file[%s] failed!" % file)print("Error:", str(e))finally:sftp.close()ssh.close()

说明:

SERVER_INFO是定义的一个字典,其格式为:
SERVER_INFO = {"xx.xx.xx.xx":{"port":22, "username":"root", "password":"xxxxxx", "get_path":"D:/FTP/Middle/", "get_file":["xx1.tar.gz", "xx2.tar.gz","xx3.tar.gz"],"save_path":"/home/省略.../"}}

其中get_path是指:要上传服务器的程序包(.tar.gz文件)的本地路径get_file的是指:需要上传至服务器更新的程序包
save_path是指:上传至linux服务器的路径

os.path.join(get_path, get_file)是要上传的程序包的整个路径

call_command()是自定义函数,主要是运行服务器上启动,停止服务的脚本。定义如下:

def call_command(ssh, cmd):stdin,stdout,stderr = ssh.exec_command(cmd)print("-------------------return result--------------------")for each in stdout.readlines():print(each)print("----------------------Error-------------------------")for each in stderr.readlines():print(each)

这里着重说一下paramiko的exec_command(cmd)方法。
开始的时候我产生一个误区,以为:先执行ssh.exec_command(“cd /home/abc/efg”),shh就会定位在/home/abc/efg,其实不是这样的。
通过paramiko建立ssh连接,会默认定位于/home/当前用户的路径。
如果你想先cd /home/abc/efg,而后执行/home/abc/efg路径下的脚本./stop.sh则应该这样:ssh.exec_command(“cd /home/abc/efg; ./stop.sh”)

运行程序

以下是运行程序方法:

spend_time()(ftp_down)
un_rar("D:/FTP/Middle/")
un_rar("D:/FTP/DB/")
spend_time()(ssh_upload)

为了查看各个过程花费的时长,做了个时间统计。前面说手动操作是20分钟以上,那么当然想看看程序能为我们节省下多少时间。
spend_time()函数定义如下:

def spend_time():"""Calculate calling a fuctionthe how longs it will spend. """time1 = time.time()def wrapper(func):func()time2 = time.time()return print(time2-time1)return wrapper

涉及库

以下是支撑该脚本运行的库

from ftplib import FTP
import os, time
import paramiko
import rarfile
import shutil
import pymysql

windows安装paramiko库我上篇文章提过。
windows安装rarfile安装可用pip命令。安装完毕之后,找到windows下rar安装路径,将Unrar.exe放在python的环境变量中即可。
以下是windows 64位Unrar.exe程序包。
链接:http://pan.baidu.com/s/1hsJmZbe 密码:ee6h

从FTP服务器下载文件部署更新linux服务器上的服务相关推荐

  1. Demo_C#_Winform Ftp异步下载文件,更新ProgressBar

    由于研究Winform项目的版本自动检测更新,需要用到Ftp下载更新包文件. 特写出这个小Demo. 我的Ftp是本地用IIS搭建的FTP服务器,下载过一个1.8G的视频文件,亲测有效. 注意点: F ...

  2. linux服务器不允许下载文件,关于从Linux服务器下载Excel文件的问题

    本地下载文件可以,可是把代码放到Linux服务器下载下来的是jsp页面内容,下载的Excel文件中的内容则是jsp中展示的内容 相关代码 response.setCharacterEncoding(& ...

  3. filezilla 设置服务器_java项目部署到linux服务器,微信小程序后台springboot项目部署到腾讯云服务器(图文详解)...

    前面给大家讲了一个点餐系统的开发,包括java点餐后台和微信点餐小程序.可是都是教大家如何在本地把项目跑起来.今天就来教大家如何把这个点餐系统部署到服务器,实现商用. 传送门 点餐系统的开发,java ...

  4. 怎样把服务器的文件改名字,linux服务器如何修改文件名称rm命令删除文件时排除特定文件...

    grep -i richard telnos 在文件telnos中检索字符串richard,不顾字母的大小写. grep '[0-9]*' chapter1 由于[0-9]*与空字符串匹配,上述命令打 ...

  5. android 从本地服务器下载文件,Retrofit2-如何从服务器下载文件

    在这篇博客中,将会讲述使用Retrofit十分需要的一个功能:怎么去下载文件,下面会展示一些下载文件需要写的代码片段,从小的 png 图片到大的 zip文件.

  6. 使用scp上传文件到服务器或从服务器下载文件(支持跨越跳板机)

    转载 原文链接 原贴写的很好,我转载懒得排版了 scp是什么? 使用man scp可以看到scp的解释『scp - secure copy (remote file copy program)』,sc ...

  7. linux中如何用ftp命令下载文件,linux中ftp下载文件命令的用法

    linxu下的ftp命令是用来下载文件或者上传文件的,下面由学习啦小编为大家整理了linux的ftp下载文件命令的用法的相关知识,希望对大家有帮助! 一.linux中的ftp下载文件命令的用法 从远程 ...

  8. 在linux系统,用FTP工具下载文件

    在linux系统,用FTP工具下载文件 有两种方式: 1. 打开终端,使用ftp命令连接到ftp 服务器如ftp 192.168.1.9 ,然后输入用户名密码,进入服务器后,用get命令下载你要下的文 ...

  9. 从Linux服务器下载文件和文件夹到本地命令

    从Linux 服务器上传或者下载文件到本地除了使用FTP外,还可以通过Linux命令来实现,Linux服务器与本地电脑之间传输文件的命令及使用方法: 1.使用scp命令 命令格式: scp [参数] ...

最新文章

  1. system.img格式打包学习
  2. C# message简单实现窗口间信息接收与发送
  3. Python 中如何自动导入缺失的库?
  4. Intel Sandy Bridge/Ivy Bridge架构/微架构/流水线 (2) - 流水线概述框图
  5. 精通oracle能干嘛,五分鍾精通Oracle表空間
  6. ActionMapping
  7. pillow python histogram_Python中的PIL库
  8. android抓socket数据包,sokit-1.3 CommMonitor 串行端口监视精灵 友善串口调试助手
  9. 在Python中安装meta模块
  10. 冰点还原精灵如何关闭?
  11. php 分享网 齐老师,令我难忘的齐老师
  12. xcode11 The app delegate must implement the window property if it wants to use a main storyboard fil
  13. 使用MIPS完成汇编程序——选择排序实现
  14. Civil 3d-快速转换C3D图形为CAD图形
  15. 【注入】C# 构造注入的方法
  16. 定期把电脑的文件备份到服务器,怎么让电脑定期自动备份文件或文件夹(学会这一招,让电脑自动备份你的重要资料)...
  17. 微信小程序开发之——云开发初探
  18. 关于 Safari 无法下载 pdf 文件的问题
  19. WordPress模板Uigreat1.4设计资源主题
  20. 山雨欲来风满楼——云计算趋势一览

热门文章

  1. Root作对数坐标图及蒙卡随机模拟
  2. MathType 6.9 安装提示关闭软件再试一次
  3. 差分隐私:原理、应用与展望(新加坡国立大学 萧小奎)
  4. slf4j.Logger的全面讲解及e.getMessage()为何为空
  5. 14、保存文件格式为.txt
  6. 程序员必备技术类微信公众号
  7. 计算机原理第四章存储器题目,计算机组成原理第四章部分课后题答案(唐朔飞版)...
  8. java报销系统的参考文献_java毕业设计_springboot框架的企业报销管理与实现
  9. c语言推流,1小时学会:最简单的iOS直播推流(一)介绍
  10. 专利检索工具网站分享