最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用paramiko遠(yuǎn)程執(zhí)行命令、下發(fā)文件的實(shí)例

 更新時(shí)間:2017年10月01日 08:37:40   作者:agnewee  
下面小編就為大家?guī)?lái)一篇使用paramiko遠(yuǎn)程執(zhí)行命令、下發(fā)文件的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

寫(xiě)部署腳本時(shí),難免涉及到一些遠(yuǎn)程執(zhí)行命令或者傳輸文件。

之前一直使用sh庫(kù),調(diào)用sh.ssh遠(yuǎn)程執(zhí)行一些命令,sh.scp傳輸文件,但是實(shí)際使用中還是比較麻煩的,光是模擬用戶(hù)登陸這一點(diǎn),還需要單獨(dú)定義方法模擬輸入。

感受一下:

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)

來(lái)自官方文檔

后來(lái)發(fā)現(xiàn)paramiko庫(kù)更加優(yōu)雅、便捷,所以準(zhǔn)備用pramiko替換掉sh。

之前通過(guò)同事了解到,paramiko在遠(yuǎn)程執(zhí)行python腳本時(shí),腳本中的輸出內(nèi)容可能會(huì)通過(guò)stderr這個(gè)管道輸出出來(lái),所以直接用paramiko的SSHClient類(lèi)中的exec_command方法執(zhí)行,通過(guò)讀stderr管道中有無(wú)輸出來(lái)判斷命令是否成功執(zhí)行的方式是行不通的。所以用更底層一些的Channel類(lèi)的recv_exit_status方法判斷執(zhí)行退出碼更好一些。

安裝

可以通過(guò)使用pip install paramiko安裝,細(xì)節(jié)這里不再贅述。

封裝

首先定義幾個(gè)異常

# coding: utf-8
import os.path

from paramiko import SSHClient, AutoAddPolicy, AuthenticationException


class ConnectError(Exception):
  """
  連接錯(cuò)誤時(shí)拋出的異常
  """
  pass

class RemoteExecError(Exception):
  """
  遠(yuǎn)程執(zhí)行命令,失敗時(shí)拋出的異常
  """
  pass

class SCPError(Exception):
  """
  遠(yuǎn)程下發(fā)文件時(shí)拋出的異常
  """
  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('連接失敗,請(qǐng)確認(rèn)用戶(hù)名、密碼、端口或密鑰文件是否有效')
    except Exception as e:
      self._ssh = None
      raise ConnectionError('連接時(shí)出現(xiàn)意料外的錯(cuò)誤:%s' % e)

  def get_ssh(self):
    if not self._ssh:
      self._connect()
    return self._ssh

實(shí)例化SSHClient類(lèi),通過(guò)它的connect()方法獲取SSH連接。

需要注意的是,遠(yuǎn)程訪問(wèn)的主機(jī)若是第一次連接,屬于未知設(shè)備需要認(rèn)證,通過(guò)set_missing_host_key_policy()方法設(shè)置一種策略,這里使用的是AutoAddPolicy()。

這里的_connect支持兩種方式登錄,一種是提供主機(jī)的用戶(hù)名密碼,另一種是通過(guò)密鑰文件。在連接時(shí)檢查如果指定了密鑰文件則使用這種方式登錄,否則通過(guò)用戶(hù)名密碼登錄。

_connect()雖然是實(shí)際的建立連接的方法,但實(shí)際對(duì)外接口是get_ssh(),如果已經(jīng)有建立好的SSH連接直接返回,避免重復(fù)建立連接。

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

在遠(yuǎn)程執(zhí)行某些命令時(shí),可能需要管理員權(quán)限,這種時(shí)候需要做一些判斷,首先判斷登錄提供的用戶(hù)名如果不是root,則需要對(duì)命令做一些修改。這里的修改有兩種情況,一是,該普通用戶(hù)本身就有sudo權(quán)限,只需要把執(zhí)行的命令加到sudo之后執(zhí)行就可以,還有一種是普通用戶(hù)沒(méi)有sudo權(quán)限,需要通過(guò)su先切換到root身份之后再執(zhí)行,這種情況下需要提供root密碼。

還有一點(diǎn)要注意的是get_pty這個(gè)參數(shù),實(shí)際在遠(yuǎn)程執(zhí)行sudo命令時(shí),一般主機(jī)都會(huì)需要通過(guò)tty才能執(zhí)行,通過(guò)把get_pty值設(shè)置為T(mén)rue,可以模擬tty,但是隨之而來(lái)也會(huì)有一個(gè)問(wèn)題,如果是遠(yuǎn)程執(zhí)行一個(gè)需要長(zhǎng)期運(yùn)行的進(jìn)程,例如啟動(dòng)nginx服務(wù),當(dāng)遠(yuǎn)程命令執(zhí)行后SSH退出之后,此次運(yùn)行的所有程序也會(huì)隨之結(jié)束,所以在需要通過(guò)遠(yuǎn)程命令運(yùn)行某些服務(wù)或程序時(shí),是不能指定get_pty參數(shù)的;但同時(shí),如果是普通用戶(hù)遠(yuǎn)程登錄,是沒(méi)有權(quán)限執(zhí)行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)

