首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Python Paramiko 實作 SSH 連線與遠端指令執行完整教學

     編輯:更多程式設計知識

在 Windows 環境下以 Python 連線 Linux 伺服器執行指令,Paramiko 是最成熟、純 Python 實作的 SSHv2 客戶端庫。本文記錄 Windows 7 + Python 2.7 環境的完整安裝流程(含 pycrypto、mingw 編譯工具鏈),並提供密碼認證、金鑰認證、SFTP 檔案傳輸、錯誤處理的生產級程式碼範本。

環境建置(Windows + Python 2.7)

  1. 安裝 MinGW:官方下載,安裝時勾選 gcc、g++、make。
  2. 設定 distutils 使用 MinGW:在 Python安裝目錄\Lib\distutils\distutils.cfg 建立:

[build]
compiler=mingw32
  1. 安裝 pycrypto:

pip install pycrypto
# 或下載原始碼 python setup.py install
  1. 安裝 Paramiko:

pip install paramiko

✅ Python 3.6+ 可直接 pip install paramiko(內建 cryptography 取代 pycrypto),無需 MinGW。

基本 SSH 連線與指令執行


import paramiko

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())  # 自動接受未知主機金鑰

client.connect(
    hostname='192.168.8.248',
    port=22,
    username='root',
    password='password',
    timeout=4
)

stdin, stdout, stderr = client.exec_command('ls -l')
for line in stdout.readlines():
    print(line.rstrip())

client.close()

輸出範例


總計 184804
-rw------- 1 root root 973 05-19 20:27 anaconda-ks.cfg
-rw-r--r-- 1 root root 13895 05-19 20:27 install.log
-rw-r--r-- 1 root root 3058 05-19 20:25 install.log.syslog
-rw-r--r-- 1 root root 189008625 05-28 09:55 tmp

進階模式:金鑰認證 + SFTP 檔案下載


import paramiko
import time

hostname = 'your.server.com'
port = 22
username = 'app'
password = 'your_password'  # 或使用私鑰

# 1. SSH 連線執行指令
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname, port, username, password, timeout=10)

stdin, stdout, stderr = ssh.exec_command('sh ~/log/check')
print(stdout.read())
ssh.close()

# 2. SFTP 下載日誌檔案
transport = paramiko.Transport((hostname, port))
transport.connect(username=username, password=password)
sftp = paramiko.SFTPClient.from_transport(transport)

files = sftp.listdir('/home/app/log/')
for f in files:
    print(f)

# 下載固定檔名
sftp.get('/home/app/log/server.txt', r'C:\Users\Admin\Desktop\server.txt')

# 下載當日日期命名的壓縮檔
today = time.strftime('%Y-%m-%d')
remote = f'/home/app/log/{today}.log.zip'
local = rf'C:\Users\Admin\Desktop\{today}.log.zip'
sftp.get(remote, local)

transport.close()

私鑰認證(RSA Key)


pkey_file = r'E:\keys\id_rsa'
private_key = paramiko.RSAKey.from_private_key_file(pkey_file)

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname, port, username, pkey=private_key, timeout=10)

stdin, stdout, stderr = ssh.exec_command('ls -l /home/app/log')
print(stdout.read())
ssh.close()

⚠️ 私鑰檔案權限需 600(chmod 600 id_rsa),否則 Paramiko 會拒絕載入。

生產級封裝類別範本


import paramiko
import logging
from contextlib import contextmanager

class SSHClient:
    def __init__(self, host, port=22, user=None, password=None, pkey_path=None, timeout=10):
        self.host = host
        self.port = port
        self.user = user
        self.password = password
        self.pkey = paramiko.RSAKey.from_private_key_file(pkey_path) if pkey_path else None
        self.timeout = timeout
        self._client = None
        self._sftp = None
        self._transport = None

    def connect(self):
        self._client = paramiko.SSHClient()
        self._client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self._client.connect(
            self.host, self.port, self.user,
            password=self.password, pkey=self.pkey,
            timeout=self.timeout
        )
        self._transport = paramiko.Transport((self.host, self.port))
        self._transport.connect(username=self.user, password=self.password, pkey=self.pkey)
        self._sftp = paramiko.SFTPClient.from_transport(self._transport)

    def exec_command(self, cmd, get_pty=False):
        if not self._client:
            self.connect()
        stdin, stdout, stderr = self._client.exec_command(cmd, get_pty=get_pty)
        return stdout.read().decode('utf-8'), stderr.read().decode('utf-8'), stdout.channel.recv_exit_status()

    def download(self, remote_path, local_path):
        if not self._sftp:
            self.connect()
        self._sftp.get(remote_path, local_path)

    def upload(self, local_path, remote_path):
        if not self._sftp:
            self.connect()
        self._sftp.put(local_path, remote_path)

    def close(self):
        if self._sftp: self._sftp.close()
        if self._transport: self._transport.close()
        if self._client: self._client.close()

    def __enter__(self):
        self.connect()
        return self

    def __exit__(self, *args):
        self.close()

# 用法
with SSHClient('192.168.1.100', user='deploy', pkey_path='~/.ssh/id_rsa') as ssh:
    out, err, code = ssh.exec_command('systemctl status nginx')
    print(out)
    ssh.download('/var/log/nginx/access.log', './access.log')

常見問題排查

錯誤原因解決
Authentication failed密碼/金鑰錯誤、伺服器禁用密碼登入確認憑證、啟用 PasswordAuthentication yes 或使用金鑰
SSHException: Incompatible ssh peer版本協商失敗升級 Paramiko、檢查伺服器 sshd_config KexAlgorithms
FileNotFoundError (SFTP)遠端路徑不存在先 sftp.listdir() 確認、使用絕對路徑
連線逾時防火牆、IP 錯誤、Port 不對telnet host 22 測試、檢查 Security Group
私鑰載入失敗格式不支援(OpenSSH 新格式)、權限過寬ssh-keygen -p -m PEM -f id_rsa 轉舊格式、chmod 600

結語

Paramiko 提供完整的 SSHv2 客戶端功能,配合上下文管理器封裝,能構建穩健的自動化部署、日誌收集、遠端管理腳本。關鍵點:正確處理主機金鑰驗證、選擇適當認證方式、善用 SFTP 進行檔案傳輸、統一錯誤處理與資源清理。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved