使用paramiko进行ssh工作
最近在单位写一个自动build的小工具。因为clearcase的setview命令实际上是激活一个新的shell,所以用简单的“串通”shell的脚本很难做到。
因为在邮件组里面看到有同样问题的Matt说用paramiko解决了问题,就试了试,过程还颇有点艰辛。
首先,paramiko没有直接的msi或者exe版本给Windows用户下载,而是需要在本地进行编译。而且python的easy_install工具在vista下面会报错,所以至少花了十几分钟才算安装完毕。
结果在用test.py验证安装的时候就报错了,说什么:
paramiko.SSHException: No suitable address
安装是我自己一步步弄得,难道搞错了?只好照着demo写了一个sftp的脚本,发现是可以跑的,干。
只好丢了封信给邮件组,然后自己开始找是啥问题。丢给邮件组的信至今没有回音(人气不行啊,paramiko),问题还是找到了。原来是1.7.5的paramiko增加了对ipv6的支持,结果引入了错误。更新了client.py后重新编译就可以用了。windows-1.7.5无错安装版可以在我这里下载。
paramiko-1.7.5 (253)
最后,虽然demo的例子也挺多,但是好像没有说清楚怎么用invoke_shell和get_pty以及照例奉上一段代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | """ This script is using for build the software package """ import sys import time import paramiko import traceback import ConfigParser """ The main class of the builder. """ class Builder: """Parses options from the ini file to create connection.""" def __init__(self,inifile): try: config = ConfigParser.ConfigParser() config.readfp(open(inifile)) self._ssh = paramiko.SSHClient() self._ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self._ssh.connect(config.get('host','server'), port=config.getint('host', 'port'), username=config.get('host','user'), password=config.get('host','password')) self._t = paramiko.Transport((config.get('host','server'), config.getint('host', 'port'))) self._t.start_client() self._t.auth_password(config.get('host','user'),config.get('host','password')) self._sftp = paramiko.SFTPClient.from_transport(self._t) except Exception, e: print '*** Caught exception: %s: %s' % (e.__class__, e) traceback.print_exc() try: self.closeConn() except: pass sys.exit(1) self._fpga = config.get('fpga compress','fpga') self._lpath = config.get('fpga compress','local_fpga_path') self._rpath = config.get('fpga compress','remote_fpga_path') self._oab = config.get('fpga compress','oab') self._xlf = config.get('xlf build','xlf') self._lmid = config.get('xlf build','lmid') self._xpp = config.get('xlf build','xpp') self._xdp = config.get('xlf build','xdp') self._rru = config.get('xlf build','rru') self._rruswdb = config.get('xlf build','rru_sw_db') self._xpl = config.get('xlf build','xpl') print("Your input fpga file is:"+self._lpath+self._fpga+"\n") print("Your ouput xlf file will be:"+self._xlf+"\n") """Run command on the server""" def runCmd(self, command): """run <command> Execute this command on all hosts in the list""" if command: stdin, stdout, stderr = self._ssh.exec_command(command) stdin.close() for line in stdout.read().splitlines(): print line else: print "usage: run <command>" """Upload the fpga and compress it to oab.bin""" def createOab(self): self._sftp.put(self._lpath+self._fpga,self._rpath+self._fpga) self.runCmd("hou_create_fpga -bf \"/home/ehholli/fpgainput/fpga.med\" -dn \"CXC 172 8213/1\" -of oab -dev \"XC2V6000,-4\" -dir /home/ehholli/fpgaoutput/") try: self._sftp.get(self._oab,'oab.bin') print("Fpga file compress successfully!") except Exception, e: print '*** Caught exception: %s: %s' % (e.__class__, e) traceback.print_exc() try: self.closeConn() except: pass sys.exit(1) """Make the tlf""" def genXlf(self): #open a interactive shell ct_chan = self._t.open_session() ct_chan.setblocking(0) ct_chan.get_pty() ct_chan.invoke_shell() #ct setview ehholli if(ct_chan.send_ready()): ct_chan.send("ct setview ehholli\r\n") time.sleep(10) #compile build_cmd="/vobs/rbs/hw/bcp/xp/deliv/solaris2/bin/xlf_gen -r "+self._xpp+" "+self._xdp+" "+self._rru \ +" -i "+self._oab+" "+self._rruswdb \ +" -o /home/ehholli/tmp/"+self._xlf \ +" -x "+self._xpl \ +" -lmid \""+self._lmid+"\"" \ +" -t \"au_applic\" -v \r\n" print(build_cmd) if(ct_chan.send_ready()): ct_chan.send(build_cmd) tCheck2 = 0 while not ct_chan.recv_ready(): time.sleep(5) tCheck2+=1 if tCheck2 >= 6: print 'time out'#TODO: add exeption here print(ct_chan.recv(65536)) ct_chan.close() time.sleep(10) #download the xlf file try: self._sftp.get("/home/ehholli/tmp/"+self._xlf,self._xlf) print("xlf file downloaded successfully!") except Exception, e: print '*** Caught exception: %s: %s' % (e.__class__, e) traceback.print_exc() try: self.closeConn() except: pass sys.exit(1) """Close everything we opened""" def closeConn(self): self._ssh.close() self._sftp.close() self._t.close() if __name__=='__main__': # setup logging paramiko.util.log_to_file('demo_builder.log') b=Builder('cfg.ini') b.createOab() b.genXlf() #b.runCmd('ls') b.closeConn() |