堡垒机实例以及执行命令

Python的paramiko模块,该模块基于SSH用于连接远程服务器并执行相关操作。

SSHClient

用于连接远程服务器并执行基本命令

基于用户名密码连接:

方法1:

import paramiko

# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='c1.salt.com', port=22, username='root', password='123')

# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()

# 关闭连接
ssh.close()

方法2:

使用transport封装来实现

import paramiko
#  封装transport  获取到主机、端口、用户名、密码
transport = paramiko.Transport(('192.168.56.11', 22))
transport.connect(username='root', password='123')

# 基于transport来连接
ssh = paramiko.SSHClient()
ssh._transport = transport

# 执行命令,标准输入、输出、错误
stdin, stdout, stderr = ssh.exec_command('df')
print stdout.read()

transport.close()

基于密钥的连接

方法1:

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')

# 创建SSH对象
ssh = paramiko.SSHClient()

# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# 连接服务器
ssh.connect(hostname='c1.salt.com', port=22, username='root', key=private_key)

# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')

# 获取命令结果
result = stdout.read()

# 关闭连接
ssh.close()

方式二:

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')

transport = paramiko.Transport(('192.168.56.12', 22))
transport.connect(username='root', pkey=private_key)

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('df')

transport.close()

SFTPClient

用于连接远程服务器并执行上传下载

基于用户名密码上传下载

import paramiko

transport = paramiko.Transport(('192.168.56.12',22))
transport.connect(username='root',password='123')

sftp = paramiko.SFTPClient.from_transport(transport)

# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')

# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')

transport.close()

基于公钥密钥上传下载

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')

# 封装transport对象
transport = paramiko.Transport(('192.168.56.12', 22))
transport.connect(username='root', pkey=private_key )

# 调用执行
sftp = paramiko.SFTPClient.from_transport(transport)

# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')

# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
# 关闭连接
transport.close()

使用paramiko使用简单的上传下载

方式一:

连接方式选择不实用transport的方式

#!/usr/bin/env python
# coding:utf-8
import  paramiko
import uuid

class haproxy(object):
    # 初始化
    def __init__(self):
        self.host = '192.168.56.11'
        self.port = 22
        self.username = 'root'
        self.pwd = '123456'
    # 创建文件,使用UUID来生成名字,一个字符串
    def creat_file(self):
        file_name = str(uuid.uuid4())
        with open(file_name,'w') as f:
            f.write('sbsbsbsbsb')
        # 将文件名封装到内存中
        return file_name

    def run(self):
        self.upload()
        self.rename()
    # 上传文件
    def upload(self):
        # 在本地创建文件,名称是file_name
        file_name = self.creat_file()
        transport = paramiko.Transport((self.host, self.port))
        transport.connect(username=self.username, password=self.pwd)
        sftp = paramiko.SFTPClient.from_transport(transport)
        # 将location.py 上传至服务器 /tmp/test.py
        sftp.put(file_name, '/home/root/dddddddddddddd.py')
        transport.close()
    # 文件重命名
    def rename(self):
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(hostname=self.host, port=self.port, username=self.username, password=self.pwd)
        stdin,stdout,stderr = ssh.exec_command('mv /home/root/dddddddddddddd.py /home/root/ssssssssssss.py')
        result = stdout.read()
        ssh.close()

a = haproxy()
a.run()

方法2:

使用transport连接方式

#!/usr/bin/env python
# coding:utf-8
import  paramiko

import uuid
class haproxy(object):
    def __init__(self):
        self.host = '192.168.56.12'
        self.port = 22
        self.username = 'root'
        self.pwd = '123456'

    def creat_file(self):
        file_name = str(uuid.uuid4())
        with open(file_name,'w') as f:
            f.write('sbsbsbsbsb')
        return file_name

    def run(self):
        self.connect()
        self.upload()
        self.rename()
        self.close()

    def connect(self):
        transport = paramiko.Transport((self.host, self.port))
        transport.connect(username=self.username, password=self.pwd)
        self.__transport = transport
    def close(self):
        self.__transport.close()

    def upload(self):
        self.__transport = self.__transport
        file_name = self.creat_file()
        sftp = paramiko.SFTPClient.from_transport(self.__transport)
        # 将location.py 上传至服务器 /tmp/test.py
        sftp.put(file_name, '/ssssssssssss.py')


    def rename(self):
        ssh = paramiko.SSHClient()
        self.__transport = self.__transport
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(hostname=self.host, port=self.port, username=self.username, password=self.pwd)
        stdin,stdout,stderr = ssh.exec_command('mv /ssssssssssss.py /dddddddddddddd.py')
        result = stdout.read()


a = haproxy()
a.run()

之前上面的两种实现方式都不能实现持续连接服务器,下面咱们来搞搞让他更持久。。。。。

持久一:

他会直接连接到远程服务器上

#!/usr/bin/env python
# coding:utf-8
import sys
import select
import socket
import paramiko

# 使用transport封装一个tran,
tran = paramiko.Transport(('192.168.56.12',22))
tran.start_client()
# 使用用户名密码的方式连接
tran.auth_password('root','123456')
# 打开一个通道
chan = tran.open_session()
# 获取一个终端
chan.get_pty()
# 激活器
chan.invoke_shell()


while True:
    # 使用select来检测,chan和sys.stdin这两个句柄有没有发生变化
    # 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 '
*** EOF
',
                break
            sys.stdout.write(x)
            sys.stdout.flush()
        except socket.timeout:
            pass
    # 如果stdin中有内容,那么就发送给远端服务器
    if sys.stdin in readable:
        inp = sys.stdin.readable()
        chan.sendall(inp)

chan.close()
tran.close()
 

上面代码的问题:用户输入内容后,只有点击回车,才会放到stdin中,才会发送给服务器端。

持久二:

更新tab补全功能,与标准模式个原生模式的转换

#!/usr/bin/env python
# coding:utf-8
import sys
import select
import socket
import paramiko
import termios
import tty

tran = paramiko.Transport(('192.168.56.12',22))
tran.start_client()

tran.auth_password('root','123456')

chan = tran.open_session()

chan.get_pty()
chan.invoke_shell()

# 获取原tty属性
oldtty = termios.tcgetattr(sys.stdin)
try:
    # 为tty设置一个新的属性
    # 默认的属性是:输入一行回车,然后执行
    # crtl+C进程退出,遇到特殊字符,特殊处理
    # 这是为原始模式,不认识所有特殊字符
    # 放置特殊字符应该用在当前终端,将所有的用户输入均发送到远程服务器
    tty.setraw(sys.stdin.fileno())
    chan.settimeout(0.0)
    while True:
        # 监视 用户的输入和远程服务器返回数据
        # 阻塞,知道句柄有内容可读
        r,w,e = select.select([chan,sys.stdin],[],[],1)
        if chan in r:
            try:
                x =chan.recv(1024)
                if len(x)==0:
                    print '
*** EOF
',
                    break
            except socket.timeout:
                pass
        if sys.stdin in r:
            x = sys.stdin.read(1)
            if len(x)==0:
                break
            chan.send(x)
finally:
    # 重新将终端设置为标准的属性
    termios.tcgetattr(sys.stdin,termios.TCSADRAIN,oldtty)

chan.close()
tran.close()

 

 

 

 

原文地址:https://www.cnblogs.com/caoxiaojian/p/5130923.html