广告
返回顶部
首页 > 资讯 > 后端开发 > Python >利用Python Paramiko开发l
  • 624
分享到

利用Python Paramiko开发l

PythonParamiko 2023-01-31 07:01:59 624人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

1.Paramiko模块下的demo.py程序    前面利用python中的Paramiko模块可以进行ssh的连接,以及用来传送文件(SFTP),但是无论是哪一种方式,连接都是短暂的,并非是长连的,即一次执行一个命令或上传与下载一个文件

1.Paramiko模块下的demo.py程序

    前面利用python中的Paramiko模块可以进行ssh的连接,以及用来传送文件(SFTP),但是无论是哪一种方式,连接都是短暂的,并非是长连的,即一次执行一个命令或上传与下载一个文件,显然效率是不如直接使用linux shell下的ssh连接命令来进行连接。其实在将Paramiko的源码解压出来后,里面有一个demo的文件夹,里面有一个demo.py的程序,利用它,我们就可以进行长连接,即像ssh一样连接远程主机:

xpleaf@xpleaf-Machine:/mnt/hgfs/Python/day6/sorftwares/demp_test/paramiko-1.7.7.1$ ls
demos  LICENSE      paramiko           PKG-INFO  setup.cfg        setup.py  tests
docs   MANIFEST.in  paramiko.egg-info  README    setup_helper.py  test.py
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6/sorftwares/demp_test/paramiko-1.7.7.1$ cd demos/
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6/sorftwares/demp_test/paramiko-1.7.7.1/demos$ ls -l demo.py
-rwxrwxrwx 1 root root 5340  6月 16  2010 demo.py

    利用demo.py程序,我们可以进行ssh的长连接,比如这里有一台IP地址为192.168.1.124的远程主机需要进行连接,使用远程主机的账户名为xpleaf,如下:

xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6/sorftwares/demp_test/paramiko-1.7.7.1/demos$ python demo.py 
Hostname: 192.168.1.124
*** Host key OK.
Username [xpleaf]: xpleaf
Auth by (p)assWord, (r)sa key, or (d)ss key? [p] 
Password for xpleaf@192.168.1.124: 
*** Here we Go!

Last login: Fri Oct  9 17:19:42 2015 from 192.168.1.13
[xpleaf@moban ~]$ pwd
/home/xpleaf

    这样我们就可以像ssh连接一样在远程主机上执行相关的命令了,下面,我们就是通过观察demo.py程序的源代码来对相关的程序模块作修改,然后实现简单的堡垒主机监控程序的开发


2.通过修改与demo.py相关的模块来达到堡垒主机监控的功能

    堡垒主机可以监控运维人员在服务器上做的命令操作,这里要做的,只是可以监控运维人员在Linux服务器上执行命令的操作,下面先给出这个监控程序的示意图:

运维人员登陆认证示意图:

wKioL1YXtrjiuvFFAAMvP_erInQ280.jpg

运维人员命令监控记录示意图:

wKioL1YXtvex6g2sAAF1xGkmXWA643.jpg

    

    基于上面两个图示的说明,以及对Paramiko模块中demo.py程序代码的理解,可以对demo.py模块以及相关的模块程序源代码作相应的修改,至于这个引导的过程,因为是Alex老师引导过来的,根据Alex老师修改源代码的一些思想,然后自己再进一步修改其它部分的源代码,所以这整一个探索的过程如果要讲出来,篇幅比较大,这里就不提及了,下面直接给代码:


修改后的demo.py源代码:

#!/usr/bin/env python

import base64
from binascii import hexlify
import getpass
import os
import select
import Socket
import sys
import threading
import time
import traceback

import paramiko
import interactive


def agent_auth(transport, username):
    """
    Attempt to authenticate to the given transport using any of the private
    keys available from an SSH agent.
    """
    
    agent = paramiko.Agent()
    agent_keys = agent.get_keys()
    if len(agent_keys) == 0:
        return
        
    for key in agent_keys:
        print 'Trying ssh-agent key %s' % hexlify(key.get_fingerprint()),
        try:
            transport.auth_publickey(username, key)
            print '... success!'
            return
        except paramiko.SSHException:
            print '... nope.'


def manual_auth(username, hostname,pw):
    '''default_auth = 'p'
    auth = raw_input('Auth by (p)assword, (r)sa key, or (d)ss key? [%s] ' % default_auth)
    if len(auth) == 0:
        auth = default_auth

    if auth == 'r':
        default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
        path = raw_input('RSA key [%s]: ' % default_path)
        if len(path) == 0:
            path = default_path
        try:
            key = paramiko.RSAKey.from_private_key_file(path)
        except paramiko.PasswordRequiredException:
            password = getpass.getpass('RSA key password: ')
            key = paramiko.RSAKey.from_private_key_file(path, password)
        t.auth_publickey(username, key)
    elif auth == 'd':
        default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_dsa')
        path = raw_input('DSS key [%s]: ' % default_path)
        if len(path) == 0:
            path = default_path
        try:
            key = paramiko.DSSKey.from_private_key_file(path)
        except paramiko.PasswordRequiredException:
            password = getpass.getpass('DSS key password: ')
            key = paramiko.DSSKey.from_private_key_file(path, password)
        t.auth_publickey(username, key)
    else:
        pw = getpass.getpass('Password for %s@%s: ' % (username, hostname))
        t.auth_password(username, pw)'''
    t.auth_password(username,pw)


# setup logging
paramiko.util.log_to_file('demo.log')

username = ''
if len(sys.argv) > 1:
    hostname = sys.argv[1]
    if hostname.find('@') >= 0:
        username, hostname = hostname.split('@')
else:
    hostname = raw_input('Hostname: ')
if len(hostname) == 0:
    print '*** Hostname required.'
    sys.exit(1)
port = 22
if hostname.find(':') >= 0:
    hostname, portstr = hostname.split(':')
    port = int(portstr)

# now connect
try:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((hostname, port))
except Exception, e:
    print '*** Connect failed: ' + str(e)
    traceback.print_exc()
    sys.exit(1)

try:
    t = paramiko.Transport(sock)
    try:
        t.start_client()
    except paramiko.SSHException:
        print '*** SSH negotiation failed.'
        sys.exit(1)

    try:
        keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
    except IOError:
        try:
            keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts'))
        except IOError:
            print '*** Unable to open host keys file'
            keys = {}

    # check server's host key -- this is important.
    key = t.get_remote_server_key()
    if not keys.has_key(hostname):
        print '*** WARNING: Unknown host key!'
    elif not keys[hostname].has_key(key.get_name()):
        print '*** WARNING: Unknown host key!'
    elif keys[hostname][key.get_name()] != key:
        print '*** WARNING: Host key has changed!!!'
        sys.exit(1)
    else:
        print '*** Host key OK.'

    # get username
    '''if username == '':
        default_username = getpass.getuser()
        username = raw_input('Username [%s]: ' % default_username)
        if len(username) == 0:
            username = default_username'''
    #changed by xpleaf at 2015.10.9
    username = sys.argv[2]
    password = sys.argv[3]
    sa_username = sys.argv[4]

    agent_auth(t, username)
    if not t.is_authenticated():
        manual_auth(username, hostname,password)
    if not t.is_authenticated():
        print '*** Authentication failed. :('
        t.close()
        sys.exit(1)

    chan = t.open_session()
    chan.get_pty()
    chan.invoke_shell()
    print '*** Here we go!'
    print
    interactive.interactive_shell(chan,hostname,username,sa_username)
    chan.close()
    t.close()

except Exception, e:
    print '*** Caught exception: ' + str(e.__class__) + ': ' + str(e)
    traceback.print_exc()
    try:
        t.close()
    except:
        pass
    sys.exit(1)


修改后的interactive.py源代码:

import socket
import sys,time

# windows does not have termiOS...
try:
    import termios
    import tty
    has_termios = True
except ImportError:
    has_termios = False


def interactive_shell(chan,hostname,username,sa_username):
    if has_termios:
        posix_shell(chan,hostname,username,sa_username)
    else:
        windows_shell(chan)


def posix_shell(chan,hostname,username,sa_username):
    import select
    date = time.strftime('%Y_%m_%d') #Here is changed!
    f = file('/tmp/%s_%s_record.log' % (sa_username,date),'a+') #Here is changed!
    record = [] #Here is changed!

    oldtty = termios.tcgetattr(sys.stdin)
    try:
        tty.setraw(sys.stdin.fileno())
        tty.setcbreak(sys.stdin.fileno())
        chan.settimeout(0.0)

        while True:
            date = time.strftime('%Y_%m_%d %H:%M:%S') #Here is changed!
            r, w, e = select.select([chan, sys.stdin], [], [])
            if chan in r:
                try:
                    x = chan.recv(1024)
                    if len(x) == 0:
                        print '\r\n*** EOF\r\n',
                        break
                    sys.stdout.write(x)
                    sys.stdout.flush()
                except socket.timeout:
                    pass
            if sys.stdin in r:
                x = sys.stdin.read(1)
                if len(x) == 0:
                    break
                #print x
                record.append(x)
                chan.send(x)

            if x == '\r':    #Here is changed!Follow:
                #print record
                cmd = ''.join(record).split('\r')[-2]
                log = "%s | %s | %s | %s\n" % (hostname,date,sa_username,cmd)
                f.write(log)
                f.flush()
        f.close()    #Here is changed!Above:

    finally:
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)

    
# thanks to Mike Looijmans for this code
def windows_shell(chan):
    import threading

    sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n")
        
    def writeall(sock):
        while True:
            data = sock.recv(256)
            if not data:
                sys.stdout.write('\r\n*** EOF ***\r\n\r\n')
                sys.stdout.flush()
                break
            sys.stdout.write(data)
            sys.stdout.flush()
        
    writer = threading.Thread(target=writeall, args=(chan,))
    writer.start()
        
    try:
        while True:
            d = sys.stdin.read(1)
            if not d:
                break
            chan.send(d)
    except EOFError:
        # user hit ^Z or F6
        pass


存放在堡垒主机下的Menus程序,这里命名为run_demo.py:

#!/usr/bin/env python
import os,Mysqldb

os.system('clear')
print '='*35
print '''\033[32;1mWelcome to the Connecting System!\033[0m
Choose the Server to connect:
1.DNS Server:  192.168.1.124
2.DHCP Server: 192.168.1.134'''
print '='*35
choice = raw_input('Your choice:')

	

if choice == '1':
        address = '192.168.1.124'
elif choice == '2':
        address = '192.168.1.134'

sa_user = 'yonghaoye'


try:
        conn = mysqldb.connect(host = 'localhost', user = 'root', \
                passwd = '123456', db = 'Server_list', port = 3306)
        cur = conn.cursor()
        cur.execute("select * from users where sa = '%s'" % sa_user)
        qur_result = cur.fetchall()

        for record in qur_result:
                if record[3] == address:
                        hostname = record[3]
                        username = record[4]
                        password = record[5]
        cur.close()
        conn.close()
except Mysqldb.Error,e:
        print 'Mysql Error Msg:',e

cmd = 'python /mnt/hgfs/Python/day6/sorftwares/paramiko-1.7.7.1/demos/demo.py %s %s %s %s' % (hostname,username,password,sa_user)
os.system(cmd)


在堡垒主机上添加数据库:

添加了下面这样的数据库
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| infORMation_schema |
| Server_list        |
| ftp_user           |
| linkman            |
| mysql              |
| performance_schema |
| s6py               |
+--------------------+
7 rows in set (0.01 sec)

mysql> use Server_list
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-----------------------+
| Tables_in_Server_list |
+-----------------------+
| users                 |
+-----------------------+
1 row in set (0.00 sec)

mysql> describe users;
+-----------------+------------------+------+-----+---------+----------------+
| Field           | Type             | Null | Key | Default | Extra          |
+-----------------+------------------+------+-----+---------+----------------+
| id              | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| sa              | char(20)         | NO   |     | NULL    |                |
| server_name     | char(20)         | NO   |     | NULL    |                |
| server_address  | char(20)         | NO   |     | NULL    |                |
| server_username | char(20)         | NO   |     | NULL    |                |
| server_password | char(20)         | NO   |     | NULL    |                |
+-----------------+------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

mysql> selec * from users;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'selec * from users' at line 1
mysql> select * from users;
+----+-----------+-------------+----------------+-----------------+-----------------+
| id | sa        | server_name | server_address | server_username | server_password |
+----+-----------+-------------+----------------+-----------------+-----------------+
|  1 | yonghaoye | DNS Server  | 192.168.1.124  | xpleaf          | 123456          |
|  2 | yonghaoye | DHCP Server | 192.168.1.134  | public          | 123456          |
+----+-----------+-------------+----------------+-----------------+-----------------+
2 rows in set (0.00 sec)

就不对数据库中的内容做解释说明了,其实看了前面的示意图,再看这里的代码就可以理解了。


3.监控程序演示

    演示的网络环境如下:

wKiom1YX6Hqh83g9AACrMe-qv88213.jpg

    由于我在堡垒主机上安装了shellinabox程序,所以在运维人员主机上,可以直接在WEB界面输入堡垒主机的IP地址进行远程连接,来看下面操作:

(1)运维人员主机登陆堡垒主机

wKiom1YX6gjxakHcAAJTCWbW1cw906.jpg


(2)输入堡垒主机账号密码

wKioL1YX6pzzjycKAAHCjTRCIFU430.jpg