先確認(rèn)要下發(fā)的文件存在,并且是文件不是目錄,如果不是則拋出異常。同時(shí),remote_path需要是遠(yuǎn)程主機(jī)的文件絕對(duì)目錄,例如/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')

總結(jié)

相較于sh,paramiko好用的不是一星半點(diǎn),這里只是提供了一個(gè)簡(jiǎn)單的封裝,paramiko本身還有很多其他用法,歡迎大家積極討論。

以上只是本人的一點(diǎn)理解,如果有錯(cuò)誤之處,歡迎指正。

以上這篇使用paramiko遠(yuǎn)程執(zhí)行命令、下發(fā)文件的實(shí)例就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • python使用mysql的兩種使用方式

    python使用mysql的兩種使用方式

    pymsql是Python中操作MySQL的模塊。這篇文章主要介紹了python使用mysql的兩種使用方式,需要的朋友可以參考下
    2018-03-03
  • Python獲取時(shí)光網(wǎng)電影數(shù)據(jù)的實(shí)例代碼

    Python獲取時(shí)光網(wǎng)電影數(shù)據(jù)的實(shí)例代碼

    這篇文章主要介紹了Python獲取時(shí)光網(wǎng)電影數(shù)據(jù),基本原理是先通過(guò)requests庫(kù),通過(guò)時(shí)光網(wǎng)自帶的電影數(shù)據(jù)API接口,獲取到指定的電影數(shù)據(jù),本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • 淺析python標(biāo)準(zhǔn)庫(kù)中的glob

    淺析python標(biāo)準(zhǔn)庫(kù)中的glob

    glob 文件名模式匹配,不用遍歷整個(gè)目錄判斷每個(gè)文件是不是符合。這篇文章主要介紹了python標(biāo)準(zhǔn)庫(kù)中的glob的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2020-03-03
  • python3如何清除過(guò)濾emoji表情

    python3如何清除過(guò)濾emoji表情

    這篇文章主要介紹了python3如何清除過(guò)濾emoji表情問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Python實(shí)現(xiàn)時(shí)間序列變化點(diǎn)檢測(cè)功能

    Python實(shí)現(xiàn)時(shí)間序列變化點(diǎn)檢測(cè)功能

    平穩(wěn)性是時(shí)間序列分析與預(yù)測(cè)的核心概念,在平穩(wěn)條件下,時(shí)間序列的統(tǒng)計(jì)特性(如均值)在時(shí)間維度上保持不變,僅存在隨機(jī)波動(dòng),但是時(shí)間序列通常會(huì)經(jīng)歷結(jié)構(gòu)性斷裂或變化,本文給大家介紹了Python實(shí)現(xiàn)時(shí)間序列變化點(diǎn)檢測(cè)功能,需要的朋友可以參考下
    2024-09-09
  • 利用Python命令行傳遞實(shí)例化對(duì)象的方法

    利用Python命令行傳遞實(shí)例化對(duì)象的方法

    最近在工作中遇到了一個(gè)問(wèn)題,需要接收啟動(dòng)腳本傳遞過(guò)來(lái)的實(shí)例化后的對(duì)象,通過(guò)在網(wǎng)上查找資料發(fā)現(xiàn)了兩個(gè)方法,文中通過(guò)實(shí)例代碼就給大家詳細(xì)介紹了這兩種方法,有需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。
    2016-11-11
  • python 實(shí)現(xiàn)多進(jìn)程日志輪轉(zhuǎn)ConcurrentLogHandler

    python 實(shí)現(xiàn)多進(jìn)程日志輪轉(zhuǎn)ConcurrentLogHandler

    這篇文章主要介紹了python 實(shí)現(xiàn)多進(jìn)程日志輪轉(zhuǎn)ConcurrentLogHandler,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • Python-VTK批量讀取二維切片并顯示三維模型

    Python-VTK批量讀取二維切片并顯示三維模型

    這篇文章主要介紹了Python-VTK批量讀取二維切片并顯示三維模型,文章基于python的相關(guān)資料展開(kāi)對(duì)主題的詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-04-04
  • Mysql數(shù)據(jù)庫(kù)反向生成Django里面的models指令方式

    Mysql數(shù)據(jù)庫(kù)反向生成Django里面的models指令方式

    這篇文章主要介紹了Mysql數(shù)據(jù)庫(kù)反向生成Django里面的models指令方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-05-05
  • python利用遞歸方法實(shí)現(xiàn)求集合的冪集

    python利用遞歸方法實(shí)現(xiàn)求集合的冪集

    這篇文章主要給大家介紹了關(guān)于python利用遞歸方法實(shí)現(xiàn)求集合的冪集的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09

最新評(píng)論

丰城市| 库伦旗| 苗栗县| 蒙城县| 双牌县| 固原市| 吉木萨尔县| 长丰县| 莱西市| 温州市| 娄烦县| 砚山县| 邵武市| 福安市| 张掖市| 得荣县| 呼玛县| 合阳县| 大理市| 乌拉特前旗| 营口市| 固始县| 盖州市| 平舆县| 海丰县| 莫力| 浦江县| 江孜县| 博兴县| 岫岩| 灵石县| 蓬莱市| 长岛县| 鲁甸县| 霸州市| 南京市| 衡南县| 西昌市| 紫金县| 郸城县| 富阳市|