python基于paramiko庫(kù)遠(yuǎn)程執(zhí)行 SSH 命令,實(shí)現(xiàn) sftp 下載文件
楔子
我們使用 Python 避免不了和 Linux 打交道,而有時(shí)我們需要執(zhí)行一些 shell 命令。如果在本地的話,那么可以通過調(diào)用 os.system 或者 subprocess.Popen 來執(zhí)行,但如果我們希望遠(yuǎn)程執(zhí)行其它機(jī)器上的 shell 命令,這個(gè)時(shí)候該怎么做呢?下面我們就來推薦一個(gè)第三方庫(kù) paramiko,看看如何使用 Python 遠(yuǎn)程操作其它機(jī)器。
paramiko
網(wǎng)絡(luò)傳輸是遵循協(xié)議的,比如 SSH,paramiko 則是實(shí)現(xiàn)了 SSHv2 協(xié)議的一個(gè) Python 第三方庫(kù)(底層使用的是 cryptography)。有了 paramiko 之后,我們便可以通過 Python 使用 SSH 協(xié)議來連接遠(yuǎn)程服務(wù)器執(zhí)行操作,和 xshell 本質(zhì)上是類似的。
注意:我們?cè)?Python 代碼中是直接通過 SSH 協(xié)議對(duì)遠(yuǎn)程服務(wù)器執(zhí)行操作,而不是調(diào)用 ssh 命令對(duì)遠(yuǎn)程服務(wù)器進(jìn)行操作。
既然要使用,那么首先要安裝,直接 pip install paramiko 即可。
paramiko 包含兩大核心組件:SSHClient 和 SFTPClient
SSHClient 的作用類似于 Linux 下的 ssh 命令,是對(duì) SSH 會(huì)話的封裝,通常用于執(zhí)行遠(yuǎn)程命令。
SFTPClient 的作用類似于 Linux 下的 sftp 命令,是對(duì) SFTP 客戶端的封裝,用于實(shí)現(xiàn)遠(yuǎn)程文件的操作。比如:文件上傳,下載、修改文件權(quán)限等操作。
下面我們就來介紹它們的用法。
SSHClient 的使用
首先創(chuàng)建一個(gè)客戶端實(shí)例, client = paramiko.SSHClient(),然后這個(gè) client 下有很多方法。
connect:實(shí)現(xiàn)遠(yuǎn)程服務(wù)器的連接與認(rèn)證
def connect( self, hostname, port=SSH_PORT, username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None, ): """"""
里面參數(shù)很多,但常用的參數(shù)如下:
- hostname:連接的目的主機(jī), 這個(gè)參數(shù)是必須的
- port=SSH_PORT:指定的端口, 默認(rèn)是 22
- username=None:登陸的用戶
- password=None:用戶密碼
- pkey=None:通過私鑰進(jìn)行身份驗(yàn)證
- key_filename=None:一個(gè)文件名或文件列表, 指定私鑰文件
- timeout=None:可選的 tcp 連接超時(shí)時(shí)間
- allow_agent=True:是否允許連接到 ssh 代理, 默認(rèn)為 True
- look_for_keys=True:是否在 ~/.ssh 中搜索私鑰文件, 默認(rèn)為 True, 表示允許
- compress=False:是否打開壓縮
set_missing_host_key_policy:當(dāng)遠(yuǎn)程服務(wù)器沒有本地秘鑰或 HostKeys 對(duì)象時(shí)的應(yīng)對(duì)策略,目前支持三種:
- 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 的配置, 該選項(xiàng)為默認(rèn)選項(xiàng)
所以我們一般都會(huì)將策略改成 AutoAddPolicy,不然還需要在本地進(jìn)行配置。
exec_command:遠(yuǎn)程執(zhí)行的具體 Linux 命令
open_sftp:在當(dāng)前 ssh 會(huì)話的基礎(chǔ)上創(chuàng)建一個(gè) sftp 會(huì)話,該方法會(huì)返回一個(gè) SFTPClient 對(duì)象,可以執(zhí)行文件的上傳、下載等操作。我們后面在 SFTPClient 的時(shí)候會(huì)說。
下面我們來演示一下:
import paramiko
# 實(shí)例化 SSHClient
client = paramiko.SSHClient()
# 自動(dòng)添加策略, 保存服務(wù)器的主機(jī)名和密鑰信息; 如果不添加, 那么不再本地 know_hosts 文件中的主機(jī)將無法連接
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 連接 SSH 服務(wù)端, 通過用戶名和密碼進(jìn)行認(rèn)證
# 該過程會(huì)創(chuàng)建一個(gè) session, 它是 client 和 server 保持連接的對(duì)象
client.connect(hostname='47.94.174.89', port=22, username='root', password='xxxxxxx')
# 執(zhí)行遠(yuǎn)程命令, 該方法會(huì)打開一個(gè) paramiko.Channel 對(duì)象(類 socket, 一種安全的 SSH 傳輸通道)
# 會(huì)返回三個(gè)值, 分別是 stdin(標(biāo)準(zhǔn)輸入)、stdout(標(biāo)準(zhǔn)輸出)、stderr(錯(cuò)誤輸出)
stdin, stdout, stderr = client.exec_command("ls /")
# 打印執(zhí)行結(jié)果, 顯然我們要通過 stdout 來查看, 我們可以調(diào)用 stdout.read 獲取執(zhí)行的結(jié)果
# 但是返回的是字節(jié), 所以需要先獲取對(duì)應(yīng)的編碼, 然后再進(jìn)行 decode
print(stdout.read().decode("utf-8"))
"""
bin
boot
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
"""
# 最后關(guān)閉 SSHClient 對(duì)象
client.close()
還是很簡(jiǎn)單的,如果我們輸入了一條錯(cuò)誤的命令,那么 stdout 里面就不會(huì)有內(nèi)容了,因?yàn)殄e(cuò)誤信息會(huì)保存是在 stderr 中。
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname='47.94.174.89', port=22, username='root', password='xxxxxxx')
stdin, stdout, stderr = client.exec_command("xxxxx")
print(stderr.read().decode("utf-8"))
"""
bash: xxxxx: command not found
"""
client.close()
SFTPClient 的使用
SFTPClient 作為一個(gè) sftp 的客戶端對(duì)象,根據(jù) ssh 傳輸協(xié)議的 sftp 會(huì)話,可以實(shí)現(xiàn)遠(yuǎn)程文件的操作,例如:上傳、下載、查看權(quán)限和狀態(tài)等等。
import paramiko
# 創(chuàng)建一個(gè) Transport 對(duì)象, 使用時(shí)會(huì)同步創(chuàng)建一個(gè) paramiko.Channel 對(duì)象
# 參數(shù)傳遞一個(gè)由 IP 和 PORT 組成的元組即可
transport = paramiko.Transport(("47.94.174.89", 22))
# 連接 ssh, 通過 username 和 password
transport.connect(username="root", password="xxxxxxx")
# 獲取 SFTPClient 實(shí)例, 它便相當(dāng)于 Linux 下的 sftp, 我們通過它可以進(jìn)行文件的一些操作
sftp = paramiko.SFTPClient.from_transport(transport)
以上我們便得到的 sftp,那么它都支持哪些操作呢?
- put(self, localpath, remotepath, callback=None, confirm=True):將本地文件上傳到服務(wù)器, callback 表示回調(diào)函數(shù), 上傳成功后調(diào)用; confirm 表示是否調(diào)用 stat 方法檢查文件狀態(tài), 返回 ls -l 的結(jié)果
- get(self, remotepath, localpath, callback=None):將文件從服務(wù)器下載到本地
- mkdir(self, path, mode=o777):在服務(wù)器上創(chuàng)建目錄, mode 表示權(quán)限, 默認(rèn)為 511(o777 是一個(gè)變量, 等于 511)
- rmdir(self, path):刪除服務(wù)器上的目錄
- remove(self, path):刪除服務(wù)器上的文件
- rename(self, oldpath, newpath):對(duì)服務(wù)器上目錄進(jìn)行重命名
- stat(self, path):查看文件或目錄的狀態(tài)
- listdir(self, path='.'):列出服務(wù)器目錄下的文件
- getcwd(self):查看工作區(qū), 也就是當(dāng)前所在路徑
- chmod(self, path, mode):改變權(quán)限
- chown(self, path, uid, gid): 改變用戶和組
- chdir(self, path):改變工作區(qū)
常用的大概以上這些,我們來演示一下。
# 1. 改變工作區(qū)
sftp.chdir("/usr/local/bin")
# 2. 查看工作區(qū)
print(sftp.getcwd()) # /usr/local/bin
sftp.chdir("/root")
print(sftp.getcwd()) # /root
"""
如果不調(diào)用 sftp.chdir(path) 的時(shí)候, 那么打印 sftp.getcwd() 時(shí)結(jié)果為 None
但我們知道登陸 Linux 時(shí), 默認(rèn)會(huì)在 /root 目錄(對(duì)于 root 用戶而言)
對(duì)于當(dāng)前的 sftp 而言也確實(shí)如此, 只不過打印 sftp.getcwd() 的時(shí)候結(jié)果為 None 罷了
"""
# 3. 列出當(dāng)前目錄下的文件
print(sftp.listdir("/usr/local")) # ['lib', 'lib64', 'games', 'aegis', ...]
# 4. 查看文件或目錄狀態(tài)
print(sftp.stat("/root/.ssh/authorized_keys"))
"""
-rw------- 1 0 0 0 16 Dec 13:26 ?
"""
# 5. 改變權(quán)限
sftp.chmod("/root/.ssh/authorized_keys", 0o777)
print(sftp.stat("/root/.ssh/authorized_keys"))
"""
-rwxrwxrwx 1 0 0 0 16 Dec 13:26 ?
"""
# 6. 創(chuàng)建目錄
print("dir" in sftp.listdir("/root")) # False
sftp.mkdir("/root/dir", mode=0o777)
print("dir" in sftp.listdir("/root")) # True
# 7. 刪除目錄
sftp.rmdir("/root/dir")
print("dir" in sftp.listdir("/root")) # False
# 8. 刪除文件
sftp.remove("/root/1.py")
# 9. 下載文件
sftp.get("/root/makefile", r"makefile")
# 10. 上傳文件
sftp.put("dockerfile", "/root/dockerfile")
# 最后關(guān)閉 sftp 和 transport
sftp.close()
transport.close()
當(dāng)然我們?cè)诮榻B SSHClient 的時(shí)候說過,還可以通過 open_sftp 的方式來創(chuàng)建 sftp 客戶端。
import paramiko client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(hostname='47.94.174.89', port=22, username='root', password='xxxxxxx') # 這種方式創(chuàng)建也是可以的 sftp = client.open_sftp()
以上就是python基于paramiko庫(kù)遠(yuǎn)程執(zhí)行 SSH 命令,實(shí)現(xiàn) sftp 下載文件的詳細(xì)內(nèi)容,更多關(guān)于python paramiko庫(kù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Python使用paramiko連接遠(yuǎn)程服務(wù)器執(zhí)行Shell命令的實(shí)現(xiàn)
- python利用paramiko實(shí)現(xiàn)交換機(jī)巡檢的示例
- 解決Python paramiko 模塊遠(yuǎn)程執(zhí)行ssh 命令 nohup 不生效的問題
- Python?Paramiko上傳下載sftp文件及遠(yuǎn)程執(zhí)行命令詳解
- python 采用paramiko 遠(yuǎn)程執(zhí)行命令及報(bào)錯(cuò)解決
- Python通過paramiko庫(kù)實(shí)現(xiàn)遠(yuǎn)程執(zhí)行l(wèi)inux命令的方法
相關(guān)文章
使用Python開發(fā)Telegram?Bot的流程步驟
Telegram?Bot?是一種可以與用戶交互的機(jī)器人應(yīng)用程序,通過?Telegram?的?Bot?API?與服務(wù)器通信,它可以用來處理消息、執(zhí)行命令、提供服務(wù),如通知提醒、數(shù)據(jù)查詢和自動(dòng)化任務(wù)等,本文給大家介紹了如何用?Python?開發(fā)一個(gè)?Telegram?Bot,需要的朋友可以參考下2025-01-01
一篇文章帶你了解python標(biāo)準(zhǔn)庫(kù)--time模塊
下面小編就為大家?guī)硪黄猵ython模塊之time模塊。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2021-08-08
將本地Python項(xiàng)目打包成docker鏡像上傳到服務(wù)器并在docker中運(yùn)行
Docker是一個(gè)開源項(xiàng)目,為開發(fā)人員和系統(tǒng)管理員提供了一個(gè)開放平臺(tái),可以將應(yīng)用程序構(gòu)建、打包為一個(gè)輕量級(jí)容器,并在任何地方運(yùn)行,這篇文章主要給大家介紹了關(guān)于將本地Python項(xiàng)目打包成docker鏡像上傳到服務(wù)器并在docker中運(yùn)行的相關(guān)資料,需要的朋友可以參考下2023-12-12
Python編程實(shí)現(xiàn)下載器自動(dòng)爬取采集B站彈幕示例
這篇文章主要介紹了使用Python編程來實(shí)現(xiàn)一個(gè)下載器可以自動(dòng)爬取采集B站彈幕的示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2021-10-10
基于python實(shí)現(xiàn)開箱即用的桌面時(shí)鐘
這篇文章主要為大家詳細(xì)介紹了如何基于python實(shí)現(xiàn)開箱一個(gè)即用的桌面時(shí)鐘,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的小伙伴可以參考下2023-12-12
Pandas實(shí)現(xiàn)數(shù)據(jù)拼接的操作方法詳解
Python處理大規(guī)模數(shù)據(jù)集的時(shí)候經(jīng)常需要使用到合并、鏈接的方式進(jìn)行數(shù)據(jù)集的整合,本文為大家主要介紹了.merge()、?.join()?和?.concat()?三種方法,感興趣的可以了解一下2022-04-04

