脚本实现登录服务器执行命令+上传下载文件自动化
最近一直在调试一个客户的平台,但是每次的调试流程都是:通过winscp上传本地文件到服务器上某个固定路径,在xshell上输入make指令编译系统代码,编译成功后再通过winscp将新生成的烧录文件下载到本地。
整个流程重复性极强而且涉及到的文件夹路径也很固定,耗时也非常的长,故而想到用脚本来将这些操作实现自动化,不需要我守在电脑前面等着。
winscp的上传下载脚本
winscp这种ssh软件一般都会支持脚本,查了资料以后发现winscp还提供了脚本教程。在windows终端里输入winscp以后,再输入help就会看到软件支持的指令列表。
在winscp>后面输入 help XXX
,XXX就是指令列表中的某个指令,例如get指令。就会提供给你使用该指令的几个例子
通过官方提供的例子,可写出自己需要的上传/下载文件的脚本。
上传脚本:
open sftp://用户名:登录密码@10.XXX.10.XXX:22
cd /home/.../lib/firmware/
put -neweronly D:\Files\客户\...\代码编译相关\fw.bin ./
close
exit
脚本中第一句是登录服务器,sftp表示使用sftp文件协议,@后面跟着的是服务器ip地址,即主机名,:后跟着的是应用层端口号。每一部分应该填的值等价于在winscp中创建新会话时的值。
第二句是进入对应的路径,脚本中所有路径最好都写成绝对路径。第三句会将windows中对应目录里的fw.bin文件上传到服务器上的当前目录里("./"),并替换掉同名文件。
最后两句是关闭会话退出脚本。
同理,下载脚本:
open sftp://用户名:登录密码@10.XXX.10.XXX:22
cd /home/.../allbins/
get -neweronly rootfs.img cpuap.bin rootfs.tgz "D:\Files\客户\...\代码编译相关\shao lu - 78M\"
cd /home/.../wireless/
get -neweronly mydrv D:\Files\客户\...\代码编译相关\
close
exit
其中,第三句的neweronly意思是仅替换最新的这三个文件,目的文件夹之所以用双引号引起来是因为路径里包含了空格和特殊符号。
第五句是将“wireless/mydrv”这一整个文件夹都下载到“代码编译相关\mydrv”里,即更新这个同名文件夹以及里面的文件。
winscp调用脚本的方法是:(假设脚本文件为download.txt)
cmd终端里cd到脚本存放的目录,输入winscp /script=download.txt
即可调用当前目录下文件名为download.txt的脚本。
到这里,已经实现了大部分的自动化,现在还需将到服务器上输入指令编译代码这一操作和上传下载文件的脚本自动化调用起来。
python脚本前期准备
查了些资料也实践过,发现这部分脚本用python最适合我的需求。需要安装python+python的模块paramiko+python加密工具包pycrypto。
安装python需要将python加入系统环境变量里,能在cmd中调用成功即可。
如果没有安装paramiko,直接import会出错。
windows安装python的部分网上很多博客讲解,windows安装paramiko和pycrypto的部分可以看博客:windows 安装paramiko
按照上面这篇博客,我python版本2.7.16,安装了对应的以下版本:(版本一定要匹配)
安装成功后,再import不会有报错显示了。
python脚本
因为我大部分的操作只需要编译+下载,故以下的脚本里没有写自动调用上传脚本的部分。
make+download.py脚本如下:
import os
import paramiko
client = paramiko.SSHClient() # 前三行,通过paramiko实现ssh登录,登录到服务器上
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('10.XX.10.XX', 22, username='用户名', password='登录密码', timeout=4)
stdin, stdout, stderr = client.exec_command('cd /home/.../build/ ; make normal2 ****')
#执行两条指令,指令间用;隔开
err_flags = 0
for std in stdout.readlines():
print std # 将编译
if "recipe for target \'normal2\' failed" in std : #这是编译失败必出现的输出
err_flags = 1
client.close() # 退掉ssh连接
if err_flags != 1 :
print("*****SERVER!!!MAKE!!!SUCCESS!!!*****")
download_str = 'winscp /script=download.txt'
os.system(download_str) # 这个函数使指令download_str运行,并将结果显示在终端窗口上
else :
print("*****SERVER!!!MAKE!!!ERROR!!!*****") # 如果编译失败就无需调用下载文件的脚本了