Python – paramiko 套件

Loading

測試環境為 CentOS 8 x86_64 (虛擬機)

paramiko 套件允許我們可以透過 SSH 連線方式來執行遠端機器的程式.

安裝所需套件.

[root@localhost ~]# pip install paramiko
[root@localhost ~]# python3
Python 3.6.8 (default, Mar 25 2022, 11:15:52)
[GCC 8.5.0 20210514 (Red Hat 8.5.0-10)] on linux
Type "help", "copyright", "credits" or "license" for more information.

使用密碼方式進行連線

import paramiko
username = "root"
password = "111111"
hostname = "192.168.31.132"
port = 22

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname, port, username, password)
stdin, stdout, stderr = client.exec_command('ls /')
result = stdout.readlines()
print (result)

執行結果

['bin\n', 'boot\n', 'dev\n', 'etc\n', 'home\n', 'lib\n', 'lib64\n', 'media\n', 'mnt\n', 'opt\n', 'powercycle\n', 'proc\n', 'root\n', 'run\n', 'sbin\n', 'srv\n', 'sys\n', 'tmp\n', 'usr\n', 'var\n']

程式說明:
匯入 paramiko 套件

import paramiko

後面 connect 函數所需參數.

username = "root"
password = "111111"
hostname = "192.168.31.132"
port = 22

建立 paramiko 物件.

client = paramiko.SSHClient()

set_missing_host_key_policy 函數為不使用 host key 來建立連線方式, paramiko.AutoAddPolicy() 會將收到的 SSH Public 公鑰儲存起起來到預設路徑 ( root 為 /rot/.ssh/known_hosts )

client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

建立連線

client.connect(hostname, port, username, password)

透過 SSH 執行遠端程式.

stdin, stdout, stderr = client.exec_command('ls /')

使用金鑰安全驗證方式進行連線

事前準備
我們可以透過建立 Public Key 而不需輸入密碼.實作上的步驟如下 :

  • Client 端 ( SSH Client / paramiko : IP: 192.168.31.132)
    先在 Client 上面建立 Public Key 跟 Private Key 這兩把鑰匙,利用的指令為 ssh-keygen 這個命令:

    [root@localhost ~]# ssh-keygen -t rsa
    Generating public/private rsa key pair.
    Enter file in which to save the key (/root/.ssh/id_rsa):
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /root/.ssh/id_rsa.
    Your public key has been saved in /root/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:d9roPISeul9kCny111111Cx1jXFCfyJGhq222222vfw root@localhost.localdomain
    The key's randomart image is:
    +---[RSA 3072]----+
    | .+* e.B.oB+.    |
    |  o + ..B+.+.    |
    |   tto.o5 o o .  |
    |    +. t.+ . o   |
    |     oo.S.= .    |
    |      Ej.B.=     |
    |       ..o= .    |
    |        o+.      |
    |      o+. o.     |
    +----[SHA256]-----+
    

    上面指令產生的 key 為 RSA ,儲存在 $HOME/.ssh 中 (id_rsa 為私鑰, id_rsa.pub 為公鑰),passphrase 主要是保護私鑰 (你需要一串密碼來解開私鑰,也可以不設).

    [root@localhost ~]# ll .ssh/
    id_rsa       id_rsa.pub   known_hosts
    

    要這把 Client 的 Public Key 放在任何一個你想要用來登入的主機的 Server 端 User 的家目錄內 (請先確認有 ~/.ssh 目錄).

    [root@localhost ~]# scp .ssh/id_rsa.pub 192.168.31.128:/root/.ssh/
    root@192.168.31.128's password:
    
  • server 端 (IP: 192.168.31.128)
    匯入剛才 client 端產生的公鑰至 $HOME/.ssh/ 裏面的認證檔案 authorized_keys 即可完成

    [root@localhost ~]# cd .ssh/
    [root@localhost .ssh]# cat id_rsa.pub >> authorized_keys
    

回到 Python 程式.

import paramiko
username = "root"
hostname = "192.168.31.128"
port = 22

client = paramiko.SSHClient()
client.load_system_host_keys()

client.connect(hostname, port, username)
stdin, stdout, stderr = client.exec_command('ls /')
result = stdout.readlines()
print (result)

執行結果

['bin\n', 'boot\n', 'dev\n', 'etc\n', 'home\n', 'lib\n', 'lib64\n', 'media\n', 'mnt\n', 'opt\n', 'powercycle\n', 'proc\n', 'root\n', 'run\n', 'sbin\n', 'srv\n', 'sys\n', 'tmp\n', 'usr\n', 'var\n']

主要差別在於使用系統預設的公私鑰 ( root 公鑰預設儲存路徑 為 /rot/.ssh/ )

client.load_system_host_keys()

multiple hosts

import paramiko
username = "root"
password = "111111"
hosts = ['192.168.31.132', 
         '192.168.31.128']
port = 22

for host in hosts:
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(host, port, username, password)
    stdin, stdout, stderr = client.exec_command('ls /')
    result = stdout.readlines()
    print (result)

執行結果

['bin\n', 'boot\n', 'dev\n', 'etc\n', 'home\n', 'lib\n', 'lib64\n', 'media\n', 'mnt\n', 'opt\n', 'powercycle\n', 'proc\n', 'root\n', 'run\n', 'sbin\n', 'srv\n', 'sys\n', 'tmp\n', 'usr\n', 'var\n']
['bin\n', 'boot\n', 'dev\n', 'etc\n', 'home\n', 'lib\n', 'lib64\n', 'media\n', 'mnt\n', 'opt\n', 'proc\n', 'root\n', 'run\n', 'sbin\n', 'srv\n', 'sys\n', 'tmp\n', 'usr\n', 'var\n']

主要差別在於使用陣列定義 hots 並使用 for 迴圈 來執行.

hosts = ['192.168.31.132', 
         '192.168.31.128']
for host in hosts:

遇過的問題

>>> client.exec_command('ls /')
(<paramiko.ChannelFile from <paramiko.Channel 3 (open) window=2097152 -> <paramiko.Transport at 0x90e6e438 (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>, 
<paramiko.ChannelFile from <paramiko.Channel 3 (open) window=2097152 -> <paramiko.Transport at 0x90e6e438 (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>, 
<paramiko.ChannelFile from <paramiko.Channel 3 (open) window=2097152 -> <paramiko.Transport at 0x90e6e438 (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>)

paramiko 物件 exec_command 函數回傳多個結果,需正確使用多個物件來承接資料.

>>> stdin, stdout, stderr = client.exec_command('ls /')
沒有解決問題,試試搜尋本站其他內容

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料