python 學習筆記(paramiko模塊)

paramiko模塊

paramiko是一個基于SSH用于連接遠程服務器并執(zhí)行相關操作(SSHClient和SFTPClinet,即一個是遠程連接,一個是上傳下載服務),使用該模塊可以對遠程服務器進行命令或文件操作,值得一說的是,fabric和ansible內部的遠程管理就是使用的paramiko來現實。

1. 下載安裝

pip install paramiko

模塊使用

[1]SSHClient
遠程連接分為兩種:(1)基于用戶名密碼連接 (2)基于公鑰秘鑰連接
通過是用paramiko遠程操作,其實本質也分為兩種:
(1)只用SSHClient (2)自己創(chuàng)建一個transport

1,基于用戶名和密碼的連接

import paramiko

# 創(chuàng)建SSH對象
ssh = paramiko.SSHClient()
# 允許連接不在know_hosts文件中的主機
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 連接服務器
ssh.connect(hostname='ip地址', port=22, username='root', password='@999')
# 執(zhí)行命令
stdin, stdout, stderr = ssh.exec_command('ls')
# 獲取命令結果
result = stdout.read()
print(result)
# 關閉連接
ssh.close()

SSHClient 封裝 Transport

import paramiko

transport = paramiko.Transport(('ip地址', 22))
transport.connect(username='root', password='@999')

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('ls')
print(stdout.read())

transport.close()

2,基于用戶名和密碼的連接

import paramiko
 
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
# 創(chuàng)建SSH對象
ssh = paramiko.SSHClient()
# 允許連接不在know_hosts文件中的主機
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 連接服務器
ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', key=private_key)
# 執(zhí)行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 獲取命令結果
result = stdout.read()
# 關閉連接
ssh.close()

SSHClient 封裝Transport

import paramiko
 
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='wupeiqi', pkey=private_key)
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df')
transport.close()

[2]SFTPClient:
用于連接遠程服務器并進行上傳下載功能。
1,基于用戶名密碼上傳下載

import paramiko

transport = paramiko.Transport(('ip', 22))
transport.connect(username='root', password='SHIzhiming@999')

sftp = paramiko.SFTPClient.from_transport(transport)
# 將up.py 上傳至服務器
# sftp.put('up.py', 'up.py')
#將服務器的文件 下載到本地 
sftp.get('up9.py', 'up_9.py')

transport.close()

2,基于公鑰秘鑰上傳下載

import paramiko
 
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
 
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='GSuser', pkey=private_key )
 
sftp = paramiko.SFTPClient.from_transport(transport)
# 將location.py 上傳至服務器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 將remove_path 下載到本地 local_path
sftp.get('remove_path', 'local_path')
 
transport.close()

Demo: 實現遠程命令執(zhí)行和文件上傳

import paramiko
 
class SSHConnection(object):
 
    def __init__(self, host='192.168.12.68', port=22, username='locojoy',pwd='123321QQ!'):
        self.host = host
        self.port = port
        self.username = username
        self.pwd = pwd
        self.__k = None
 
    def run(self):
        self.connect()  # 連接遠程服務器
        self.upload('db.py','/tmp/1.py')  # 將本地的db.py文件上傳到遠端服務器的/tmp/目錄下并改名為1.py
        self.cmd('df')  # 執(zhí)行df 命令
        self.close()    # 關閉連接
 
    def connect(self):
        transport = paramiko.Transport((self.host, self.port))
        transport.connect(username=self.username, password=self.pwd)
        self.__transport = transport
 
    def close(self):
        self.__transport.close()
 
    def upload(self,local_path,target_path):
        sftp = paramiko.SFTPClient.from_transport(self.__transport)
        sftp.put(local_path,target_path)
 
    def cmd(self, command):
        ssh = paramiko.SSHClient()
        ssh._transport = self.__transport
        # 執(zhí)行命令
        stdin, stdout, stderr = ssh.exec_command(command)
        # 獲取命令結果
        result = stdout.read()
        print(result)
        return result
 
obj = SSHConnection()
obj.run()

paramiko在堡壘機中的應用
(1)簡單實例:遠程連接一臺主機,操作命令,linux版本,輸入終端為回車則發(fā)送命令。不支持tab補全功能。

import paramiko, sys, os, socket, select, getpass
from paramiko.py3compat import u   # 在python3中是這樣使用的,如果在Python2中則注釋這行
 
# 這個程序依賴于終端,只能在Liunx下運行,windows用其他的方式
 
tran = paramiko.Transport(('192.168.12.68', 22,))
tran.start_client()
tran.auth_password('locojoy', '123321QQ!')
 
