Python SSH遠程連接之Paramiko

一阴挣、簡介

ssh是一個協議贵少,OpenSSH是其中一個開源實現,paramiko是Python的一個庫吻商,實現了SSHv2協議(底層使用cryptography)。

有了Paramiko以后糟红,我們就可以在Python代碼中直接使用SSH協議對遠程服務器執(zhí)行操作艾帐,而不是通過ssh命令對遠程服務器進行操作。

由于paramiko屬于第三方庫盆偿,所以需要使用如下命令先行安裝

pip3 install paramiko

二柒爸、Paramiko介紹

paramiko包含兩個核心組件:SSHClient和SFTPClient。

  • SSHClient的作用類似于Linux的ssh命令事扭,是對SSH會話的封裝捎稚,該類封裝了傳輸(Transport),通道(Channel)及SFTPClient建立的方法(open_sftp)求橄,通常用于執(zhí)行遠程命令今野。
  • SFTPClient的作用類似與Linux的sftp命令,是對SFTP客戶端的封裝谈撒,用以實現遠程文件操作腥泥,如文件上傳、下載啃匿、修改文件權限等操作蛔外。

Paramiko中的幾個基礎名詞:

1、Channel:是一種類Socket溯乒,一種安全的SSH傳輸通道夹厌;
2、Transport:是一種加密的會話裆悄,使用時會同步創(chuàng)建了一個加密的Tunnels(通道)矛纹,這個Tunnels叫做Channel;
3光稼、Session:是client與Server保持連接的對象或南,用connect()/start_client()/start_server()開始會話。

三艾君、Paramiko的基本使用

SSHClient常用的方法介紹

connect():實現遠程服務器的連接與認證采够,對于該方法只有hostname是必傳參數。

常用參數
hostname 連接的目標主機
port=SSH_PORT 指定端口
username=None 驗證的用戶名
password=None 驗證的用戶密碼
pkey=None 私鑰方式用于身份驗證
key_filename=None 一個文件名或文件列表冰垄,指定私鑰文件
timeout=None 可選的tcp連接超時時間
allow_agent=True, 是否允許連接到ssh代理蹬癌,默認為True 允許
look_for_keys=True 是否在~/.ssh中搜索私鑰文件,默認為True 允許
compress=False, 是否打開壓縮

set_missing_host_key_policy():設置遠程服務器沒有在know_hosts文件中記錄時的應對策略。目前支持三種策略:

設置連接的遠程主機沒有本地主機密鑰或HostKeys對象時的策略逝薪,目前支持三種:
 
AutoAddPolicy 自動添加主機名及主機密鑰到本地HostKeys對象隅要,不依賴load_system_host_key的配置。即新建立ssh連接時不需要再輸入yes或no進行確認
WarningPolicy 用于記錄一個未知的主機密鑰的python警告董济。并接受步清,功能上和AutoAddPolicy類似,但是會提示是新連接
RejectPolicy 自動拒絕未知的主機名和密鑰感局,依賴load_system_host_key的配置尼啡。此為默認選項

exec_command():在遠程服務器執(zhí)行Linux命令的方法暂衡。

open_sftp():在當前ssh會話的基礎上創(chuàng)建一個sftp會話询微。該方法會返回一個SFTPClient對象。

# 利用SSHClient對象的open_sftp()方法狂巢,可以直接返回一個基于當前連接的sftp對象撑毛,可以進行文件的上傳等操作.
 
sftp = client.open_sftp()
sftp.put('test.txt','text.txt')

SSHClient常用的方法舉例

import paramiko
 
   # 實例化SSHClient
   client = paramiko.SSHClient()
 
   # 自動添加策略,保存服務器的主機名和密鑰信息唧领,如果不添加藻雌,那么不再本地know_hosts文件中記錄的主機將無法連接
   client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
 
   # 連接SSH服務端,以用戶名和密碼進行認證
   client.connect(hostname='192.168.117.136', port=22, username='root', password='123456')
 
   # 打開一個Channel并執(zhí)行命令
   stdin, stdout, stderr = client.exec_command('df -h ')  # stdout 為正確輸出斩个,stderr為錯誤輸出胯杭,同時是有1個變量有值
 
   # 打印執(zhí)行結果
   print(stdout.read().decode('utf-8'))
 
   # 關閉SSHClient
   client.close()

密鑰連接方式

# 配置私人密鑰文件位置
private = paramiko.RSAKey.from_private_key_file('/Users/ch/.ssh/id_rsa')
 
#實例化SSHClient
client = paramiko.SSHClient()
 
#自動添加策略,保存服務器的主機名和密鑰信息受啥,如果不添加做个,那么不再本地know_hosts文件中記錄的主機將無法連接
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
 
#連接SSH服務端,以用戶名和密碼進行認證
client.connect(hostname='192.168.117.136',port=22,username='root',pkey=private)

SSHClient 封裝 Transport

import paramiko
 
   # 創(chuàng)建一個通道
   transport = paramiko.Transport(('192.168.117.136', 22))
   transport.connect(username='root', password='12345')
 
   ssh = paramiko.SSHClient()
   ssh._transport = transport
 
   stdin, stdout, stderr = ssh.exec_command('df -h')
   print(stdout.read().decode('utf-8'))
 
   transport.close()

SFTPClient常用方法介紹

SFTPCLient作為一個sftp的客戶端對象滚局,根據ssh傳輸協議的sftp會話居暖,實現遠程文件操作,如上傳藤肢、下載太闺、權限、狀態(tài)
 
