paramiko 应用示例
实现密钥方式登录远程主机
实现自动密钥登录方式,第一步需要配置与目标设备的密钥认证支持,具体见 9.2.5 节,私钥文件可以存放在默认路径 "~/.ssh/id_rsa",当然也可以自定义,如本例的 "/home/key/id_rsa",通过 paramiko.RSAKey.from_private_key_file() 方法引用,详细代码如下:
#!/usr/bin/env python
import paramiko
import os
hostname = '192.168.1.21'
username = 'root'
paramiko.util.log_to_file('syslogin.log')
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
privatekey = os.path.expanduser('/home/key/id_rsa') # 定义私钥存放路径
key = paramiko.RSAKey.from_private_key_file(privatekey) # 创建私钥对象key
ssh.connect(hostname=hostname, username=username, pkey=key)
stdin, stdout, stderr = ssh.exec_command('free -m')
print(stdout.read())
ssh.close()
程序执行结果见图 6-1。
实现堡垒机模式下的远程命令执行
堡垒机环境在一定程度上提升了运营安全级别,但同时也提高了日常运营成本,作为管理的中转设备,任何针对业务服务器的管理请求都会经过此节点,比如 SSH 协议,首先运维人员在办公电脑通过 SSH 协议登录堡垒机,再通过堡垒机 SSH 跳转到所有的业务服务器进行维护操作,如图6-2所示。
我们可以利用 paramiko 的 invoke_shell 机制来实现通过堡垒机实现服务器操作,原理是 SSHClient.connect 到堡垒机后开启一个新的 SSH 会话(session),通过新的会话运行 "ssh user@IP" 去实现远程执行命令的操作。实现代码如下:
#!/usr/bin/env python
import paramiko
import os, sys, time
blip = "192.168.1.23" # 定义堡垒机信息
bluser = "root"
blpasswd = "KJsdiug45"
hostname = "192.168.1.21" # 定义业务服务器信息
username = "root"
password = "IS8t5jgrie"
port = 22
passinfo = '\'s password: ' # 输入服务器密码的前标志串
paramiko.util.log_to_file('syslogin.log')
ssh = paramiko.SSHClient() # ssh登录堡垒机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=blip, username=bluser, password=blpasswd)
channel = ssh.invoke_shell() # 创建会话,开启命令调用
channel.settimeout(10) # 会话命令执行超时时间,单位为秒
buff = ''
resp = ''
channel.send('ssh ' + username + '@' + hostname + '\n') # 执行ssh登录业务主机
while not buff.endswith(passinfo): # ssh登录的提示信息判断,输出串尾含有"\'s password:"时
try: # 退出while循环
resp = channel.recv(9999)
except Exception as e:
print('Error info:%s connection time.' % (str(e)))
channel.close()
ssh.close()
sys.exit()
buff += resp
if not buff.find('yes/no')==-1: #输出串尾含有"yes/no"时发送"yes"并回车
channel.send('yes\n')
buff=''
channel.send(password+'\n') #发送业务主机密码
buff=''
while not buff.endswith('# '): #输出串尾为"# "时说明校验通过并退出while循环
resp = channel.recv(9999)
if not resp.find(passinfo)==-1: #输出串尾含有"\'s password: "时说明密码不正确,
#要求重新输入
print('Error info: Authentication failed.')
channel.close() #关闭连接对象后退出
ssh.close()
sys.exit()
buff += resp
channel.send('ifconfig\n') #认证通过后发送ifconfig命令来查看结果
buff=''
try:
while buff.find('# ')==-1:
resp = channel.recv(9999)
buff += resp
except Exception as e:
print("error info:" + str(e))
print(buff) # 打印输出串
channel.close()
ssh.close()
运行结果如下:
# python /home/test/paramiko/simple3.py
ifconfig
eth0 Link encap:Ethernet HWaddr 00:50:56:28:63:2D
inet addr:192.168.1.21 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fe28:632d/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:3523007 errors:0 dropped:0 overruns:0 frame:0
TX packets:6777657 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:606078157 (578.0 MiB) TX bytes:1428493484 (1.3 GiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
显示 "inet addr:192.168.1.21" 说明命令已经成功执行。
实现堡垒机模式下的远程文件上传
实现堡垒机模式下的文件上传,原理是通过 paramiko 的 SFTPClient 将文件从办公设备上传至堡垒机指定的临时目录,如 /tmp,再通过 SSHClient 的 invoke_shell 方法开启 ssh 会话,执行 scp 命令,将 /tmp 下的指定文件复制到目标业务服务器上,如图6-3所示。
本示例具体使用 sftp.put() 方法上传文件至堡垒机临时目录,再通过 send() 方法执行 scp 命令,将堡垒机临时目录下的文件复制到目标主机,详细的实现源码如下:
#!/usr/bin/env python
import paramiko
import os, sys, time
blip = "192.168.1.23" # 定义堡垒机信息
bluser = "root"
blpasswd = " IS8t5jgrie"
hostname = "192.168.1.21" # 定义业务服务器信息
username = "root"
password = " KJsdiug45"
tmpdir = "/tmp"
remotedir = "/data"
localpath = "/home/nginx_access.tar.gz" # 本地源文件路径
tmppath = tmpdir + "/nginx_access.tar.gz" # 堡垒机临时路径
remotepath = remotedir + "/nginx_access_hd.tar.gz" # 业务主机目标路径
port = 22
passinfo = '\'s password: '
paramiko.util.log_to_file('syslogin.log')
t = paramiko.Transport((blip, port))
t.connect(username=bluser, password=blpasswd)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put(localpath, tmppath) # 上传本地源文件到堡垒机临时路径
sftp.close()
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=blip, username=bluser, password=blpasswd)
channel = ssh.invoke_shell()
channel.settimeout(10)
buff = ''
resp = ''
# scp中转目录文件到目标主机
channel.send('scp ' + tmppath + ' ' + username + '@' + hostname + ':' + remotepath + '\n')
while not buff.endswith(passinfo):
try:
resp = channel.recv(9999)
except Exception as e:
print('Error info:%s connection time.' % (str(e)))
channel.close()
ssh.close()
sys.exit()
buff += resp
if not buff.find('yes/no') == -1:
channel.send('yes\n')
buff = ''
channel.send(password + '\n')
buff = ''
while not buff.endswith('# '):
resp = channel.recv(9999)
if not resp.find(passinfo) == -1:
print('Error info: Authentication failed.')
channel.close()
ssh.close()
sys.exit()
buff += resp
print(buff)
channel.close()
ssh.close()
运行结果如下,如目标主机 /data/nginx_access_hd.tar.gz 存在,则说明文件已成功上传。
# python /home/test/paramiko/simple4.py
nginx_access.tar.gz 100% 1590KB 1.6MB/s 00:00
当然,整合以上两个示例,再引入主机清单及功能配置文件,可以实现更加灵活、强大的功能,大家可以自己动手,在实践中学习,打造适合自身业务环境的自动化运营平台。
参考提示
-
6.2 节和 6.3 节常用类说明与应用案例参考 http://docs.paramiko.org/en/1.13/ 官网文档。