写部署脚本时,难免涉及到一些远程执行命令或者传输文件。

之前一直使用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
# 远程执行命令
# Python Paramiko模块的安装与使用详解
# windows下安装python paramiko模块的代码
# paramiko模块安装和使用(远程登录服务器)
# Python Paramiko模块的使用实际案例
# Python paramiko模块的使用示例
# paramiko使用tail实时获取服务器的日志输出详解
# 的是
# 抛出
# 普通用户
# 也会
# 给大家
# 如果不是
# 几个
# 传输文件
# 就有
# 一是
# 之处
# 两种
# 只需
# 要把
# 可以通过
# 要注意
# 希望能
# 欢迎大家
# 还需要
# 要对
相关文章:
建站之星后台管理如何实现高效配置?
济南企业网站制作公司,济南社保单位网上缴费步骤?
再谈Python中的字符串与字符编码(推荐)
如何配置WinSCP新建站点的密钥验证步骤?
PHP正则匹配日期和时间(时间戳转换)的实例代码
南京做网站制作公司,南京哈发网络有限公司,公司怎么样,做网页美工DIV+CSS待遇怎么样?
制作网站的过程怎么写,用凡科建站如何制作自己的网站?
深圳防火门网站制作公司,深圳中天明防火门怎么编码?
如何在企业微信快速生成手机电脑官网?
小自动建站系统:AI智能生成+拖拽模板,多端适配一键搭建
黑客如何利用漏洞与弱口令入侵网站服务器?
网站制作难吗安全吗,做一个网站需要多久时间?
内网网站制作软件,内网的网站如何发布到外网?
深圳网站制作培训,深圳哪些招聘网站比较好?
如何配置IIS站点权限与局域网访问?
如何在Tomcat中配置并部署网站项目?
网站制作的方法有哪些,如何将自己制作的网站发布到网上?
常州自助建站:操作简便模板丰富,企业个人快速搭建网站
,石家庄四十八中学官网?
潍坊网站制作公司有哪些,潍坊哪家招聘网站好?
制作网站的网址是什么,请问后缀为.com和.com.cn还有.cn的这三种网站是分别是什么类型的网站?
视频网站app制作软件,有什么好的视频聊天网站或者软件?
深圳网站制作费用多少钱,读秀,深圳文献港这样的网站很多只提供网上试读,但有些人只要提供试读的文章就能全篇下载,这个是怎么弄的?
如何通过.red域名打造高辨识度品牌网站?
广东企业建站网站优化与SEO营销核心策略指南
北京的网站制作公司有哪些,哪个视频网站最好?
香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南
建站之星如何修改网站生成路径?
香港服务器WordPress建站指南:SEO优化与高效部署策略
深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?
免费制作海报的网站,哪位做平面的朋友告诉我用什么软件做海报比较好?ps还是cd还是ai这几个软件我都会些我是做网页的?
想学网站制作怎么学,建立一个网站要花费多少?
建站之星价格显示格式升级,你的预算足够吗?
如何制作一个表白网站视频,关于勇敢表白的小标题?
活动邀请函制作网站有哪些,活动邀请函文案?
网站企业制作流程,用什么语言做企业网站比较好?
SAX解析器是什么,它与DOM在处理大型XML文件时有何不同?
文字头像制作网站推荐软件,醒图能自动配文字吗?
网站规划与制作是什么,电子商务网站系统规划的内容及步骤是什么?
如何解决ASP生成WAP建站中文乱码问题?
成都品牌网站制作公司,成都营业执照年报网上怎么办理?
如何在七牛云存储上搭建网站并设置自定义域名?
如何批量查询域名的建站时间记录?
小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?
建站之星后台密码遗忘或太弱?如何重置与强化?
如何零成本快速生成个人自助网站?
建站之星安全性能如何?防护体系能否抵御黑客入侵?
网站制作公司排行榜,抖音怎样做个人官方网站
已有域名和空间如何快速搭建网站?
C++如何编写函数模板?(泛型编程入门)
*请认真填写需求信息,我们会在24小时内与您取得联系。