在 Windows 環境下以 Python 連線 Linux 伺服器執行指令,Paramiko 是最成熟、純 Python 實作的 SSHv2 客戶端庫。本文記錄 Windows 7 + Python 2.7 環境的完整安裝流程(含 pycrypto、mingw 編譯工具鏈),並提供密碼認證、金鑰認證、SFTP 檔案傳輸、錯誤處理的生產級程式碼範本。
gcc、g++、make。Python安裝目錄\Lib\distutils\distutils.cfg 建立:
[build]
compiler=mingw32
pip install pycrypto
# 或下載原始碼 python setup.py install
pip install paramiko
✅ Python 3.6+ 可直接 pip install paramiko(內建 cryptography 取代 pycrypto),無需 MinGW。
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
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()
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 進行檔案傳輸、統一錯誤處理與資源清理。