python模块paramiko与ssh

paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。paramiko支持Linux, Solaris, BSD, MacOS X, Windows等平台通过SSH从一个平台连接到另外一个平台。利用该模块,可以方便的进行ssh连接和sftp协议进行sftp文件传输。

一、paramiko模块的安装

paramiko模块依赖PyCrypto模块,而PyCrypto需要GCC库编译,不过一般发行版的源里带有该模块。这里以centos6为例,直接借助以下命令可以直接完成安装:

 
 
  1. # yum install gcc python-crypto python-paramiko python-devel -y

windows版下可以安装windows版的GCC(MinGW),然后编辑安装pycrypto和paramiko ,下载安成后,直接运行python.exe setup.py build 和 python.exe setup.py install 就可以了。

二、paramiko的连接

使用paramiko模块有两种连接方式,一种是通过paramiko.SSHClient()函数,另外一种是通过paramiko.Transport()函数。

方法一:

 
 
  1. import paramiko
  2. ssh = paramiko.SSHClient()
  3. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  4. ssh.connect("某IP地址",22,"用户名", "口令")

上面的第二行代码的作用是允许连接不在know_hosts文件中的主机。

方法二:

 
 
  1. import paramiko
  2. t = paramiko.Transport(("主机","端口"))
  3. t.connect(username = "用户名", password = "口令")

如果连接远程主机需要提供密钥,上面第二行代码可改成:

 
 
  1. t.connect(username = "用户名", password = "口令", hostkey="密钥")

三、paramiko ssh连接

以下是一个简单的通过paramiko模块定义的ssh连接并执行命令的函数,如下:

 
 
  1. #!/usr/bin/python
  2. #-*- coding: utf-8 -*-
  3. import paramiko
  4. #paramiko.util.log_to_file('/tmp/sshout')
  5. def ssh2(ip,username,passwd,cmd):
  6. try:
  7. ssh = paramiko.SSHClient()
  8. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  9. ssh.connect(ip,22,username,passwd,timeout=5)
  10. stdin,stdout,stderr = ssh.exec_command(cmd)
  11. # stdin.write("Y") #简单交互,输入 ‘Y’
  12. print stdout.read()
  13. # for x in stdout.readlines():
  14. # print x.strip("n")
  15. print '%stOKn'%(ip)
  16. ssh.close()
  17. except :
  18. print '%stErrorn'%(ip)
  19. ssh2("192.168.0.102","root","361way","hostname;ifconfig")
  20. ssh2("192.168.0.107","root","123456","ifconfig")

其中第四行的日志部分,是记录ssh连接交互时的一些信息,可以看做是类似于debug的输出,一般情况下不需要开启。

stdin.write部分是用于交互情况下,通过该命令可以执行交互。注意这里可能会引起歧义,这里的交互并不是ssh连接过程中出现的让输入yes的交互,因为paramiko模块在连接过程中会自动处理好yes确认。这里的交互是指后面的cmd需要的执行的程序可能出现交互的情况下,可以通过该参数进行交互。

stdout标准输出,在输出内容比较少时,可以通过直接使用read读取出所有的输出;但在输出内容比较多时,建议通过按行读取进行处理。不过按行读取时,每行结尾会有换行符n,这样输出的结果很不美观。可以通过strip进行字符串的处理。

在函数调用过程中需要注意的是,IP、username、passwd都是属于字符串型的,所以需要加引号。后面执行的cmd,如果有多个命令需要操作时,需要通过分号进行分割。

四、paramiko sftp示例

单个文件小传下载的示例:

 
 
  1. import paramiko
  2. #建立一个加密的管道
  3. scp=paramiko.Transport(('192.168.0.102',22))
  4. #建立连接
  5. scp.connect(username='root',password='361way')
  6. #建立一个sftp客户端对象,通过ssh transport操作远程文件
  7. sftp=paramiko.SFTPClient.from_transport(scp)
  8. #Copy a remote file (remotepath) from the SFTP server to the local host
  9. sftp.get('/root/testfile','/tmp/361way')
  10. #Copy a local file (localpath) to the SFTP server as remotepath
  11. sftp.put('/root/crash-6.1.6.tar.gz','/tmp/crash-6.1.6.tar.gz')
  12. scp.close()

一个目录下多个文件上传下载的示例:

 
 
  1. #!/usr/bin/env python
  2. #-*- coding: utf-8 -*-
  3. import paramiko,datetime,os
  4. hostname='192.168.0.102'
  5. username='root'
  6. password='361way'
  7. port=22
  8. local_dir='/tmp/getfile'
  9. remote_dir='/tmp/abc'
  10. try:
  11. t=paramiko.Transport((hostname,port))
  12. t.connect(username=username,password=password)
  13. sftp=paramiko.SFTPClient.from_transport(t)
  14. #files=sftp.listdir(dir_path)
  15. files=sftp.listdir(remote_dir)
  16. for f in files:
  17. print ''
  18. print '#########################################'
  19. print 'Beginning to download file from %s %s ' % (hostname,datetime.datetime.now())
  20. print 'Downloading file:',os.path.join(remote_dir,f)
  21. sftp.get(os.path.join(remote_dir,f),os.path.join(local_dir,f))#下载
  22. #sftp.put(os.path.join(local_dir,f),os.path.join(remote_dir,f))#上传
  23. print 'Download file success %s ' % datetime.datetime.now()
  24. print ''
  25. print '##########################################'
  26. t.close()
  27. except Exception:
  28. print "connect error!"

