<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          原來(lái)Python是這樣連接遠(yuǎn)程主機(jī)的,你會(huì)嗎?

          共 13981字,需瀏覽 28分鐘

           ·

          2021-08-10 17:19

          導(dǎo)語(yǔ):

          在軟件測(cè)試的過(guò)程中,涉及到遠(yuǎn)程Linux主機(jī)環(huán)境測(cè)試的時(shí)候,難免會(huì)遇到需要執(zhí)行shell命令的場(chǎng)景,比如通過(guò)shell命令去配置一些環(huán)境或者去檢查用例執(zhí)行的結(jié)果等等,那么就是用到了比較常用的工具paramiko。

          paramiko庫(kù)有兩種連接主機(jī)的方式,

          • 一種是使用用戶名和密碼;

          • 一種是使用秘鑰連接。

          當(dāng)使用用戶名密碼連接時(shí)遇到一個(gè)異常如下:
          當(dāng)你連接的對(duì)方主機(jī)有SSH秘鑰的時(shí)候,在使用用戶名密碼連接的時(shí)候:
          ValueError: ('Invalid private key', [_OpenSSLErrorWithText(code=67764350, lib=4, func=160, reason=126, reason_text=b'error:040A007E:rsa routines:RSA_check_key_ex:iqmp not inverse of q')])

          解決辦法1:

          搜索了很久,一直找不到答案。
          仔細(xì)端詳之后,決定卸載當(dāng)前版本paramiko2.7.1,然后重新安裝一下,發(fā)現(xiàn)有新的版本paramiko2.7.2,還真就解決問(wèn)題了。

          pip uninstall paramiko #先卸載原來(lái)安裝的
          pip install paramiko  #再重新安裝一下,問(wèn)題搞定

          解決辦法2:

          在這個(gè)ssh.connect(...)里面加入 allow_agent=False,look_for_keys=False,如下

          ssh.connect(ip, port, username, passwd, timeout=5,allow_agent=False,look_for_keys=False)

          再來(lái)說(shuō)說(shuō)paramiko的使用:

          def test1(ip, port, username, passwd, cmd):
              import paramiko
              try:
                  ssh = paramiko.SSHClient() #創(chuàng)建一個(gè)ssh對(duì)象
                  ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())  # 允許連接know_hosts中不存在的主機(jī)
                  ssh.connect(ip, port, username, passwd, timeout=5# 連接服務(wù)器,其中timeout的是超時(shí)時(shí)間
                  stdin, stdout, stderr = ssh.exec_command(cmd) # 執(zhí)行命令,并獲取結(jié)果
                  print(stdout.read().decode('utf-8'))  # 以u(píng)tf-8編碼對(duì)結(jié)果進(jìn)行解碼
                  ssh.close() #關(guān)閉ssh
              except Exception as e:
                  print('%s' % e)

          if __name__ == '__main__':
              test1("10.0.132.45"22"root""root""ls -al")

          ssh是一個(gè)協(xié)議,OpenSSH是其中一個(gè)開(kāi)源實(shí)現(xiàn),paramiko是Python的一個(gè)庫(kù),實(shí)現(xiàn)了SSHv2協(xié)議(底層使用cryptography)。

          有了Paramiko以后,我們就可以在Python代碼中直接使用SSH協(xié)議對(duì)遠(yuǎn)程服務(wù)器執(zhí)行操作,而不是通過(guò)ssh命令對(duì)遠(yuǎn)程服務(wù)器進(jìn)行操作。下面主要介紹一下Paramiko的一些相關(guān)概念。

          在這里插入圖片描述

          Paramiko介紹

          paramiko包含兩個(gè)核心組件:SSHClient和SFTPClient。

          在這里插入圖片描述
          • SSHClient的作用類似于Linux的ssh命令,是對(duì)SSH會(huì)話的封裝,該類封裝了傳輸(Transport),通道(Channel)及SFTPClient建立的方法(open_sftp),通常用于執(zhí)行遠(yuǎn)程命令。

          • SFTPClient的作用類似與Linux的sftp命令,是對(duì)SFTP客戶端的封裝,用以實(shí)現(xiàn)遠(yuǎn)程文件操作,如文件上傳、下載、修改文件權(quán)限等操作。

          Paramiko中的幾個(gè)基礎(chǔ)名詞:

          • Channel:是一種類Socket,一種安全的SSH傳輸通道;

          • Transport:是一種加密的會(huì)話,使用時(shí)會(huì)同步創(chuàng)建了一個(gè)加密的Tunnels(通道),這個(gè)Tunnels叫做Channel;

          • Session:是client與Server保持連接的對(duì)象,用connect()/start_client()/start_server()開(kāi)始會(huì)話。

          Paramiko的基本使用

          1. SSHClient常用的方法介紹

          (1) connect():實(shí)現(xiàn)遠(yuǎn)程服務(wù)器的連接與認(rèn)證,對(duì)于該方法只有hostname是必傳參數(shù)。

          常用參數(shù)

          • hostname 連接的目標(biāo)主機(jī)

          • port=SSH_PORT 指定端口

          • username=None 驗(yàn)證的用戶名

          • password=None 驗(yàn)證的用戶密碼

          • pkey=None 私鑰方式用于身份驗(yàn)證

          • key_filename=None 一個(gè)文件名或文件列表,指定私鑰文件

          • timeout=None 可選的tcp連接超時(shí)時(shí)間

          • allow_agent=True, 是否允許連接到ssh代理,默認(rèn)為T(mén)rue 允許l

          • ook_for_keys=True 是否在~/.ssh中搜索私鑰文件,默認(rèn)為T(mén)rue 允許

          • compress=False, 是否打開(kāi)壓縮

          (2) set_missing_host_key_policy():設(shè)置遠(yuǎn)程服務(wù)器沒(méi)有在know_hosts文件中記錄時(shí)的應(yīng)對(duì)策略。
          目前支持三種策略:
          設(shè)置連接的遠(yuǎn)程主機(jī)沒(méi)有本地主機(jī)密鑰或HostKeys對(duì)象時(shí)的策略,目前支持三種:

          • AutoAddPolicy 自動(dòng)添加主機(jī)名及主機(jī)密鑰到本地HostKeys對(duì)象,不依賴load_system_host_key的配置。即新建立ssh連接時(shí)不需要再輸入yes或no進(jìn)行確認(rèn)

          • WarningPolicy 用于記錄一個(gè)未知的主機(jī)密鑰的python警告。并接受,功能上和AutoAddPolicy類似,但是會(huì)提示是新連接

          • RejectPolicy 自動(dòng)拒絕未知的主機(jī)名和密鑰,依賴load_system_host_key的配置。此為默認(rèn)選項(xiàng)

          (3) exec_command():在遠(yuǎn)程服務(wù)器執(zhí)行Linux命令的方法。

          在這里插入圖片描述

          (4) open_sftp():在當(dāng)前ssh會(huì)話的基礎(chǔ)上創(chuàng)建一個(gè)sftp會(huì)話。該方法會(huì)返回一個(gè)SFTPClient對(duì)象。

          利用SSHClient對(duì)象的open_sftp()方法,可以直接返回一個(gè)基于當(dāng)前連接的sftp對(duì)象,可以進(jìn)行文件的上傳等操作.

          sftp = client.open_sftp() 
          sftp.put('test.txt','text.txt'

          Paramiko使用的七大案例

          1. paramiko遠(yuǎn)程密碼連接

          import paramiko 
          ##1.創(chuàng)建一個(gè)ssh對(duì)象 
          client = paramiko.SSHClient() 
          #2.解決問(wèn)題:如果之前沒(méi)有,連接過(guò)的ip,會(huì)出現(xiàn)選擇yes或者no的操作, 
          ##自動(dòng)選擇yes 
          client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
          #3.連接服務(wù)器 
          client.connect(hostname='172.25.254.31'
           port=22
           username='root'
           password='westos'
          #4.執(zhí)行操作 
          stdin,stdout, stderr = client.exec_command('hostname'
          #5.獲取命令執(zhí)行的結(jié)果 
          result=stdout.read().decode('utf-8'
          print(result) 
          #6.關(guān)閉連接 
          client.close() 
          1. 使用sftp上傳文件

          import paramiko 
          #獲取Transport實(shí)例 
          tran = paramiko.Transport("172.25.254.31",22
          #連接SSH服務(wù)端 
          tran.connect(username = "root", password = "westos"
          #獲取SFTP實(shí)例 
          sftp = paramiko.SFTPClient.from_transport(tran) 
          #設(shè)置上傳的本地/遠(yuǎn)程文件路徑 
          localpath="passwd.html" ##本地文件路徑 
          remotepath="/home/kiosk/Desktop/fish" ##上傳對(duì)象保存的文件路徑 
          #執(zhí)行上傳動(dòng)作 
          sftp.put(localpath,remotepath) 
          tran.close() 
          1. 使用sftp下載文件

          import paramiko 
          #獲取SSHClient實(shí)例 
          client = paramiko.SSHClient() 
          client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
          #連接SSH服務(wù)端 
          client.connect("172.25.254.31",username="root",password="westos"
          #獲取Transport實(shí)例 
          tran = client.get_transport() 
          #獲取SFTP實(shí)例 
          sftp = paramiko.SFTPClient.from_transport(tran) 
          remotepath='/home/kiosk/Desktop/fish' 
          localpath='/home/kiosk/Desktop/fish' 
          sftp.get(remotepath, localpath) 
          client.close() 
          1. 批量遠(yuǎn)程密碼連接

          from paramiko.ssh_exception import NoValidConnectionsError 
          from paramiko.ssh_exception import AuthenticationException 
          def connect(cmd,hostname,port=22,username='root',passwd='westos'): 
           import paramiko 
           ##1.創(chuàng)建一個(gè)ssh對(duì)象 
           client = paramiko.SSHClient() 
           #2.解決問(wèn)題:如果之前沒(méi)有,連接過(guò)的ip,會(huì)出現(xiàn)選擇yes或者no的操作, 
           ##自動(dòng)選擇yes 
           client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
           #3.連接服務(wù)器 
           try
           client.connect(hostnamehostname=hostname, 
           portport=port, 
           usernameusername=username, 
           password=passwd) 
           print('正在連接主機(jī)%s......'%(hostname)) 
           except NoValidConnectionsError as e: ###用戶不存在時(shí)的報(bào)錯(cuò) 
           print("連接失敗"
           except AuthenticationException as t: ##密碼錯(cuò)誤的報(bào)錯(cuò) 
           print('密碼錯(cuò)誤'
           else
           #4.執(zhí)行操作 
           stdin,stdout, stderr = client.exec_command(cmd) 
           #5.獲取命令執(zhí)行的結(jié)果 
           result=stdout.read().decode('utf-8'
           print(result) 
           #6.關(guān)閉連接 
           finally
           client.close() 
          with open('ip.txt'as f: #ip.txt為本地局域網(wǎng)內(nèi)的一些用戶信息 
           for line in f: 
           lineline = line.strip() ##去掉換行符 
           hostname,port,username,passwd= line.split(':'
           print(hostname.center(50,'*')) 
           connect('uname', hostname, port,username,passwd) 
          1. paramiko基于公鑰密鑰連接

          import paramiko 
          from paramiko.ssh_exception import NoValidConnectionsError, AuthenticationException 
          def connect(cmd, hostname, port=22, user='root'): 
           client = paramiko.SSHClient()  
           private_key = paramiko.RSAKey.from_private_key_file('id_rsa'
           ###id_rsa為本地局域網(wǎng)密鑰文件 
           client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
           try
           client.connect(hostnamehostname=hostname, 
           portport=port, 
           userusername=user, 
           pkey=private_key 
           ) 
           stdin, stdout, stderr = client.exec_command(cmd) 
           except NoValidConnectionsError as e: 
           print("連接失敗"
           except AuthenticationException as e: 
           print("密碼錯(cuò)誤"
           else
           result = stdout.read().decode('utf-8'
           print(result) 
           finally
           client.close() 
          for count in range(254): 
           host = '172.25.254.%s' %(count+1
           print(host.center(50'*')) 
           connect('uname', host) 
          1. 基于密鑰的上傳和下載

          import paramiko 
          private_key = paramiko.RSAKey.from_private_key_file('id_rsa'
          tran = paramiko.Transport('172.25.254.31',22
          tran.connect(username='root',password='westos'
          #獲取SFTP實(shí)例 
          sftp = paramiko.SFTPClient.from_transport(tran) 
          remotepath='/home/kiosk/Desktop/fish8' 
          localpath='/home/kiosk/Desktop/fish1' 
          sftp.put(localpath,remotepath) 
          sftp.get(remotepath, localpath) 
          1. paramiko的再封裝

          import os 
          import paramiko 
          from paramiko.ssh_exception import NoValidConnectionsError, AuthenticationException, SSHException 
          class SshRemoteHost(object): 
           def __init__(self, hostname, port, user, passwd, cmd): 
           self.hostname = hostname 
           self.port = port 
           self.user = user 
           self.passwd = passwd 
           self.cmd = cmd 
           def run(self): 
           """默認(rèn)調(diào)用的內(nèi)容""" 
           # cmd hostname 
           # put 
           # get 
           cmd_str = self.cmd.split()[0# cmd 
           # 類的反射,判斷類里面是否可以支持該操作 
           if hasattr(self, 'do_'+ cmd_str): # do_cmd 
           getattr(self, 'do_'+cmd_str)() 
           else
           print("目前不支持該功能"
           def do_cmd(self): 
           client = paramiko.SSHClient() 
           client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
           try
           client.connect(hostname=self.hostname, 
           port=self.port, 
           username=self.user, 
           password=self.passwd) 
           print("正在連接%s......." % (self.hostname)) 
           except NoValidConnectionsError as e: 
           print("連接失敗"
           except AuthenticationException as e: 
           print("密碼錯(cuò)誤"
           else
           # 4. 執(zhí)行操作 
           cmd = ''.join(self.cmd.split()[1:]) ##將輸入的后面的取出,作為 
           stdin, stdout, stderr = client.exec_command(cmd) 
           # 5.獲取命令執(zhí)行的結(jié)果 
           result = stdout.read().decode('utf-8'
           print(result) 
           finally
           # 6.關(guān)閉連接 
           client.close() 
           def do_put(self): 
           ###put /tmp/passwd ###將本地的/tmp/passwd上傳到遠(yuǎn)端/tmp/passwd 
           print('正在上傳...'
           try
           #獲取Transport實(shí)例 
           tran = paramiko.Transport(self.hostname,int(self.port)) ##由于端口為整形,而我們用split方法得到的是str 
           #連接SSH服務(wù)端 
           tran.connect(username = self.user, password = self.passwd) 
           except SSHException as e: 
           print('連接失敗'
           else
           #獲取SFTP實(shí)例 
           sftp = paramiko.SFTPClient.from_transport(tran) 
           newCmd = self.cmd.split()[1:] 
           if len(newCmd) == 2
           #設(shè)置上傳的本地/遠(yuǎn)程文件路徑 
           localpath=newCmd[0
           remotepath=newCmd[1
           #執(zhí)行上傳動(dòng)作 
           sftp.put(localpath,remotepath) 
           print('%s文件上傳到%s主機(jī)的%s文件成功' %(localpath,self.hostname,remotepath)) 
           else
           print('上傳文件信息錯(cuò)誤'
           tran.close() 
           def do_get(self): 
           print('正在下載...'
           try
           # 獲取Transport實(shí)例 
           tran = paramiko.Transport(self.hostname, int(self.port)) ##由于端口為整形,而我們用split方法得到的是str 
           # 連接SSH服務(wù)端 
           tran.connect(username=self.user, password=self.passwd) 
           except SSHException as e: 
           print('連接失敗'
           else
           # 獲取SFTP實(shí)例 
           sftp = paramiko.SFTPClient.from_transport(tran) 
           newCmd = self.cmd.split()[1:] 
           if len(newCmd) == 2
           # 設(shè)置下載的本地/遠(yuǎn)程文件路徑 
           localpath = newCmd[1
           remotepath = newCmd[0
           # 執(zhí)行上傳動(dòng)作 
           sftp.get( remotepath,localpath) 
           print('%s主機(jī)的%s文件下載到%s文件成功' % (self.hostname,remotepath,localpath)) 
           else
           print('上傳文件信息錯(cuò)誤'
           tran.close() 
          import paramiko 
          import os 
          # 1.選擇操作的主機(jī)組:eg:mysql,web,ftp 
          groups=[file.rstrip('.conf'for file in os.listdir('conf')] 
          print("主機(jī)組顯示:".center(50,'*')) 
          for group in groups: 
           print('\t',group) 
          choiceGroup = input("選擇批量操作的主機(jī)組(eg:mysql):"
          ##2.根據(jù)選擇的主機(jī)組,顯示包含的主機(jī)IP/主機(jī)名 
          # 1).打開(kāi)文件conf/choiceGroup.conf 
          # 2).依次讀取文件每一行 
          # 3).只拿出 
          print("主機(jī)組包含的主機(jī):".center(50,'*')) 
          with open('conf/%s.conf' %(choiceGroup)) as f: 
           for line in f: 
           print(line.split(':')[0]) 
           f.seek(0,0##把指針移動(dòng)到文件最開(kāi)始 
           hostinfos = [line.strip() for line in f.readlines()] 
          ###3.讓用戶確認(rèn)信息,選擇需要批量執(zhí)行的命令; 
          ## -cmd shell 命令 
          ## -put 本地文件 遠(yuǎn)程文件 
          ## -get 遠(yuǎn)程文件 本地文件 
          print("批量執(zhí)行腳本".center(50,"*")) 
          while True
           cmd = input('>>:').strip() 
           if cmd : 
           if cmd == 'exit' or cmd == "quit"
           print("執(zhí)行完畢,正在退出"
           break 
           for info in hostinfos: 
           host,port,user,passwd = info.split(':'
           clientObj = SshRemoteHost(host,port,user,passwd,cmd) 
           clientObj.run() 


          歷史文章:
          相信我,這么寫(xiě)Python Request代碼,老板給你漲工資
          API測(cè)試之Postman,看這篇文章就夠了
          你知道兩臺(tái)Linux之間如何傳輸文件嗎?
          你知道Docker容器與主機(jī)之間的文件數(shù)據(jù)如何拷貝嗎?

          文章合集
          Selenium Appium  | Jenkins  |  Jmeter 
          軟件測(cè)試方法匯總 Postman接口參數(shù)化 | 測(cè)試用例設(shè)計(jì) | APP抓包

          微信群:
          軟件自動(dòng)化測(cè)試交流群
          已創(chuàng)建,公號(hào)回復(fù)入群即可獲取入群二維碼。
          瀏覽 117
          點(diǎn)贊
          評(píng)論
          1收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          1收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  韩国三级电影HD中文久久免费 | 美女乱伦免费 | 久久国产精品伦子伦网爆社区 | 黄片在线免费播放 | 国产精品无码插逼 |