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()
相关文章
相关标签/搜索