(3)登陆成功并进入服务器连接列表选择界面

wKiom1YX68_zfdPcAANYG-EGNyQ242.jpg


(4)选择连接相应服务器

wKioL1YX7Omx4QqnAAME0UKu7gU217.jpg


(5)运维人员执行相关命令

wKiom1YX7aXBHkGSAAOANMMjiEQ254.jpg


(6)在堡垒主机上查看运维人员的命令操作

xpleaf@xpleaf-machine:/tmp$ tail -f yonghaoye_2015_10_10_record.log 
192.168.1.124 | 2015_10_10 00:36:44 | yonghaoye | pwd
192.168.1.124 | 2015_10_10 00:36:48 | yonghaoye | whoami
192.168.1.124 | 2015_10_10 00:37:13 | yonghaoye | echo $PATH

    可以看到,在堡垒主机上生成了一个相对应用户的命令记录日志文件,这里可以查看用户执行的每一个命令,需要注意的是,这里记录了用户名“yonghaoye”,是堡垒主机上的用户,并不是Linux服务器上面的,该用户是分配给运维人员的,因此,也再一次看到,运维人员并不知道Linux服务器的账户和密码,这样就比较安全了。


3.不足与优化思路

    通过上面的操作,这样的一个程序确实是可以记录运维人员在Linux服务器上做的操作,但是不足的是:

(1)程序还存在非常多的细节问题和Bug

(2)界面操作不够人性化

    但不管怎么说,这个小程序只是作为学习过程中的一个练习程序而已,但思路基本上是没有问题的,根据上面的两个缺点,往后可以进一步修改源代码以保证程序运行的稳定性,同时对于界面问题,往后应该是要做成Web界面的,而不是借助shellinabox程序,这就需要调用Python中的Django模块来做Web方面的开发,当然还有其它技术。

    刚过国庆放假期间,看到Alex老师开发了一个开源的堡垒机监控程序,大家可以去看看,而我这里所的这个小程序,作为入门来学习,其实也是非常不错的。

    Alex老师开发的开源软件:Http://3060674.blog.51cto.com/3050674/1700814

    真的,那就非常了不得了,目前自己也在努力学习过程中,坚持下来就一定可以学到很多!Python不会让我们失望的!


4.对于堡垒主机监控程序的进一步开发计划

    由于现在知道的真的是太少,往后会不断学习,希望以后也能以这里这个小程序的思路自己开发一个开源的堡垒主机监控系统,虽然目前已经有开源的了,但作为自己来练手我想也是非常不错的。


    文章的思路写得有点唐突,因为实在是很难把这其中学习的一个完整的过程写下来,因为所花费时间非常多。所以我选择了在演示操作里进行了更多的说明,至于源代码的修改,有兴趣的朋友可以对比修改前的代码进行比对的。

    



--结束END--

本文标题: 利用Python Paramiko开发l