# 打開一個通道
chan = tran.open_session()
# 獲取一個終端
chan.get_pty()
# 激活器
chan.invoke_shell()
 
# 原始的方法利用終端進行收發(fā)消息
# 利用sys.stdin,肆意妄為執(zhí)行操作
# 用戶在終端輸入內容,并將內容發(fā)送至遠程服務器
# 遠程服務器執(zhí)行命令,并將結果返回
# 用戶終端顯示內容
 
while True:
    # 監(jiān)視用戶輸入和服務器返回數據
    # sys.stdin 處理用戶輸入
    # chan 是之前創(chuàng)建的通道,用于接收服務器返回信息
    # 通過select監(jiān)聽終端(輸入輸出),一旦變化,就將拿到的數據發(fā)送給服務器
    # 通過監(jiān)聽socket句柄,如果有變化表示服務器要給我發(fā)消息
    readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1)
    # 通過select.select 監(jiān)聽chan(打開的通道(和遠程服務器連接的狀態(tài))), sys.stdin(輸入),一旦變化就寫入readable
    # 當chan變化時,加入到readable,遠程服務器發(fā)送內容過來
    if chan in readable:
        try:
            x = u(chan.recv(1024))  # Python3用這個
            # x = chan.recv(1024)  Python2使用這個
            if len(x) == 0:
                print('\r\n*** EOF\r\n')
                break
            sys.stdout.write(x)   # 寫入緩沖區(qū)
            sys.stdout.flush()    # 刷新,將緩沖區(qū)內容顯示出來
        except socket.timeout:
            pass
    # 當sys.stdin 放入readable中時,將獲取到的內容發(fā)送到遠程服務器
    if sys.stdin in readable:
        inp = sys.stdin.readline()
        chan.sendall(inp)
 
chan.close()
tran.close()

(2)每按一個鍵就發(fā)送記錄,并支持tab自動補全

import paramiko, sys, os, socket, select, getpass, termios, tty
from paramiko.py3compat import u
 
tran = paramiko.Transport(('10.211.55.4', 22,))
tran.start_client()
tran.auth_password('wupeiqi', '123')
# 打開一個通道
chan = tran.open_session()
# 獲取一個終端
chan.get_pty()
# 激活器
chan.invoke_shell()
 
# 獲取原tty屬性
oldtty = termios.tcgetattr(sys.stdin)
try:
    # 為tty設置新屬性
    # 默認當前tty設備屬性:
    #   輸入一行回車,執(zhí)行
    #   CTRL+C 進程退出,遇到特殊字符,特殊處理。
    # 這是為原始模式,不認識所有特殊符號
    # 放置特殊字符應用在當前終端,如此設置,將所有的用戶輸入均發(fā)送到遠程服務器
    tty.setraw(sys.stdin.fileno())  # 恢復終端原始狀態(tài),每按一個鍵就發(fā)送
    chan.settimeout(0.0)
 
    while True:
        # 監(jiān)視 用戶輸入 和 遠程服務器返回數據(socket)
        # 阻塞,直到句柄可讀
        r, w, e = select.select([chan, sys.stdin], [], [], 1)
        if chan in r:  # 獲取服務返回的內容
            try:
                x = u(chan.recv(1024))
                if len(x) == 0:
                    print('\r\n*** EOF\r\n')
                    break
                sys.stdout.write(x)
                sys.stdout.flush()
            except socket.timeout:
                pass
        if sys.stdin in r: # 發(fā)送命令
            x = sys.stdin.read(1) # 讀取一個字符
            if len(x) == 0:
                break
            chan.send(x) # 發(fā)送一個字符
 
finally:
    # 重新設置終端屬性,將終端狀態(tài)還原
    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
 
chan.close()
tran.close()

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現,斷路器,智...
    卡卡羅2017閱讀 136,534評論 19 139
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,631評論 1 32
  • “你曾說過不分離,要一直一直在一起,現在我想問問你,是否只是童言無忌......”帶著耳機,聽著音樂,望著街上...
    大圣老師閱讀 1,032評論 0 6
  • 2017-06-27 一個人喜歡上你, 不是你年不年輕,好不好看, 而是, 你給了這個人一種其他人給不了的感覺。 ...
    永紅語錄閱讀 270評論 0 1
  • 1.初始化方法和類方法定義一個類,繼承與 NSObject 在里面寫如下代碼import UIKit class ...
    蹲在路口的男孩丶閱讀 293評論 0 0

友情鏈接更多精彩內容