python模組 paramiko
阿新 • • 發佈:2018-11-10
paramiko模組提供了ssh及sft進行遠端登入伺服器執行命令和上傳下載檔案的功能。這是一個第三方的軟體包,使用之前需要安裝。
1 基於使用者名稱和密碼的 sshclient 方式登入
# 建立一個sshclient物件
ssh = paramiko.SSHClient()
# 允許將信任的主機自動加入到host_allow 列表,此方法必須放在connect方法的前面
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 呼叫connect方法連線伺服器
ssh.connect(hostname='192.168.2.129' , port=22, username='super', password='super')
# 執行命令
stdin, stdout, stderr = ssh.exec_command('df -hl')
# 結果放到stdout中,如果有錯誤將放到stderr中
print(stdout.read().decode())
# 關閉連線
ssh.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
2 基於使用者名稱和密碼的 transport 方式登入
方法1是傳統的連線伺服器、執行命令、關閉的一個操作,有時候需要登入上伺服器執行多個操作,比如執行命令、上傳/下載檔案,方法1則無法實現,可以通過如下方式來操作
# 例項化一個transport物件
trans = paramiko.Transport(('192.168.2.129', 22))
# 建立連線
trans.connect(username='super', password='super')
# 將sshclient的物件的transport指定為以上的trans
ssh = paramiko.SSHClient()
ssh._transport = trans
# 執行命令,和傳統方法一樣
stdin, stdout, stderr = ssh.exec_command('df -hl')
print(stdout.read().decode())
# 關閉連線
trans.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
3 基於公鑰金鑰的 SSHClient 方式登入
# 指定本地的RSA私鑰檔案,如果建立金鑰對時設定的有密碼,password為設定的密碼,如無不用指定password引數
pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345')
# 建立連線
ssh = paramiko.SSHClient()
ssh.connect(hostname='192.168.2.129',
port=22,
username='super',
pkey=pkey)
# 執行命令
stdin, stdout, stderr = ssh.exec_command('df -hl')
# 結果放到stdout中,如果有錯誤將放到stderr中
print(stdout.read().decode())
# 關閉連線
ssh.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
以上需要確保被訪問的伺服器對應使用者.ssh目錄下有authorized_keys檔案,也就是將伺服器上生成的公鑰檔案儲存為authorized_keys。並將私鑰檔案作為paramiko的登陸金鑰
4 基於金鑰的 Transport 方式登入
# 指定本地的RSA私鑰檔案,如果建立金鑰對時設定的有密碼,password為設定的密碼,如無不用指定password引數
pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345')
# 建立連線
trans = paramiko.Transport(('192.168.2.129', 22))
trans.connect(username='super', pkey=pkey)
# 將sshclient的物件的transport指定為以上的trans
ssh = paramiko.SSHClient()
ssh._transport = trans
# 執行命令,和傳統方法一樣
stdin, stdout, stderr = ssh.exec_command('df -hl')
print(stdout.read().decode())
# 關閉連線
trans.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
##### 傳檔案 SFTP ###########
# 例項化一個trans物件# 例項化一個transport物件
trans = paramiko.Transport(('192.168.2.129', 22))
# 建立連線
trans.connect(username='super', password='super')
# 例項化一個 sftp物件,指定連線的通道
sftp = paramiko.SFTPClient.from_transport(trans)
# 傳送檔案
sftp.put(localpath='/tmp/11.txt', remotepath='/tmp/22.txt')
# 下載檔案
# sftp.get(remotepath, localpath)
trans.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
5 實現輸入命令立馬返回結果的功能
以上操作都是基本的連線,如果我們想實現一個類似xshell工具的功能,登入以後可以輸入命令回車後就返回結果:
import paramiko
import os
import select
import sys
# 建立一個socket
trans = paramiko.Transport(('192.168.2.129', 22))
# 啟動一個客戶端
trans.start_client()
# 如果使用rsa金鑰登入的話
'''
default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
prikey = paramiko.RSAKey.from_private_key_file(default_key_file)
trans.auth_publickey(username='super', key=prikey)
'''
# 如果使用使用者名稱和密碼登入
trans.auth_password(username='super', password='super')
# 開啟一個通道
channel = trans.open_session()
# 獲取終端
channel.get_pty()
# 啟用終端,這樣就可以登入到終端了,就和我們用類似於xshell登入系統一樣
channel.invoke_shell()
# 下面就可以執行你所有的操作,用select實現
# 對輸入終端sys.stdin和 通道進行監控,
# 當用戶在終端輸入命令後,將命令交給channel通道,這個時候sys.stdin就發生變化,select就可以感知
# channel的傳送命令、獲取結果過程其實就是一個socket的傳送和接受資訊的過程
while True:
readlist, writelist, errlist = select.select([channel, sys.stdin,], [], [])
# 如果是使用者輸入命令了,sys.stdin發生變化
if sys.stdin in readlist:
# 獲取輸入的內容
input_cmd = sys.stdin.read(1)
# 將命令傳送給伺服器
channel.sendall(input_cmd)
# 伺服器返回了結果,channel通道接受到結果,發生變化 select感知到
if channel in readlist:
# 獲取結果
result = channel.recv(1024)
# 斷開連線後退出
if len(result) == 0:
print("\r\n**** EOF **** \r\n")
break
# 輸出到螢幕
sys.stdout.write(result.decode())
sys.stdout.flush()
# 關閉通道
channel.close()
# 關閉連結
trans.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
6 支援tab自動補全
import paramiko
import os
import select
import sys
import tty
import termios
'''
實現一個xshell登入系統的效果,登入到系統就不斷輸入命令同時返回結果
支援自動補全,直接呼叫伺服器終端
'''
# 建立一個socket
trans = paramiko.Transport(('192.168.2.129', 22))
# 啟動一個客戶端
trans.start_client()
# 如果使用rsa金鑰登入的話
'''
default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
prikey = paramiko.RSAKey.from_private_key_file(default_key_file)
trans.auth_publickey(username='super', key=prikey)
'''
# 如果使用使用者名稱和密碼登入
trans.auth_password(username='super', password='super')
# 開啟一個通道
channel = trans.open_session()
# 獲取終端
channel.get_pty()
# 啟用終端,這樣就可以登入到終端了,就和我們用類似於xshell登入系統一樣
channel.invoke_shell()
# 獲取原操作終端屬性
oldtty = termios.tcgetattr(sys.stdin)
try:
# 將現在的操作終端屬性設定為伺服器上的原生終端屬性,可以支援tab了
tty.setraw(sys.stdin)
channel.settimeout(0)
while True:
readlist, writelist, errlist = select.select([channel, sys.stdin,], [], [])
# 如果是使用者輸入命令了,sys.stdin發生變化
if sys.stdin in readlist:
# 獲取輸入的內容,輸入一個字元傳送1個字元
input_cmd = sys.stdin.read(1)
# 將命令傳送給伺服器
channel.sendall(input_cmd)
# 伺服器返回了結果,channel通道接受到結果,發生變化 select感知到
if channel in readlist:
# 獲取結果
result = channel.recv(1024)
# 斷開連線後退出
if len(result) == 0:
print("\r\n**** EOF **** \r\n")
break
# 輸出到螢幕
sys.stdout.write(result.decode())
sys.stdout.flush()
finally:
# 執行完後將現在的終端屬性恢復為原操作終端屬性
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
# 關閉通道
channel.close()
# 關閉連結
trans.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-778f64ae39.css" rel="stylesheet">
</div>