使用paramiko远程执行
写部署脚本时,难免涉及到一些远程执行命令或者传输文件。
之前一直使用sh库,调用sh.ssh远程执行一些命令,sh.scp传输文件,但是实际使用中还是比较麻烦的,光是模拟用户登陆这一点,还需要单独定义方法模拟输入。
感受一下:
from sh import ssh
PASS = 'xxxx'
def ssh_interact(line, stdin):
line = line.strip()
print(line)
if line.endswith('password:'):
stdin.put(PASS)
ssh('x.x.x.x', _out=ssh_interact)
来自官方文档
后来发现paramiko库更加优雅、便捷,所以准备用pramiko替换掉sh。
之前通过同事了解到,paramiko在远程执行python脚本时,脚本中的输出内容可能会通过stderr这个管道输出出来,所以直接用paramiko的SSHClient类中的exec_command方法执行,通过读stderr管道中有无输出来判断命令是否成功执行的方式是行不通的。所以用更底层一些的Channel类的recv_exit_status方法判断执行退出码更好一些。
安装
可以通过使用pip install paramiko安装,细节这里不再赘述。
封装
首先定义几个异常
# coding: utf-8
import os.path
from paramiko import SSHClient, AutoAddPolicy, AuthenticationException
class ConnectError(Exception):
"""
连接错误时抛出的异常
"""
pass
class RemoteExecError(Exception):
"""
远程执行命令,失败时抛出的异常
"""
pass
class SCPError(Exception):
"""
远程下发文件时抛出的异常
"""
pass
...
class Remote(object):
def __init__(self, host, username, password=None, port=22, key_filename=None):
self.host = host
self.username = username
self.password = password
self.port = port
self.key_filename = key_filename
self._ssh = None
def _connect(self):
self._ssh = SSHClient()
self._ssh.set_missing_host_key_policy(AutoAddPolicy())
try:
if self.key_filename:
self._ssh.connect(self.host, username=self.username, port=self.port, key_filename=self.key_filename)
else:
self._ssh.connect(self.host, username=self.username, password=self.password, port=self.port)
except AuthenticationException:
self._ssh = None
raise ConnectionError('连接失败,请确认用户名、密码、端口或密钥文件是否有效')
except Exception as e:
self._ssh = None
raise ConnectionError('连接时出现意料外的错误:%s' % e)
def get_ssh(self):
if not self._ssh:
self._connect()
return self._ssh
实例化SSHClient类,通过它的connect()方法获取SSH连接。
需要注意的是,远程访问的主机若是第一次连接,属于未知设备需要认证,通过set_missing_host_key_policy()方法设置一种策略,这里使用的是AutoAddPolicy()。
这里的_connect支持两种方式登录,一种是提供主机的用户名密码,另一种是通过密钥文件。在连接时检查如果指定了密钥文件则使用这种方式登录,否则通过用户名密码登录。
_connect()虽然是实际的建立连接的方法,但实际对外接口是get_ssh(),如果已经有建立好的SSH连接直接返回,避免重复建立连接。
class Remote(object):
...
def ssh(self, cmd, root_password=None, get_pty=False, super=False):
cmd = self._prepare_cmd(cmd, root_password, super)
stdout = self._exec(cmd, get_pty)
return stdout
def _prepare_cmd(self, cmd, root_password=None, super=False):
if self.username != 'root' and super:
if root_password:
cmd = "echo '{}'|su - root -c '{}'".format(root_password, cmd)
else:
cmd = "echo '{}'|sudo -p '' -S su - root -c '{}'".format(self.password, cmd)
return cmd
def _exec(self, cmd, gty_pty=False):
channel = self.get_ssh().get_transport().open_session()
if get_pty:
channel.get_pty()
channel.exec_command(cmd)
stdout = channel.makefile('r', -1).readlines()
stderr = channel.makefile_stderr('r', -1).readlines()
ret_code = channel.recv_exit_status()
if ret_code:
msg = ''.join(stderr) if stderr else ''.join(stdout)
raise RemoteExecError(msg)
return stdout
在远程执行某些命令时,可能需要管理员权限,这种时候需要做一些判断,首先判断登录提供的用户名如果不是root,则需要对命令做一些修改。这里的修改有两种情况,一是,该普通用户本身就有sudo权限,只需要把执行的命令加到sudo之后执行就可以,还有一种是普通用户没有sudo权限,需要通过su先切换到root身份之后再执行,这种情况下需要提供root密码。
还有一点要注意的是get_pty这个参数,实际在远程执行sudo命令时,一般主机都会需要通过tty才能执行,通过把get_pty值设置为True,可以模拟tty,但是随之而来也会有一个问题,如果是远程执行一个需要长期运行的进程,例如启动nginx服务,当远程命令执行后SSH退出之后,此次运行的所有程序也会随之结束,所以在需要通过远程命令运行某些服务或程序时,是不能指定get_pty参数的;但同时,如果是普通用户远程登录,是没有权限执行service命令的。建议的一种方式是修改/etc/sudoers配置文件,注释掉Defaults requiretty这行。
class Remote(object):
...
def scp(self, local_file, remote_path):
if not os.path.exists(local_file):
raise SCPError("Local %s isn't exists" % local_file)
if not os.path.isfile(local_file):
raise SCPError("%s is not a File" % local_file)
sftp = self.get_ssh().open_sftp()
try:
sftp.put(local_file, remote_path)
except Exception as e:
raise SCPError(e)
先确认要下发的文件存在,并且是文件不是目录,如果不是则抛出异常。同时,remote_path需要是远程主机的文件绝对目录,例如/tmp/xxx.xxx,而不能是/tmp。
使用
# coding: utf-8
from remote_client import RemoteClient
rc = RemoteClient('10.1.100.1', 'test', 'test_pass')
rc.ssh('whoami') # [u'test\n']
rc.scp('/tmp/test.out', '/tmp/test.out')
总结
相较于sh,paramiko好用的不是一星半点,这里只是提供了一个简单的封装,paramiko本身还有很多其他用法,欢迎大家积极讨论。
以上只是本人的一点理解,如果有错误之处,欢迎指正。
使用paramiko远程执行的更多相关文章
- 使用paramiko远程执行命令、下发文件
写部署脚本时,难免涉及到一些远程执行命令或者传输文件. 之前一直使用sh库,调用sh.ssh远程执行一些命令,sh.scp传输文件,但是实际使用中还是比较麻烦的,光是模拟用户登陆这一点,还需要单独定义 ...
- Python学习总结 06 paramiko 远程执行命令
有时会需要在远程的机器上执行一个命令,并获得其返回结果.对于这种情况,python 可以很容易的实现. 1 工具 Python paramiko 1) Paramiko模块安装 在Linux的Term ...
- python之paramiko 远程执行命令
有时会需要在远程的机器上执行一个命令,并获得其返回结果.对于这种情况,python 可以很容易的实现. 1 .工具 Python paramiko 1) Paramiko模块安装 在Linux的Ter ...
- paramiko远程执行命令成功
- paramiko 远程执行多个命令
转发博客如下 https://blog.csdn.net/c_base_jin/article/details/86561445
- 【Python】模块学习之使用paramiko连接Linux,远程执行命令,上传下载、文件
本文主要介绍paramiko远程执行linux命令,及在服务器上进行文件的上传.下载 paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. ...
- Python ssh 远程执行shell命令
工具 python paramiko 远程执行命令 import paramiko ssh = paramiko.SSHClient() key = paramiko.AutoAddPolicy() ...
- Python 模块功能paramiko SSH 远程执行及远程下载
模块 paramiko paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现 ...
- 远程执行命令:paramiko
paramiko模块用于通过 ssh 登录到远程客户端主机并执行命令,常见用法如下: [root@localhost ~]$ yum install -y python-paramiko 通过用户名密 ...
随机推荐
- 为什么内存使用2G的苹果手机比内存使用4G的安卓机更流畅?
这是在国外一家网站看到的,分析得不错,原文如下: Why does the iPhone require less RAM than Android devices? There are people ...
- 短视频服务大PK,阿里云、腾讯云、又拍云、七牛云、金山云5强横向对比
继直播后,短视频又再次爆发,在这个风口,国内的各大云厂商也都相继推出了自己的一站式短视频解决方案.上周由于公司短视频功能开发的需要,对比了阿里云.腾讯云.又拍云.七牛云.金山云5家的短视频服务. 先介 ...
- css基础:样式属性
1.背景与前景:background-color::背景色,样式表优先级高. background-image:url(路径):设置背景图片 background-attachment:fixed:背 ...
- APPIUM 输入中文 之套路
java appium 在Capabilities 中添加 capabilities.setCapabilities("unicodeKeyboard",true);和 capa ...
- 【DDD】领域驱动设计实践 —— 架构风格及架构实例
概述 DDD为复杂软件的设计提供了指导思想,其将易发生变化的业务核心域放置在限定上下文中,在确保核心域一致性和内聚性的基础上,DDD可以被多种语言和多种技术框架实现,具体的框架实现需要根据实际的业务场 ...
- chrome开发工具指南(八)
编辑 DOM Chrome DevTools 的 Elements 面板中的 DOM 树视图可以显示当前网页的 DOM 结构.通过 DOM 更新实时修改页面的内容和结构. DOM 定义您的页面结构.每 ...
- 比较三个 CSS 预处理器:Sass、LESS 和 Stylus(上)
前沿 : 第一次写不够成熟,可能描述有所错误,还请大家修改指正,我会对已完成的文章进行修改. 一.什么是CSS预处理器 CSS预处理器定义了一种新的语言,基本的思想是用一种专门的编程语言,开发者只需要 ...
- poj 1149经典网络流构图
题意:m个猪圈,n个客户,每个客户给出选则猪圈的钥匙和需要购买猪的个数,其中每次客户购买时客户选则的猪圈数量可以相互更换,问最大购买数量. 思路:以客户作为除源点汇点之外的点,然后对于每个猪圈从源点连 ...
- webservice Dome--一个webservice的简单小实例
1.理解:webservice就是为了实现不同服务器上不同应用程序的之间的通讯 2.让我们一步一步的来做一个webservice的简单应用 1)新建一个空的web应用程序,在程序上右键,新建项目,选择 ...
- 换个角度审视NAT技术
NAT (Network address translation,网络地址转换 )是局域网连接到互联网的一个对接工作. 首先要知道NAT是一个技术或者说软件而不是协议 后面你会知道NAT 是偏应用层但 ...