注:本处的目录下所有文件进行下载或上传的示例中,在遇到目录下还有嵌套的目录存在时,会将目录也当做文件进行处理,所以如果想要更加的完美的话,可以通过引入stat模块下的S_ISDIR方法进行处理

paramiko.transport对象也支持以socket的方式进行连接,如下示例:

 
 
  1. import paramiko
  2. transport = paramiko.Transport(('localhost',22))
  3. transport.connect(username='root', password = 'password')
  4. sftp = paramiko.SFTPClient.from_transport(transport)
  5. sftp.get(remotefile,localfile)
  6. #如果是上传则用:
  7. #sftp.put(localfile, remotefile)
  8. transport.close()
  9. #用socket连接
  10. tcpsock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  11. tcpsock.settimeout(5)
  12. tcpsock.connect((ip,22),)
  13. ssh = paramiko.Transport(tcpsock)
  14. ssh.connect(username=user,password=password)
  15. sftpConnect=paramiko.SFTPClient.from_transport(ssh)


五、利用paramiko实现ssh的交互式连接

以下是通过paramiko模块直接用ssh协议登陆到远程服务器的操作代码,这里先定义一个interactive模块,代码如下:

 
 
  1. import socket
  2. import sys
  3. # windows does not have termios...
  4. try:
  5. import termios
  6. import tty
  7. has_termios = True
  8. except ImportError:
  9. has_termios = False
  10. def interactive_shell(chan):
  11. if has_termios:
  12. posix_shell(chan)
  13. else:
  14. windows_shell(chan)
  15. def posix_shell(chan):
  16. import select
  17. oldtty = termios.tcgetattr(sys.stdin)
  18. try:
  19. tty.setraw(sys.stdin.fileno())
  20. tty.setcbreak(sys.stdin.fileno())
  21. chan.settimeout(0.0)
  22. while True:
  23. r, w, e = select.select([chan, sys.stdin], [], [])
  24. if chan in r:
  25. try:
  26. x = chan.recv(1024)
  27. if len(x) == 0:
  28. print 'rn*** EOFrn',
  29. break
  30. sys.stdout.write(x)
  31. sys.stdout.flush()
  32. except socket.timeout:
  33. pass
  34. if sys.stdin in r:
  35. x = sys.stdin.read(1)
  36. if len(x) == 0:
  37. break
  38. chan.send(x)
  39. finally:
  40. termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
  41. # thanks to Mike Looijmans for this code
  42. def windows_shell(chan):
  43. import threading
  44. sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.rnrn")
  45. def writeall(sock):
  46. while True:
  47. data = sock.recv(256)
  48. if not data:
  49. sys.stdout.write('rn*** EOF ***rnrn')
  50. sys.stdout.flush()
  51. break
  52. sys.stdout.write(data)
  53. sys.stdout.flush()
  54. writer = threading.Thread(target=writeall, args=(chan,))
  55. writer.start()
  56. try:
  57. while True:
  58. d = sys.stdin.read(1)
  59. if not d:
  60. break
  61. chan.send(d)
  62. except EOFError:
  63. # user hit ^Z or F6
  64. pass

代码内容可以从paramiko 在github项目上的demo里获取。再另外写一个ssh_inter.py的交互主程序,内容如下:

 
 
  1. import paramiko
  2. import interactive
  3. #记录日志
  4. paramiko.util.log_to_file('/tmp/test')
  5. #建立ssh连接
  6. ssh=paramiko.SSHClient()
  7. ssh.load_system_host_keys()
  8. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  9. ssh.connect('192.168.0.102',port=22,username='root',password='xxxxxx',compress=True)
  10. #建立交互式shell连接
  11. channel=ssh.invoke_shell()
  12. #建立交互式管道
  13. interactive.interactive_shell(channel)
  14. #关闭连接
  15. channel.close()
  16. ssh.close()

执行效果就像我们平时直接使用ssh登录一样。

解决传送暂停:

#!/usr/bin/python
#-*- encoding: utf8 -*-


import paramiko,os
import socket


host = '10.6.12.217'
port = 22
user = 'holatek'
passwd = 'jmgo++2011'


tcpsock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcpsock.settimeout(None)
tcpsock.connect((host,port),)
testssh = paramiko.Transport(tcpsock)
testssh.connect(username=user,password=passwd)
testsftp = paramiko.SFTPClient.from_transport(testssh)
localdir='/data/mqserver/'
localfiles = os.popen('ls %s' %(localdir))
for lfile in localfiles.readlines():
if "author" in str(lfile):
rfile = '%s%s'%(localdir,lfile)
lfile = '%s%s'%(localdir,lfile)
testsftp.put(lfile.strip(),rfile)


sqldir='/data/mysqlbackup/'
sqlfiles = os.popen('ls %s' %(sqldir))
for lfile in sqlfiles.readlines():
print lfile
rfile ='%s%s'%(sqldir,lfile)
lfile = '%s%s'%(sqldir,lfile)
testsftp.put(lfile.strip(),rfile)


testsftp.close()
testssh.close()
tcpsock.close()


六、总结

paramiko模块是一个比较强大的ssh连接模块,以上的示例只是列出了该模块的一些简单的使用方法,还可以使用threading模块加块程序并发的速度;也可以使用configparser模块处理配置文件,而我们将所有IP、用户信息操作都放入配置文件;使用setproctitle模块为执行的程序加一个容易区分的title等。

同样,虽然连fabric这样大名鼎鼎的软件使用的ssh都是用paramiko模块进行的封装,不过你依然可以选择不使用它,你也可以选择pexpect模块实现封装一个简易的ssh连接工具、或者使用同样比较火的salt-ssh模块。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值