负载均衡了A,B两台服务器win2008r2,同样的路径 D:\\IIS\\proName 放着Asp MVC4开放编译好的项目,每次团队修改bug或者添加新功能,我需要把A,B服务器的项目备份好,本机从TFS(感觉还是SVN好用点)获取最新代码,之后编译,再覆盖上服务器,操作的过程中要注意些问题,比如说服务器项目里的log4net生成的日志文件不要压缩备份,要不然压缩文件会很大,覆盖的时候,有些文件是不能替换的,比如说web.config,因为数据库连接等一些信息是不一样的,除此之外,还要做升级更新记录,以备领导查询等等
所以萌发搞一个程序自动化升级更新,之所以用Python,只是因为正在学习,当然另一方面是因为需要使用SSH协议来跟远程服务器交互,Python的paramiko插件比我拿手C#的ssh.net好用多
说说我的思路
1. 只压缩A服务器项目
2. 下载到本机解压
3. 本机TFS更新项目,编译发布
4. 对比获取服务器项目和本机发布项目的差异文件,并压缩差异文件,以及记录信息到数据库
5. 上传差异压缩包到A和B服务器,并覆盖替换
部分核心代码
# 压缩服务器项目
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('服务器IP', 服务器ssh端口, username='服务器用户名', password='服务器密码', timeout=4)
# paramiko ssh 远程连接window,其实是模拟成linux,所以要用linux shell命令来操作
# 下面这个就是压缩服务器项目,并且排除掉日志文件夹
comm = 'tar -zcvf 服务器备份包路径.tar.gz --exclude=服务器项目日志文件夹路径 服务器项目路径'
stdin, stdout, stderr = client.exec_command(comm)
stdout.readlines() # 要执行这句 要不然就快速关闭了
client.close()
# 下载服务器备份压缩包
t = paramiko.Transport(('服务器IP',服务器ssh端口))
t.connect(username = '服务器用户名', password = '服务器密码')
sftp = paramiko.SFTPClient.from_transport(t)
remotepath = '服务器备份压缩包路径' # 这里要用linux路径写法
localpath = '本机保存路径' # 这里要用window路径写法
sftp.get(remotepath, localpath)
t.close()
# 解压备份压缩包,这里用的window的cmd命令,可以用ssh连接本机,再用linux shell命令的,只是想尝试不同的做法而已,.tar.gz是linux特有的,window只能解压不能压缩生成
# 不能直接使用字符串,要使用占位符的形式来,也就是说不能用加号连接,我也不知道为什么,估计是路径斜杠的问题,但是测试过很多种了,也不得,真心求解
cmd = '"C:/Program Files/WinRAR/WinRAR" x %s * %s\\ -y' % ('压缩包路径', '解压路径')
os.system(cmd)
# 对比差异,比较大小或者最后修改时间,要注意的就是最后修改时间会不同,本机win7的时间和服务器win2008r2的时间是一样的,但是看下载回来的服务器压缩包里面的文件时间,有些文件,注意不是全部文件,只是有部分而已,它的时间会提前1秒,估计是因为经过linux系统产生了异常,文件大小这个倒没有发现过异常
s1 = os.path.getsize('源文件路径') # 获取大小
t1 = datetime.fromtimestamp(os.path.getmtime('源文件路径')) # 获取最后修改时间
s2 = os.path.getsize('目标文件路径')
t2 = datetime.fromtimestamp(os.path.getmtime('目标文件路径'))
timespan = (t2 - t1).total_seconds() # 最后修改时间差异值,判断3秒内的差异
if s1 != s2 or timespan >= 3:
pass # 是差异的
# 压缩差异,因为要用ssh上传到服务器操作,所以要linux的压缩格式.tar.gz
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('本机IP', 本机ssh端口, username='本机用户名', password='本机密码', timeout=4)
comm = 'tar -zcvf 压缩路径包路径.tar.gz 要压缩的文件夹路径'
stdin, stdout, stderr = client.exec_command(comm)
stdout.readlines() # 要执行这句 要不然就快速关闭了
# 上传到服务器,这个就要循环了,因为有A B两台服务器,它们的ssh端口,登录名,密码都是一样的
arrServer = ['服务器A_IP', '服务器B_IP']
for srv in arrServer:
t = paramiko.Transport((srv, 服务器端口))
t.connect(username = '服务器用户名', password = '服务器密码')
sftp = paramiko.SFTPClient.from_transport(t)
remotepath = '服务器保存压缩包路径' # 这里要用linux路径写法
localpath = '本机压缩包路径' # 这里要用window路径写法
sftp.put(localpath, remotepath)
t.close()
# 最后就是服务器解压,进行替换覆盖了
arrServer = ['服务器A_IP', '服务器B_IP']
for srv in arrServer:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(srv, 服务器端口, username = '服务器用户名', password = '服务器密码', timeout=4)
arrComm = []
# 以日期新建备份差异文件夹,用来解压差异文件
arrComm.append('mkdir 差异文件存放文件夹')
# 解压差异
arrComm.append('tar -zxvf 差异压缩包路径.tar.gz -C 差异文件存放文件夹')
# 拷贝差异
arrComm.append('cp -rf 差异文件存放文件夹 项目文件夹')
# 执行使用\n分割的多行命令
stdin, stdout, stderr = client.exec_command('\n'.join(arrComm))
stdout.readlines() # 要执行这句 要不然就快速关闭了
client.close()
来个效果图