python運(yùn)維自動(dòng)化Paramiko的實(shí)現(xiàn)示例
一、Paramiko
1、安裝
pip install paramiko
2、常用的類
SSHClient: 最常用的類,表示一個(gè)SSH客戶端連接。
SFTPClient: 用于SFTP傳輸操作。
Transport: 低級(jí)別的模塊,可用來實(shí)現(xiàn)SSH2協(xié)議。
SSHClient主要方法
connect(hostname, port=22, username=None, password=None, pkey=None): 用于連接到遠(yuǎn)程服務(wù)器??梢赃x擇使用用戶名和密碼或密鑰進(jìn)行認(rèn)證。
exec_command(command): 在遠(yuǎn)程服務(wù)器上執(zhí)行指令。
open_sftp(): 返回一個(gè)SFTPClient對象,可用于文件的上傳與下載。
SFTPClient主要方法
get(remotepath, localpath, callback=None): 下載遠(yuǎn)程文件。
put(localpath, remotepath, callback=None, confirm=True): 上傳本地文件。
listdir(path=“.”): 列出遠(yuǎn)程目錄的內(nèi)容。
3、使用
(1)SSH執(zhí)行遠(yuǎn)程命令
import paramiko
# 創(chuàng)建SSH客戶端
client = paramiko.SSHClient()
# 自動(dòng)添加未知的服務(wù)器密鑰及策略
'''
AutoAddPolicy:自動(dòng)添加主機(jī)名及主機(jī)密鑰到本地的known_hosts,不依賴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的配置。此為默認(rèn)選項(xiàng)
'''
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 連接SSH服務(wù)端
'''
hostname(str類型),連接的目標(biāo)主機(jī)地址;
port(int類型),連接目標(biāo)主機(jī)的端口,默認(rèn)為22;
username(str類型),校驗(yàn)的用戶名(默認(rèn)為當(dāng)前的本地用戶名);
password(str類型),密碼用于身份校驗(yàn)或解鎖私鑰;
pkey(Pkey類型),私鑰方式用于身份驗(yàn)證;
key_filename(str or list(str)類型),一個(gè)文件名或文件名列表,用于私鑰的身份驗(yàn)證;
timeout(float類型),一個(gè)可選的超時(shí)時(shí)間(以秒為單位)的TCP連接;
allow_agent(bool類型),設(shè)置為False時(shí)用于禁用連接到SSH代理;
look_for_keys(bool類型),設(shè)置為False時(shí)用于來禁用在~/.ssh中搜索私鑰文件;
compress(bool類型),設(shè)置為True時(shí)打開壓縮。
'''
client.connect('192.168.56.10', port=22, username='root', password='vagrant')
# 執(zhí)行命令
stdin, stdout, stderr = client.exec_command('ls -l')
# 獲取命令執(zhí)行結(jié)果
result = stdout.read()
print(result.decode())
# 關(guān)閉連接
client.close()
(2)SFTP上傳/下載文件
import paramiko
# 創(chuàng)建SSH客戶端
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.56.10', port=22, username='root', password='vagrant')
# 創(chuàng)建SFTP會(huì)話
sftp = client.open_sftp()
# 上傳文件
sftp.put('localfile.txt', '/remote/path/remote.txt')
# 下載文件
sftp.get('/remote/path/remote.txt', 'localfile.txt')
'''
mkdir,在SFTP服務(wù)端創(chuàng)建目錄,如sftp.mkdir("/home/userdir",mode=0777),默認(rèn)模式是0777(八進(jìn)制),在某些系統(tǒng)上,mode被忽略。在使用它的地方,當(dāng)前的umask值首先被屏蔽掉。
remove,刪除SFTP服務(wù)端指定目錄,如sftp.remove("/home/userdir")。
rename,重命名SFTP服務(wù)端文件或目錄,如sftp.rename("/home/test.sh","/home/testfile.sh")
stat,獲取遠(yuǎn)程SFTP服務(wù)端指定文件信息,如sftp.stat("/home/testfile.sh")。
listdir,獲取遠(yuǎn)程SFTP服務(wù)端指定目錄列表,以Python的列表(List)形式返回,如sftp.listdir("/home")。
'''
# 關(guān)閉SFTP會(huì)話和SSH連接
sftp.close()
client.close()(3)SSH簡單封裝
import paramiko
class SSHClient:
def __init__(self, hostname, port=22, username=None, password=None, pkey=None, use_proxy=False, proxy_hostname=None,
proxy_port=None, proxy_username=None, proxy_password=None, timeout=5):
"""
初始化SSH客戶端。
:param hostname: 主機(jī)名或IP地址
:param port: 端口號(hào),默認(rèn)是22
:param username: 用戶名
:param password: 密碼
:param pkey: 私鑰文件對象,用于密鑰認(rèn)證
:param use_proxy: 是否使用代理標(biāo)志
:param proxy_hostname: 代理的主機(jī)名稱
:param proxy_port: 代理的端口號(hào)
:param proxy_username: 代理的用戶名
:param proxy_password: 代理的密碼
"""
self.hostname = hostname
self.port = port
self.username = username
self.password = password
self.pkey = pkey
self.use_proxy = use_proxy
self.proxy_hostname = proxy_hostname
self.proxy_port = proxy_port
self.proxy_username = proxy_username
self.proxy_password = proxy_password
self.client = None
self.timeout = timeout
def _setup_proxy(self):
"""
配置代理。
"""
if self.use_proxy:
proxy_ssh = paramiko.SSHClient()
proxy_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
proxy_ssh.connect(hostname=self.proxy_hostname, port=self.proxy_port, username=self.proxy_username,
password=self.proxy_password, timeout=self.timeout)
vm_transport = proxy_ssh.get_transport()
remote_address = (self.hostname, self.port)
local_address = (self.proxy_hostname, self.proxy_port)
vm_channel = vm_transport.open_channel("direct-tcpip", remote_address, local_address)
return vm_channel
else:
return None
def _connect(self):
"""
創(chuàng)建SSH連接。
"""
self.client = paramiko.SSHClient()
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
proxy = self._setup_proxy()
self.client.connect(self.hostname, port=self.port, username=self.username, password=self.password,
pkey=self.pkey, sock=proxy, timeout=self.timeout)
def exec_command(self, command):
"""
在遠(yuǎn)程服務(wù)器上執(zhí)行命令。
:param command: 要執(zhí)行的命令字符串
:return: 命令輸出結(jié)果的標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤
"""
if self.client is None:
self._connect()
stdin, stdout, stderr = self.client.exec_command(command)
return stdout.read().decode(), stderr.read().decode()
def close(self):
"""
關(guān)閉SSH連接。
"""
if self.client:
self.client.close()
self.client = None
# 使用示例
if __name__ == "__main__":
# 直接連接單個(gè)服務(wù)器
'''
ssh = SSHClient(hostname='192.168.56.10', port=22, username='root', password='vagrant')
stdout, stderr = ssh.exec_command('ls -l')
print(stdout)
ssh.close()
'''
# 通過代理連接
'''
ssh_with_proxy = SSHClient(hostname='hostname', port=22, username='username', password='password', use_proxy=True,
proxy_hostname='proxy_hostname', proxy_port=22, proxy_username='proxy_username',
proxy_password='proxy_password')
stdout, stderr = ssh_with_proxy.exec_command('ls -l')
print(stdout)
ssh_with_proxy.close()
'''
# 連接多個(gè)服務(wù)器執(zhí)行多個(gè)命令
servers = {
'192.168.56.10': {
'port': 22,
'username': 'root',
'password': '123'
},
'192.168.56.11': {
'port': 22,
'username': 'root',
'password': '123'
},
'192.168.56.12': {
'port': 22,
'username': 'root',
'password': '123'
},
}
commands = [
'ls -l',
'cd xxx',
]
for ip, info in servers.items():
ssh = SSHClient(hostname=ip, port=info.get('port'), username=info.get('username'), password=info.get('password'))
for command in commands:
stdout, stderr = ssh.exec_command(command)
print(stdout)
ssh.close()(4)SFTP簡單封裝
#!/usr/bin/env python
# coding:utf-8
from stat import *
import os
import paramiko
class RemotLHost(object):
'''封裝一個(gè)遠(yuǎn)程Linux主機(jī)類,并將paramiko遠(yuǎn)程上傳下載單個(gè)文件或目錄的行為封裝為其相應(yīng)的方法'''
# 通過IP, 用戶名,密碼,超時(shí)時(shí)間初始化一個(gè)遠(yuǎn)程Linux主機(jī)
def __init__(self, ip, username, password, timeout=30):
self.ip = ip
self.username = username
self.password = password
self.timeout = timeout
# transport
self.t = None
# 鏈接失敗的重試次數(shù)
self.conn_times = 3
# get單個(gè)文件
def sftp_get(self, remotefile, localfile):
t = paramiko.Transport((self.ip, 22))
t.connect(username=self.username, password=self.password)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.get(remotefile, localfile)
t.close()
# put單個(gè)文件
def sftp_put(self, localfile, remotefile):
t = paramiko.Transport((self.ip, 22))
t.connect(username=self.username, password=self.password)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put(localfile, remotefile)
t.close()
# 獲取遠(yuǎn)端linux主機(jī)上指定目錄及其子目錄下的所有文件
def __get_all_files_in_remote_dir(self, sftp, remote_dir):
# 保存所有文件的列表
all_files = list()
# 去掉路徑字符串最后的字符'/',如果有的話
if remote_dir[-1] == '/':
remote_dir = remote_dir[0:-1]
# 獲取當(dāng)前指定目錄下的所有目錄及文件,包含屬性值
files = sftp.listdir_attr(remote_dir)
for x in files:
# remote_dir目錄中每一個(gè)文件或目錄的完整路徑
filename = remote_dir + '/' + x.filename
print("remote file is "+ filename)
# 如果是目錄,則遞歸處理該目錄,這里用到了stat庫中的S_ISDIR方法,與linux中的宏的名字完全一致
if S_ISDIR(x.st_mode):
all_files.extend(
self.__get_all_files_in_remote_dir(sftp, filename))
else:
all_files.append(filename)
return all_files
def sftp_get_dir(self, remote_dir, local_dir):
t = paramiko.Transport((self.ip, 22))
t.connect(username=self.username, password=self.password)
sftp = paramiko.SFTPClient.from_transport(t)
# 獲取遠(yuǎn)端linux主機(jī)上指定目錄及其子目錄下的所有文件
all_files = self.__get_all_files_in_remote_dir(sftp, remote_dir)
# 依次get每一個(gè)文件
for x in all_files:
filename = x.replace(remote_dir, "")
if os.name=="nt":
filename = filename.replace('/',os.sep).lstrip(os.sep)
local_filename = os.path.join(local_dir, filename)
filepath=os.sep.join(local_filename.split(os.sep)[0:-1])
if not os.path.exists(filepath):
os.mkdir(filepath)
print(u'Get <------- %s'% x)
sftp.get(x, local_filename)
#獲取本地指定目錄及其子目錄下的所有文件
def __get_all_files_in_local_dir(self, local_dir):
# 保存所有文件的列表
all_files = list()
# 獲取當(dāng)前指定目錄下的所有目錄及文件,包含屬性值
files = os.listdir(local_dir)
for x in files:
# local_dir目錄中每一個(gè)文件或目錄的完整路徑
filename = os.path.join(local_dir, x)
# 如果是目錄,則遞歸處理該目錄
if os.path.isdir(filename):
all_files.extend(self.__get_all_files_in_local_dir(filename))
else:
all_files.append(filename)
return all_files
def sftp_put_dir(self, local_dir, remote_dir):
if remote_dir[-1] != '/':
remote_dir = remote_dir + "/"
t = paramiko.Transport((self.ip, 22))
t.connect(username=self.username, password=self.password)
sftp = paramiko.SFTPClient.from_transport(t)
for root, dirs, files in os.walk(local_dir):
for filespath in files:
local_file = os.path.join(root, filespath)
a=local_file.replace(local_dir, '')
if os.name=="nt":
a = a.replace('\\','/').lstrip('/')
remote_file = os.path.join(remote_dir, a)
try:
sftp.put(local_file,remote_file)
except Exception as e:
sftp.mkdir(os.path.split(remote_file)[0])
sftp.put(local_file,remote_file)
print("Put %s to remote %s" % (local_file, remote_file))
for name in dirs:
local_path = os.path.join(root, name)
a = local_path.replace(local_dir, '')
if os.name=="nt":
a = a.replace('\\','/').lstrip('/')
remote_path = os.path.join(remote_dir, a)
try:
sftp.mkdir(remote_path)
print("mkdir path %s" % remote_path)
except Exception as e:
print(e)
t.close()
if __name__ == '__main__':
host = RemotLHost('192.168.56.10', 'root', 'vagrant')
remote_path = '/root/doc'
local_path = 'D:\\test'
# 將遠(yuǎn)端remote_path目錄中的所有文件get到本地local_path目錄
host.sftp_get_dir(remote_path, local_path)
# 將本地local_path目錄中的所有文件put到遠(yuǎn)端remote_path目錄
local_path= 'D:\ltest'
remote_path = '/root/doc2'
host.sftp_put_dir(local_path, remote_path)4、工具類
(1)自動(dòng)部署
import sys
import time
from ssh_client import SSHClient
from sftp_client import RemotLHost
if __name__ == '__main__':
servers = {
'192.168.1.1': {
'port': 22,
'username': 'root',
'password': ''
},
}
for ip, info in servers.items():
print('begin============================' + ip + '============================')
ssh = SSHClient(hostname=ip, port=info.get('port'), username=info.get('username'),
password=info.get('password'))
sftp = RemotLHost(ip=ip, username=info.get('username'), password=info.get('password'))
stdout, stderr = ssh.exec_command('cd /data;sh stop.sh')
print(stdout)
print('stop success')
time.sleep(1)
remote_path = '/data/app.jar'
local_path = 'E:\\app.jar'
# 將遠(yuǎn)端remote_path目錄中的所有文件get到本地local_path目錄
sftp.sftp_put(local_path, remote_path)
print('put success')
time.sleep(1)
stdout, stderr = ssh.exec_command('cd /data;sh start.sh')
print(stdout)
print('start success')
time.sleep(10)
stdout, stderr = ssh.exec_command('curl http://127.0.0.1:8081/check/version')
print(stdout)
print('end============================' + ip + '============================')
ssh.close()到此這篇關(guān)于python運(yùn)維自動(dòng)化Paramiko的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)python Paramiko內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python利用paramiko實(shí)現(xiàn)基本的SSH客戶端操作
- Python使用Paramiko實(shí)現(xiàn)輕松判斷文件類型
- Python基于paramiko庫操作遠(yuǎn)程服務(wù)器的實(shí)現(xiàn)
- Python Paramiko創(chuàng)建文件目錄并上傳文件詳解
- python的paramiko模塊基本用法詳解
- Python運(yùn)維自動(dòng)化之paramiko模塊應(yīng)用實(shí)例
- Python中paramiko模塊的基礎(chǔ)操作與排錯(cuò)問題
- Python遠(yuǎn)程SSH庫Paramiko詳細(xì)操作
- Python使用paramiko連接遠(yuǎn)程服務(wù)器執(zhí)行Shell命令的實(shí)現(xiàn)
相關(guān)文章
Python opencv缺陷檢測的實(shí)現(xiàn)及問題解決
這篇文章主要介紹了Python opencv缺陷檢測的實(shí)現(xiàn)及問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
Python利用臨時(shí)文件實(shí)現(xiàn)數(shù)據(jù)的保存
tempfile模塊專門用于創(chuàng)建臨時(shí)文件和臨時(shí)目錄,它既可以在?UNIX?平臺(tái)上運(yùn)行良好,也可以在?Windows?平臺(tái)上運(yùn)行良好。本文將利用tempfile模塊創(chuàng)建臨時(shí)文件來保存數(shù)據(jù),感興趣的可以了解一下2022-07-07
Python Web框架Flask中使用百度云存儲(chǔ)BCS實(shí)例
這篇文章主要介紹了Python Web框架Flask中使用百度云存儲(chǔ)BCS實(shí)例,本文調(diào)用了百度云存儲(chǔ)Python SDK中的相關(guān)類,需要的朋友可以參考下2015-02-02
使用Python實(shí)現(xiàn)構(gòu)建量化小程序
這篇文章主要為大家介紹了如何基于Python構(gòu)建查詢歷史股票行情的應(yīng)用,本文采用了dash框架,快速搭建服務(wù),減少前端渲染頁面和后端交互的工作量,感興趣的小伙伴可以了解下2025-06-06
Python教程pandas數(shù)據(jù)分析去重復(fù)值
Pandas指定行進(jìn)行去重更新值,加載數(shù)據(jù)sample抽樣函數(shù),指定需要更新的值append直接添加append函數(shù)用法,根據(jù)某一列key值進(jìn)行去重key唯一2021-09-09
使用實(shí)現(xiàn)pandas讀取csv文件指定的前幾行
下面小編就為大家分享一篇使用實(shí)現(xiàn)pandas讀取csv文件指定的前幾行,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04
python安裝完成后可以進(jìn)行的后續(xù)步驟和注意事項(xiàng)小結(jié)
本文詳細(xì)介紹了安裝Python3后的后續(xù)步驟,包括驗(yàn)證安裝、配置環(huán)境、安裝包、創(chuàng)建和運(yùn)行腳本,以及使用虛擬環(huán)境,還強(qiáng)調(diào)了注意事項(xiàng),如系統(tǒng)更新、包管理與安全,感興趣的朋友一起看看吧2025-01-01

