python學習之路網絡編程篇(第五篇)-續篇

Python堡壘機實現之基礎知識python

通常的堡壘機必需要具有如下5個基本功能:mysql

  一、權限控制
  二、執行命令
  三、上傳下載文件
  四、遠程登陸
  五、記錄操做

權限控制sql

    說明:根據不一樣的登陸用戶分配不一樣的可管理的主機組。(再細分的權限就是根據不一樣的用戶控制可在主機上執行的命令,通常不會限制的這麼嚴格)shell

    思路:使用數據庫建立用戶表,表字段有ID、用戶名、密碼、所屬組,再建立主機表,表字段有ID,主機IP,所屬組。其中用戶表中的所屬組和主機表中的所屬組相對應,這樣就能把兩張表關聯起來。當用戶登陸的時候就能夠根據用戶名去獲取可管理的主機列表。數據庫

例子:這裏只寫出關於python鏈接mysql數據庫的例子服務器

 

執行命令:session

    說明:這裏的執行命令通常是指批量執行命令,好比須要同時獲取N臺主機的主機名。併發

    思路:使用paramiko模塊來實現遠程登陸服務器並執行命令。使用multiprocessing來實現批量併發執行。ssh

    例子:(這裏只寫出paramiko模塊遠程密碼登陸服務器並執行命令的例子)socket

import paramiko
 
class Paramiko_Manage():
    def __init__(self,host,port,user,passwd):    #初始化鏈接服務器所須要的參數
        self.host = host
        self.port = port
        self.user = user
        self.passwd = passwd    #使用密碼認證
 
    def connect(self):        #鏈接方法,用來創建與服務器的鏈接
        self.transport = paramiko.Transport((self.host,self.port))
        self.transport.connect(username=self.user,password=self.passwd)
        print('connect')
 
    def close(self):        #關閉方法,用來關閉與服務器的鏈接
        self.transport.close()
        print('close') 
 
    def cmd(self,command):        #執行命令的方法,接收須要執行的命令做爲參數
        ssh = paramiko.SSHClient()
        ssh._transport = self.transport
        stdin, stdout, stderr = ssh.exec_command(command,timeout=3)
        print('command resluat: ',stdout.read()) 
 
    def run(self,command):
        self.connect()        #創建鏈接
        self.cmd(command)     #執行命令
        self.close()          #關閉鏈接
 
p = Paramiko_Manage('192.168.100.20',22,'test','123456')
p.run('hostname')
 
# 執行結果:
# connect
# command resluat:  Test1
#  
# close

上傳、下載文件:

    說明:批量上傳文件相對比較簡單,若是是批量下載文件還須要考慮到多臺服務器文件重名的問題。

            還須要考慮到文件上傳後比較大小以確認是否上傳下載成功。

    思路:使用paramiko模塊來實現遠程上傳下載文件。使用multiprocessing來實現批量併發執行。    

    例子:(這裏只寫出paramiko模塊遠程祕鑰認證登陸服務器並執行命令的例子)

import paramiko
import os
 
class Paramiko_Manage():
    def __init__(self,host,port,user,key):
        self.host = host
        self.port = port
        self.user = user
        keyfile = os.path.expanduser(key)    #使用祕鑰認證
        self.key = paramiko.RSAKey.from_private_key_file(keyfile)
 
    def connect(self):
        self.transport = paramiko.Transport((self.host,self.port))
        self.transport.connect(username=self.user,pkey=self.key)
        print('connect') 
 
    def close(self):
        self.transport.close()
        print('close') 
 
    def trans(self,file1,file2):    #傳輸文件的方法
        sftp = paramiko.SFTPClient.from_transport(self.transport)
        file1 = '%s_%s' % (file1, self.host)   #修改下載文件的保存文件名
        sftp.get(file2,file1)
        file1_size = os.path.getsize(file1)    #獲取下載文件的大小
        file2_size = int(str(sftp.stat(file2)).split()[4]) #獲取遠程文件的大小
        if file1_size == file2_size:    #比較兩個文件大小
            print('File trans done') 
 
    def run(self,file1,file2):
        self.connect()      #創建鏈接
        self.trans(file1,file2)  #傳輸文件
        self.close()               #關閉鏈接 
 
p = Paramiko_Manage('192.168.100.20',22,'test2','~/.ssh/id_rsa')
p.run('/root/hosts','/etc/hosts')
 
# 執行結果:
# connect
# File trans done
# close

遠程登陸和記錄操做:

    說明:經過堡壘機ssh遠程鏈接到服務器,並執行操做,和在終端執行操做的效果同樣。

    思路:使用paramiko實現遠程鏈接服務器的功能,使用sys.stdin和select處理用戶輸入和接受返回結果。

    例子:

import paramiko
import select
import sys
import socket
import os
 
tran = paramiko.Transport((host,port))    #鏈接服務器,host和port自定義
tran.start_client()
default_path = os.path.join(os.environ['HOME'],'.ssh','id_rsa')
key = paramiko.RSAKey.from_private_key_file(default_path)
tran.auth_publickey('root',key)
chan = tran.open_session()    #打開一個通道
chan.get_pty()                #獲取一個終端
chan.invoke_shell()           #激活器
 
f = open('log.log','a')       #打開一個文件用於寫入執行的操做
while True:
    # 監視用戶輸入和服務器返回數據
    # sys.stdin 處理用戶輸入
    # chan 是以前建立的通道,用於接收服務器返回信息
    readable,writeable,error = select.select([chan,sys.stdin,],[],[],1)
    if chan in readable:        #接受命令的返回結果
        try:
            x = chan.recv(1024)
            if len(x) == 0:
                print('\r\n*** EOF\r\n',) 
                f.close()    #退出時關閉記錄文件
                break
            sys.stdout.write(x)
            sys.stdout.flush()
        except socket.timeout:
            pass
    if sys.stdin in readable:    #處理用戶輸入發送到服務器執行
        inp = sys.stdin.readline()
        f.write(inp)    #記錄用戶輸入
        chan.sendall(inp)
 
chan.close()
tran.close()
相關文章
相關標籤/搜索