from_transport(cls,t) 創(chuàng)建一個已連通的SFTP客戶端通道
put(localpath, remotepath, callback=None, confirm=True) 將本地文件上傳到服務器 參數confirm:是否調用stat()方法檢查文件狀態(tài)嘁圈,返回ls -l的結果
get(remotepath, localpath, callback=None) 從服務器下載文件到本地
mkdir() 在服務器上創(chuàng)建目錄
remove() 在服務器上刪除目錄
rename() 在服務器上重命名目錄
stat() 查看服務器文件狀態(tài)
listdir() 列出服務器目錄下的文件

SFTPClient常用方法舉例

import paramiko
 
# 獲取Transport實例
tran = paramiko.Transport(('168.192.117.136', 22))
 
# 連接SSH服務端省骂,使用password
tran.connect(username="root", password='123456')
# 或使用
# 配置私人密鑰文件位置
private = paramiko.RSAKey.from_private_key_file('/Users/root/.ssh/id_rsa')
# 連接SSH服務端,使用pkey指定私鑰
tran.connect(username="root", pkey=private)
 
# 獲取SFTP實例
sftp = paramiko.SFTPClient.from_transport(tran)
 
# 設置上傳的本地/遠程文件路徑
localpath = "/Users/root/Downloads/1.txt"
remotepath = "/tmp/1.txt"
 
# 執(zhí)行上傳動作
sftp.put(localpath, remotepath)
# 執(zhí)行下載動作
sftp.get(remotepath, localpath)
 
tran.close()

四最住、Paramiko的綜合使用例子

class SSHConnection(object):
 
    def __init__(self, host_dict):
        self.host = host_dict['host']
        self.port = host_dict['port']
        self.username = host_dict['username']
        self.pwd = host_dict['pwd']
        self.__k = None
 
    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 run_cmd(self, command):
        """
         執(zhí)行shell命令,返回字典
         return {'color': 'red','res':error}或
         return {'color': 'green', 'res':res}
        :param command:
        :return:
        """
        ssh = paramiko.SSHClient()
        ssh._transport = self.__transport
        # 執(zhí)行命令
        stdin, stdout, stderr = ssh.exec_command(command)
        # 獲取命令結果
        res = unicode_utils.to_str(stdout.read())
        # 獲取錯誤信息
        error = unicode_utils.to_str(stderr.read())
        # 如果有錯誤信息钞澳,返回error
        # 否則返回res
        if error.strip():
            return {'color':'red','res':error}
        else:
            return {'color': 'green', 'res':res}
 
    def upload(self,local_path, target_path):
        # 連接,上傳
        sftp = paramiko.SFTPClient.from_transport(self.__transport)
        # 將location.py 上傳至服務器 /tmp/test.py
        sftp.put(local_path, target_path, confirm=True)
        # print(os.stat(local_path).st_mode)
        # 增加權限
        # sftp.chmod(target_path, os.stat(local_path).st_mode)
        sftp.chmod(target_path, 0o755)  # 注意這里的權限是八進制的温学,八進制需要使用0o作為前綴
 
    def download(self,target_path, local_path):
        # 連接略贮,下載
        sftp = paramiko.SFTPClient.from_transport(self.__transport)
        # 將location.py 下載至服務器 /tmp/test.py
        sftp.get(target_path, local_path)
 
    # 銷毀
    def __del__(self):
        self.close()
 
  
#unicode_utils.py
def to_str(bytes_or_str):
    """
    把byte類型轉換為str
    :param bytes_or_str:
    :return:
    """
    if isinstance(bytes_or_str, bytes):
        value = bytes_or_str.decode('utf-8')
    else:
        value = bytes_or_str
    return value
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子逃延,更是在濱河造成了極大的恐慌览妖,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揽祥,死亡現場離奇詭異讽膏,居然都是意外死亡,警方通過查閱死者的電腦和手機拄丰,發(fā)現死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門府树,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人料按,你說我怎么就攤上這事奄侠。” “怎么了载矿?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵垄潮,是天一觀的道長。 經常有香客問我闷盔,道長弯洗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任逢勾,我火速辦了婚禮牡整,結果婚禮上,老公的妹妹穿的比我還像新娘溺拱。我一直安慰自己逃贝,他們只是感情好,可當我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布盟迟。 她就那樣靜靜地躺著秋泳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪攒菠。 梳的紋絲不亂的頭發(fā)上迫皱,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天,我揣著相機與錄音辖众,去河邊找鬼卓起。 笑死,一個胖子當著我的面吹牛凹炸,可吹牛的內容都是我干的戏阅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼啤它,長吁一口氣:“原來是場噩夢啊……” “哼奕筐!你這毒婦竟也來了舱痘?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤离赫,失蹤者是張志新(化名)和其女友劉穎芭逝,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體渊胸,經...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡旬盯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了翎猛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胖翰。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖切厘,靈堂內的尸體忽然破棺而出萨咳,到底是詐尸還是另有隱情,我是刑警寧澤迂卢,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布某弦,位于F島的核電站,受9級特大地震影響而克,放射性物質發(fā)生泄漏。R本人自食惡果不足惜怔毛,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一员萍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拣度,春花似錦碎绎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至冤馏,卻和暖如春日麸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背逮光。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工代箭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涕刚。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓嗡综,卻偏偏與公主長得像,于是被迫代替她去往敵國和親杜漠。 傳聞我的和親對象是個殘疾皇子极景,可洞房花燭夜當晚...
    茶點故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內容