本文链接: https://www.lsjlt.com/news/191551.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 利用Python Paramiko开发l
    1.Paramiko模块下的demo.py程序    前面利用Python中的Paramiko模块可以进行SSH的连接,以及用来传送文件(SFTP),但是无论是哪一种方式,连接都是短暂的,并非是长连的,即一次执行一个命令或上传与下载一个文件...
    99+
    2023-01-31
    Python Paramiko
  • python 利用paramiko批量管
    paramiko是基于python实现的ssh2远程安全连接,支持秘钥认证,实现远程命令执行,文件传输,中间ssh代理等功能安装paramikoparamiko依赖第三方的crypto,ecdsa,python-develyum insta...
    99+
    2023-01-31
    批量 python paramiko
  • 利用Python开发App实战
    Python语言虽然很万能,但用它来开发app还是显得有点不对路,因此用Python开发的app应当是作为编码练习、或者自娱自乐所用,加上目前这方面的模块还不是特别成熟,bug比较多,总而言之,劝君莫轻入。准备工作利用Python开发app...
    99+
    2023-05-14
    Python App
  • 怎么利用Python开发App
    本篇内容介绍了“怎么利用Python开发App”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!准备工作利用Python开发app需要用到Pyt...
    99+
    2023-07-06
  • 如何在Python中利用paramiko远程连接服务器
    本篇文章为大家展示了如何在Python中利用paramiko远程连接服务器,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Python主要用来做什么Python主要应用于:1、Web开发;2、数据科学...
    99+
    2023-06-06
  • Python开发建议:如何高效利用Python开发工具
    Python是一种强大的编程语言,被广泛应用于各个领域的软件开发中。无论是大型项目还是小型工具,Python都能提供高效的开发方式和强大的工具支持。在本篇文章中,我将探讨一些如何高效利用Python开发工具的建议。首先,选择合适的集成开发环...
    99+
    2023-11-23
    高效开发 开发建议 关键词:Python工具
  • 利用 Python 开发一个 Python 解释器
    目录1.标记(Token)2.词法分析器(Lexer)3.巴科斯-诺尔范式(Backus-Naur Form,BNF)4.解析器(Parser)前言: 计算机只能理解机器码。归根结底...
    99+
    2022-11-12
  • Python利用IPython提高开发效率
    一、IPython 简介 IPython 是一个交互式的 Python 解释器,而且它更加高效。 它和大多传统工作模式(编辑 -> 编译 -> 运行)不同的是, 它采用的工作模式是:执行 -&...
    99+
    2022-06-04
    效率 Python IPython
  • 如何利用Python开发一个Python解释器
    本篇文章给大家分享的是有关如何利用Python开发一个Python解释器,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。前言:计算机只能理解机器码。归根结底,编程语言只是一串文字...
    99+
    2023-06-22
  • Django开发中如何利用Python日志?
    Django是一种基于Python的Web应用程序框架,它提供了各种开箱即用的功能,包括模板引擎、ORM等。在开发过程中,我们需要对应用程序进行调试和排错,这时就需要使用日志。 Python的标准库中包含了logging模块,它提供了一个灵...
    99+
    2023-11-03
    日志 django 编程算法
  • Python怎么利用有道翻译开发API
    这篇文章主要讲解了“Python怎么利用有道翻译开发API”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python怎么利用有道翻译开发API”吧!Python源码是关于Python利用有道...
    99+
    2023-06-02
  • python开发利器之ulipad的使用实践
    介绍 UliPad是一个国人开发的python轻量级编辑器,导向和灵活的编程器。它如类浏览器,代码自动完成许多功能,如:HTML查看器,目录浏览器,向导等。 下载与安装 下载地址:https://py...
    99+
    2022-06-04
    利器 python ulipad
  • 利用Python开发一个自动答题程序
    目录环境使用模块使用自动答题思路步骤代码展示环境使用 Python 3.8 –> 解释器 <执行python代码> Pycharm –>...
    99+
    2023-02-03
    Python自动答题程序 Python自动答题 Python 答题
  • 利用Python开发实现简单的记事本
    前言 本文的操作环境:ubuntu,Python2.7,采用的是Pycharm进行代码编辑,个人很喜欢它的代码自动补齐功能。 示例图 如上图,我们可以看到这个记事本主要分为三个模块:文件,编辑和关于,结合...
    99+
    2022-06-04
    记事本 简单 Python
  • 如何利用Python开发微信公众平台
    这篇文章主要讲解了“如何利用Python开发微信公众平台”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何利用Python开发微信公众平台”吧!自动回复实现原理首先了解一下,到底是什么样的机...
    99+
    2023-06-16
  • Python开发中,如何更好地利用缓存?
    Python作为一门高效、灵活的语言,被广泛应用于各种开发场景。在Python开发中,缓存是一个非常重要的概念,它能够提高程序运行的效率。本文将介绍Python开发中如何更好地利用缓存。 一、什么是缓存? 缓存是一种将计算结果存储在内存中的...
    99+
    2023-06-28
    load 缓存 开发技术
  • python自动化测试开发利器ulipa
    介绍UliPad是一个国人开发的python轻量级编辑器,导向和灵活的编程器。它如类浏览器,代码自动完成许多功能,如:HTML查看器,目录浏览器,向导等。下载与安装下载地址:https://pypi.python.org/pypi/UliP...
    99+
    2023-01-31
    利器 测试 python
  • Python开发加薪利器之Docker的使用实践
    目录1. Docker概述1.1 虚拟机技术VS容器化技术1.2 名词概念2. Docker安装2.1 环境查看2.2 卸载旧的版本2.3 安装必要的包2.4 添加GPG密钥2.6 安装Docker引擎2.7 添加当...
    99+
    2022-06-02
    Python Docker的使用 python开发利器docker
  • 利用Python开发微信支付的注意事项
    前言 微信支付是由微信及财付通联合推出的移动支付创新产品。如今,随着微信支付的全面开放,相关需求也越来越多,很多开发人员进行微信支付开发及商家申请微信支付时,面临着诸多疑惑。 要想开发顺利进行,首先要对业务...
    99+
    2022-06-04
    注意事项 Python
  • 利用Python框架django开发资产管理系统
    概述...
    99+
    2023-06-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作