python大佬養成計劃----paramiko實現SSH

paramiko模塊

SSH 爲 Secure Shell 的縮寫,由 IETF 的網絡小組(Network Working Group)所制定;SSH 爲創建在應用層基礎上的安全協議。SSH 是目前較可靠,專爲遠程登陸會話和其餘網絡服務提供安全性的協議。利用 SSH 協議能夠有效防止遠程管理過程當中的信息泄露問題.python

paramiko是用python語言寫的一個模塊,遵循SSH2協議,支持以加密和認證的方式,進行遠程服務器的鏈接。paramiko支持Linux, Solaris, BSD, MacOS X, Windows等平臺經過SSH從一個平臺鏈接到另一個平臺。利用該模塊,能夠方便的進行ssh鏈接和sftp協議進行sftp文件傳輸。mysql

遠程密碼鏈接

#基於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:westosios

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存放你所鏈接的主機的私鑰web

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的縮寫,安全文件傳送協議。能夠爲傳輸文件提供一種安全的網絡的加密方法。sql

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模塊執行本身想要的操做shell

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()

圖片描述
圖片描述

相關文章
相關標籤/搜索