python大佬養成計劃----paramiko實現SSH
阿新 • • 發佈:2018-12-09
paramiko模組
SSH 為 Secure Shell 的縮寫,由 IETF 的網路小組(Network Working Group)所制定;SSH 為建立在應用層基礎上的安全協議。SSH 是目前較可靠,專為遠端登入會話和其他網路服務提供安全性的協議。利用 SSH 協議可以有效防止遠端管理過程中的資訊洩露問題.
paramiko是用python語言寫的一個模組,遵循SSH2協議,支援以加密和認證的方式,進行遠端伺服器的連線。paramiko支援Linux, Solaris, BSD, MacOS X, Windows等平臺通過SSH從一個平臺連線到另外一個平臺。利用該模組,可以方便的進行ssh連線和sftp協議進行sftp檔案傳輸。
遠端密碼連線
#基於ssh,用於連線遠端伺服器做操作:遠端執行命令,上傳或下載檔案 import paramiko #建立一個ssh物件 client = paramiko.SSHClient() #2.解決問題:首次連線,會出現 # Are you sure you want to continue connecting (yes/no)? yes # 自動選擇yes # 允許連線不在know_hosts檔案中的主機 client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #3.連線伺服器 client.connect(hostname='172.25.254.19',port=22,username='root',password='westos') #4.執行操作 stdin,stdout,stderr = client.exec_command('hostname')#標準輸入,標準輸出,標準錯誤輸出。 #Execute a command on the SSH server. A new `.Channel` is opened and # the requested command is executed. The command's input and output # streams are returned as Python ``file``-like objects representing # stdin, stdout, and stderr. #5.獲取命令的執行結果 res = stdout.read().decode('utf-8')#使結果具有可讀性 print(res) #6.斷開連線 client.close()
批量連線
批量連線host.txt檔案中的主機,返回執行結果格式:172.25.254.1:22:root:westos
import paramiko with open('host.txt') as f: #保證host.txt檔案在當前目錄下 hostinfos = f.readlines() #列表形式,['172.25.254.1:22:root:westos\n', '172.25.254.2:22:root:westos\n', '172.25.254.3:22:root:westos\n', '172.25.254.19:22:root:westos\n'] for hostinfo in hostinfos: hostinfo = hostinfo.strip() #去掉空格,字串格式,172.25.254.2:22:root:westos print('正在連線%s主機' %(hostinfo.split(':')[0])) hostname,port,username,passwd = hostinfo.split(':') try: client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(hostname=hostname,port=port,username=username,password=passwd) stdin,stdout,stderr = client.exec_command('hostname') res = stdout.read().decode('utf-8') print('結果為:',res) except Exception as e : print("Connection is failed,the reason is :",e) finally: client.close() print("連線結束")
基於公鑰連線
免密登入遠端主機首先在需要連線的主機上生成一對公鑰和私鑰,本機獲取到需要連線的主機的私鑰時,就可以通過公私鑰配對,登陸遠端主機。這裡需要id_rsa存放你所連線的主機的私鑰
import paramiko
from paramiko.ssh_exception import NoValidConnectionsError, AuthenticationException
def conn(cmd,hostname,port=22,username='root'):
client = paramiko.SSHClient()
private_key = paramiko.RSAKey.from_private_key_file('id_rsa')#id_rsa存放私鑰
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
client.connect(hostname=hostname,
port=port,username=username,pkey=private_key)
except NoValidConnectionsError as e:
print('...連線失敗...')
except AuthenticationException as e:
print('...密碼錯誤...')
else:
stdin, stdout, stderr = client.exec_command(cmd)
result = stdout.read().decode('utf-8')
print(result)
finally:
client.close()
if __name__=='__main__':
for count in range(13,20):
hostname = '172.25.254.%s' %(count)
print('正在連線主機:',hostname)
conn('hostname',hostname)
print("...連線結束...")
基於使用者名稱密碼上傳下載檔案
sftp是Secure File Transfer Protocol的縮寫,安全檔案傳送協議。可以為傳輸檔案提供一種安全的網路的加密方法。
import paramiko
tran = paramiko.Transport('172.25.254.19',22)
tran.connect(username='root',password='westos')
sftp = paramiko.SFTPClient.from_transport(tran)
#class SFTPClient(BaseSFTP, ClosingContextManager)
#SFTP client object.
# Used to open an SFTP session across an open SSH `.Transport` and perform
# remote file operations.
# Instances of this class may be used as context managers.
sftp.put('/home/kiosk/PycharmProjects/day18/07_pratice.py','/mnt/practice.py')
sftp.get('/mnt/passwd','hallo')
tran.close()
paramiko再封裝
使paramiko模組執行自己想要的操作
import paramiko
import os
from paramiko.ssh_exception import NoValidConnectionsError, AuthenticationException, SSHException
class SshRrmote(object):
def __init__(self,cmd,hostname,port,username,passwd):
self.hostname = hostname
self.passwd = passwd
self.cmd = cmd
self.username = username
self.port = port
def run(self):
"""預設呼叫的內容"""
# cmd hostname
# put local_file remote_file
# get remote_file local_file
cmd_str = self.cmd.split()[0] # cmd
# 類的反射, 判斷類裡面是否可以支援該操作?
if hasattr(self, 'do_' + cmd_str): # do_cmd
getattr(self, 'do_' + cmd_str)()
else:
print("目前不支援該功能")
def do_cmd(self):
client = paramiko.SSHClient()
try:
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname=self.hostname,port=int(self.port),username=self.username,password=self.passwd)
except NoValidConnectionsError as e:
print('...連線失敗...')
except AuthenticationException as e:
print('...密碼錯誤...')
else:
cmd = ' '.join(self.cmd.split()[1:])
stdin, stdout, stderr = client.exec_command(cmd)
result = stdout.read().decode('utf-8')
print('執行結果',result)
finally:
print('斷開%s的連線' %(self.hostname))
client.close()
def do_get(self):
#有待改進,因為連線多個主機時,會覆蓋檔案
print('開始下載')
try:
trans = paramiko.Transport(self.hostname,int(self.port))
trans.connect(username=self.username,password=self.passwd)
print('hello')
except SSHException as e:
print("連線失敗")
else:
sftp = paramiko.SFTPClient.from_transport(trans)
cmd = self.cmd.split()[1:]
if len(cmd)==2:
sftp.get(cmd[0],cmd[1])
print("下載檔案%s成功,並儲存為%s" %(cmd[0],cmd[1]))
else:
print("引數有誤")
trans.close()
def do_put(self):
# put /tmp/passwd /tmp/passwd # 將本機的/tmp/passwd檔案上傳到遠端主機的/tmp/passwd;
print("開始上傳") #注意你使用的使用者是否為kiosk
try:
trans = paramiko.Transport(self.hostname, int(self.port))
trans.connect(username=self.username, password=self.passwd)
except SSHException as e:
print("連線失敗")
else:
sftp = paramiko.SFTPClient.from_transport(trans)
cmd = self.cmd.split()[1:]
if len(cmd) == 2:
sftp.put(cmd[0],cmd[1])
print("上傳檔案%s成功,並儲存為%s" %(cmd[0], cmd[1]))
else:
print("引數有誤")
trans.close()
#1.選擇要操作的主機組:mysql,web,ftp
# 主機資訊怎麼存?將不同的主機資訊存放在不同的檔案中
#2.根據選擇的主機組,顯示包含的主機IP/主機名
#3.讓使用者確認資訊,選擇需要批量執行的命令
# -cmd shell命令
# -put 本地檔案 遠端檔案
# -get 遠端檔案 本地檔案
def main():
groups = [file.rstrip('.conf') for file in os.listdir('conf')]
print('主機組顯示'.center(50,'*'))
[print('\t',item) for item in groups]
choiceGroup = input("請選擇批量操作的主機組(eg:web):")
with open('conf/'+choiceGroup+'.conf') as f:
info = f.readlines()
print("批量執行指令碼".center(50, '*'))
while True:
cmd = input(">>").strip()
if cmd:
if cmd =='exit':
print("連線執行結束")
break
for item in info:
item=item.strip()
print(item.split(':')[0].center(50,'-'))
hostname,port,username,passwd = item.split(':')
ssh = SshRrmote(cmd,hostname,port,username,passwd)
ssh.run()
main()