Python模块之paramiko

 

Paramiko

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

 

一、安装

1 pip3 install paramiko

二、使用

SSHClient

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

基于用户名密码连接:

 1 import paramiko
 2    
 3 # 创建SSH对象
 4 ssh = paramiko.SSHClient()
 5 # 允许连接不在know_hosts文件中的主机
 6 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
 7 # 连接服务器
 8 ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', password='123')
 9    
10 # 执行命令
11 stdin, stdout, stderr = ssh.exec_command('ls')
12 # 获取命令结果
13 result = stdout.read()
14    
15 # 关闭连接
16 ssh.close()
 1 import paramiko
 2 
 3 transport = paramiko.Transport(('hostname', 22))
 4 transport.connect(username='wupeiqi', password='123')
 5 
 6 ssh = paramiko.SSHClient()
 7 ssh._transport = transport
 8 
 9 stdin, stdout, stderr = ssh.exec_command('df')
10 print stdout.read()
11 
12 transport.close()
13 
14 SSHClient 封装 Transport
SSHClient 封装 Transport

基于公钥密钥连接:

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='wupeiqi', key=private_key)
  
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
  
# 关闭连接
ssh.close()
 1 import paramiko
 2 
 3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
 4 
 5 transport = paramiko.Transport(('hostname', 22))
 6 transport.connect(username='wupeiqi', pkey=private_key)
 7 
 8 ssh = paramiko.SSHClient()
 9 ssh._transport = transport
10 
11 stdin, stdout, stderr = ssh.exec_command('df')
12 
13 transport.close()
14 
15 SSHClient 封装 Transport
SSHClient 封装 Transport
 1 import paramiko
 2 from io import StringIO
 3 
 4 key_str = """-----BEGIN RSA PRIVATE KEY-----
 5 MIIEpQIBAAKCAQEAq7gLsqYArAFco02/55IgNg0r7NXOtEM3qXpb/dabJ5Uyky/8
 6 NEHhFiQ7deHIRIuTW5Zb0kD6h6EBbVlUMBmwJrC2oSzySLU1w+ZNfH0PE6W6fans
 7 H80whhuc/YgP+fjiO+VR/gFcqib8Rll5UfYzf5H8uuOnDeIXGCVgyHQSmt8if1+e
 8 7hn1MVO1Lrm9Fco8ABI7dyv8/ZEwoSfh2C9rGYgA58LT1FkBRkOePbHD43xNfAYC
 9 tfLvz6LErMnwdOW4sNMEWWAWv1fsTB35PAm5CazfKzmam9n5IQXhmUNcNvmaZtvP
10 c4f4g59mdsaWNtNaY96UjOfx83Om86gmdkKcnwIDAQABAoIBAQCnDBGFJuv8aA7A
11 ZkBLe+GN815JtOyye7lIS1n2I7En3oImoUWNaJEYwwJ8+LmjxMwDCtAkR0XwbvY+
12 c+nsKPEtkjb3sAu6I148RmwWsGncSRqUaJrljOypaW9dS+GO4Ujjz3/lw1lrxSUh
13 IqVc0E7kyRW8kP3QCaNBwArYteHreZFFp6XmtKMtXaEA3saJYILxaaXlYkoRi4k8
14 S2/K8aw3ZMR4tDCOfB4o47JaeiA/e185RK3A+mLn9xTDhTdZqTQpv17/YRPcgmwz
15 zu30fhVXQT/SuI0sO+bzCO4YGoEwoBX718AWhdLJFoFq1B7k2ZEzXTAtjEXQEWm6
16 01ndU/jhAasdfasdasdfasdfa3eraszxqwefasdfadasdffsFIfAsjQb4HdkmHuC
17 OeJrJOd+CYvdEeqJJNnF6AbHyYHIECkj0Qq1kEfLOEsqzd5nDbtkKBte6M1trbjl
18 HtJ2Yb8w6o/q/6Sbj7wf/cW3LIYEdeVCjScozVcQ9R83ea05J+QOAr4nAoGBAMaq
19 UzLJfLNWZ5Qosmir2oHStFlZpxspax/ln7DlWLW4wPB4YJalSVovF2Buo8hr8X65
20 lnPiE41M+G0Z7icEXiFyDBFDCtzx0x/RmaBokLathrFtI81UCx4gQPLaSVNMlvQA
21 539GsubSrO4LpHRNGg/weZ6EqQOXvHvkUkm2bDDJAoGATytFNxen6GtC0ZT3SRQM
22 WYfasdf3xbtuykmnluiofasd2sfmjnljkt7khghmghdasSDFGQfgaFoKfaawoYeH
23 C2XasVUsVviBn8kPSLSVBPX4JUfQmA6h8HsajeVahxN1U9e0nYJ0sYDQFUMTS2t8
24 RT57+WK/0ONwTWHdu+KnaJECgYEAid/ta8LQC3p82iNAZkpWlGDSD2yb/8rH8NQg
25 9tjEryFwrbMtfX9qn+8srx06B796U3OjifstjJQNmVI0qNlsJpQK8fPwVxRxbJS/
26 pMbNICrf3sUa4sZgDOFfkeuSlgACh4cVIozDXlR59Z8Y3CoiW0uObEgvMDIfenAj
27 98pl3ZkCgYEAj/UCSni0dwX4pnKNPm6LUgiS7QvIgM3H9piyt8aipQuzBi5LUKWw
28 DlQC4Zb73nHgdREtQYYXTu7p27Bl0Gizz1sW2eSgxFU8eTh+ucfVwOXKAXKU5SeI
29 +MbuBfUYQ4if2N/BXn47+/ecf3A4KgB37Le5SbLDddwCNxGlBzbpBa0=
30 -----END RSA PRIVATE KEY-----"""
31 
32 private_key = paramiko.RSAKey(file_obj=StringIO(key_str))
33 transport = paramiko.Transport(('10.0.1.40', 22))
34 transport.connect(username='wupeiqi', pkey=private_key)
35 
36 ssh = paramiko.SSHClient()
37 ssh._transport = transport
38 
39 stdin, stdout, stderr = ssh.exec_command('df')
40 result = stdout.read()
41 
42 transport.close()
43 
44 print(result)
45 
46 基于私钥字符进行连接
基于私钥字符进行连接

SFTPClient

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

基于用户名密码上传下载:

 1 import paramiko
 2   
 3 transport = paramiko.Transport(('hostname',22))
 4 transport.connect(username='wupeiqi',password='123')
 5   
 6 sftp = paramiko.SFTPClient.from_transport(transport)
 7 # 将location.py 上传至服务器 /tmp/test.py
 8 sftp.put('/tmp/location.py', '/tmp/test.py')
 9 # 将remove_path 下载到本地 local_path
10 sftp.get('remove_path', 'local_path')
11   
12 transport.close()

基于公钥密钥上传下载:

 1 import paramiko
 2   
 3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
 4   
 5 transport = paramiko.Transport(('hostname', 22))
 6 transport.connect(username='wupeiqi', pkey=private_key )
 7   
 8 sftp = paramiko.SFTPClient.from_transport(transport)
 9 # 将location.py 上传至服务器 /tmp/test.py
10 sftp.put('/tmp/location.py', '/tmp/test.py')
11 # 将remove_path 下载到本地 local_path
12 sftp.get('remove_path', 'local_path')
13   
14 transport.close()
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 import paramiko
 4 import uuid
 5 
 6 class SSHConnection(object):
 7 
 8     def __init__(self, host='172.16.103.191', port=22, username='wupeiqi',pwd='123'):
 9         self.host = host
10         self.port = port
11         self.username = username
12         self.pwd = pwd
13         self.__k = None
14 
15     def create_file(self):
16         file_name = str(uuid.uuid4())
17         with open(file_name,'w') as f:
18             f.write('sb')
19         return file_name
20 
21     def run(self):
22         self.connect()
23         self.upload('/home/wupeiqi/tttttttttttt.py')
24         self.rename('/home/wupeiqi/tttttttttttt.py', '/home/wupeiqi/ooooooooo.py)
25         self.close()
26 
27     def connect(self):
28         transport = paramiko.Transport((self.host,self.port))
29         transport.connect(username=self.username,password=self.pwd)
30         self.__transport = transport
31 
32     def close(self):
33 
34         self.__transport.close()
35 
36     def upload(self,target_path):
37         # 连接,上传
38         file_name = self.create_file()
39 
40         sftp = paramiko.SFTPClient.from_transport(self.__transport)
41         # 将location.py 上传至服务器 /tmp/test.py
42         sftp.put(file_name, target_path)
43 
44     def rename(self, old_path, new_path):
45 
46         ssh = paramiko.SSHClient()
47         ssh._transport = self.__transport
48         # 执行命令
49         cmd = "mv %s %s" % (old_path, new_path,)
50         stdin, stdout, stderr = ssh.exec_command(cmd)
51         # 获取命令结果
52         result = stdout.read()
53 
54     def cmd(self, command):
55         ssh = paramiko.SSHClient()
56         ssh._transport = self.__transport
57         # 执行命令
58         stdin, stdout, stderr = ssh.exec_command(command)
59         # 获取命令结果
60         result = stdout.read()
61         return result
62         
63 
64 
65 ha = SSHConnection()
66 ha.run()
67 
68 Demo
demo
1 # 对于更多限制命令,需要在系统中设置
2 /etc/sudoers
3   
4 Defaults    requiretty
5 Defaults:cmdb    !requiretty
View Code
 1 import paramiko
 2 import uuid
 3 
 4 class SSHConnection(object):
 5 
 6     def __init__(self, host='192.168.11.61', port=22, username='alex',pwd='alex3714'):
 7         self.host = host
 8         self.port = port
 9         self.username = username
10         self.pwd = pwd
11         self.__k = None
12 
13     def run(self):
14         self.connect()
15         pass
16         self.close()
17 
18     def connect(self):
19         transport = paramiko.Transport((self.host,self.port))
20         transport.connect(username=self.username,password=self.pwd)
21         self.__transport = transport
22 
23     def close(self):
24         self.__transport.close()
25 
26     def cmd(self, command):
27         ssh = paramiko.SSHClient()
28         ssh._transport = self.__transport
29         # 执行命令
30         stdin, stdout, stderr = ssh.exec_command(command)
31         # 获取命令结果
32         result = stdout.read()
33         return result
34 
35     def upload(self,local_path, target_path):
36         # 连接,上传
37         sftp = paramiko.SFTPClient.from_transport(self.__transport)
38         # 将location.py 上传至服务器 /tmp/test.py
39         sftp.put(local_path, target_path)
40 
41 ssh = SSHConnection()
42 ssh.connect()
43 r1 = ssh.cmd('df')
44 ssh.upload('s2.py', "/home/alex/s7.py")
45 ssh.close()
46 
47 Demo
Demo

堡垒机

堡垒机执行流程:

  1. 管理员为用户在服务器上创建账号(将公钥放置服务器,或者使用用户名密码)
  2. 用户登陆堡垒机,输入堡垒机用户名密码,现实当前用户管理的服务器列表
  3. 用户选择服务器,并自动登陆
  4. 执行操作并同时将用户操作记录

注:配置.brashrc实现ssh登陆后自动执行脚本,如:/usr/bin/python /home/wupeiqi/menu.py

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 from sqlalchemy import create_engine, and_, or_, func, Table
 5 from sqlalchemy.ext.declarative import declarative_base
 6 from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, DateTime
 7 from sqlalchemy.orm import sessionmaker, relationship
 8 
 9 Base = declarative_base()  # 生成一个SqlORM 基类
10 
11 
12 class Host(Base):
13     __tablename__ = 'host'
14     id = Column(Integer, primary_key=True, autoincrement=True)
15     hostname = Column(String(64), unique=True, nullable=False)
16     ip_addr = Column(String(128), unique=True, nullable=False)
17     port = Column(Integer, default=22)
18 
19 
20 class HostUser(Base):
21     __tablename__ = 'host_user'
22     id = Column(Integer, primary_key=True, autoincrement=True)
23     username = Column(String(64), unique=True, nullable=False)
24     AuthTypes = [
25         ('p', 'SSH/Password'),
26         ('r', 'SSH/KEY'),
27     ]
28     auth_type = Column(String(16))
29     cert = Column(String(255))
30 
31     host_id = Column(Integer, ForeignKey('host.id'))
32 
33     __table_args__ = (
34         UniqueConstraint('host_id', 'username', name='_host_username_uc'),
35     )
36 
37 
38 class Group(Base):
39     __tablename__ = 'group'
40     id = Column(Integer, primary_key=True, autoincrement=True)
41     name = Column(String(64), unique=True, nullable=False)
42 
43 
44 class UserProfile(Base):
45     __tablename__ = 'user_profile'
46     id = Column(Integer, primary_key=True, autoincrement=True)
47     username = Column(String(64), unique=True, nullable=False)
48     password = Column(String(255), nullable=False)
49 
50 
51 class Group2UserProfile(Base):
52     __tablename__ = 'group_2_user_profile'
53     id = Column(Integer, primary_key=True, autoincrement=True)
54     user_profile_id = Column(Integer, ForeignKey('user_profile.id'))
55     group_id = Column(Integer, ForeignKey('group.id'))
56     __table_args__ = (
57         UniqueConstraint('user_profile_id', 'group_id', name='ux_user_group'),
58     )
59 
60 
61 class Group2HostUser(Base):
62     __tablename__ = 'group_2_host_user'
63     id = Column(Integer, primary_key=True, autoincrement=True)
64     host_user_id = Column(Integer, ForeignKey('host_user.id'))
65     group_id = Column(Integer, ForeignKey('group.id'))
66     __table_args__ = (
67         UniqueConstraint('group_id', 'host_user_id', name='ux_group_host_user'),
68     )
69 
70 
71 class UserProfile2HostUser(Base):
72     __tablename__ = 'user_profile_2_host_user'
73     id = Column(Integer, primary_key=True, autoincrement=True)
74     host_user_id = Column(Integer, ForeignKey('host_user.id'))
75     user_profile_id = Column(Integer, ForeignKey('user_profile.id'))
76     __table_args__ = (
77         UniqueConstraint('user_profile_id', 'host_user_id', name='ux_user_host_user'),
78     )
79 
80 
81 class AuditLog(Base):
82     __tablename__ = 'audit_log'
83     id = Column(Integer, primary_key=True, autoincrement=True)
84 
85     action_choices2 = [
86         (u'cmd', u'CMD'),
87         (u'login', u'Login'),
88         (u'logout', u'Logout'),
89     ]
90     action_type = Column(String(16))
91     cmd = Column(String(255))
92     date = Column(DateTime)
93     user_profile_id = Column(Integer, ForeignKey('user_profile.id'))
94     host_user_id = Column(Integer, ForeignKey('host_user.id'))
95 
96 表结构示例
表结构示例

实现过程

1、前戏

 1 import paramiko
 2 import sys
 3 import os
 4 import socket
 5 import select
 6 import getpass
 7  
 8 tran = paramiko.Transport(('10.211.55.4', 22,))
 9 tran.start_client()
10 tran.auth_password('wupeiqi', '123')
11  
12 # 打开一个通道
13 chan = tran.open_session()
14 # 获取一个终端
15 chan.get_pty()
16 # 激活器
17 chan.invoke_shell()
18  
19 #########
20 # 利用sys.stdin,肆意妄为执行操作
21 # 用户在终端输入内容,并将内容发送至远程服务器
22 # 远程服务器执行命令,并将结果返回
23 # 用户终端显示内容
24 #########
25  
26 chan.close()
27 tran.close()

2、肆意妄为(一)

 1 import paramiko
 2 import sys
 3 import os
 4 import socket
 5 import select
 6 import getpass
 7 from paramiko.py3compat import u
 8  
 9 tran = paramiko.Transport(('10.211.55.4', 22,))
10 tran.start_client()
11 tran.auth_password('wupeiqi', '123')
12  
13 # 打开一个通道
14 chan = tran.open_session()
15 # 获取一个终端
16 chan.get_pty()
17 # 激活器
18 chan.invoke_shell()
19  
20 while True:
21     # 监视用户输入和服务器返回数据
22     # sys.stdin 处理用户输入
23     # chan 是之前创建的通道,用于接收服务器返回信息
24     readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1)
25     if chan in readable:
26         try:
27             x = u(chan.recv(1024))
28             if len(x) == 0:
29                 print('\r\n*** EOF\r\n')
30                 break
31             sys.stdout.write(x)
32             sys.stdout.flush()
33         except socket.timeout:
34             pass
35     if sys.stdin in readable:
36         inp = sys.stdin.readline()
37         chan.sendall(inp)
38  
39 chan.close()
40 tran.close()
View Code
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 import paramiko
 5 import sys
 6 import os
 7 import socket
 8 import select
 9 import getpass
10 from paramiko.py3compat import u
11 
12 
13 default_username = getpass.getuser()
14 username = input('Username [%s]: ' % default_username)
15 if len(username) == 0:
16     username = default_username
17 
18 
19 hostname = input('Hostname: ')
20 if len(hostname) == 0:
21     print('*** Hostname required.')
22     sys.exit(1)
23 
24 tran = paramiko.Transport((hostname, 22,))
25 tran.start_client()
26 
27 default_auth = "p"
28 auth = input('Auth by (p)assword or (r)sa key[%s] ' % default_auth)
29 if len(auth) == 0:
30     auth = default_auth
31 
32 if auth == 'r':
33     default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
34     path = input('RSA key [%s]: ' % default_path)
35     if len(path) == 0:
36         path = default_path
37     try:
38         key = paramiko.RSAKey.from_private_key_file(path)
39     except paramiko.PasswordRequiredException:
40         password = getpass.getpass('RSA key password: ')
41         key = paramiko.RSAKey.from_private_key_file(path, password)
42     tran.auth_publickey(username, key)
43 else:
44     pw = getpass.getpass('Password for %s@%s: ' % (username, hostname))
45     tran.auth_password(username, pw)
46 
47 
48 
49 # 打开一个通道
50 chan = tran.open_session()
51 # 获取一个终端
52 chan.get_pty()
53 # 激活器
54 chan.invoke_shell()
55 
56 while True:
57     # 监视用户输入和服务器返回数据
58     # sys.stdin 处理用户输入
59     # chan 是之前创建的通道,用于接收服务器返回信息
60     readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1)
61     if chan in readable:
62         try:
63             x = u(chan.recv(1024))
64             if len(x) == 0:
65                 print('\r\n*** EOF\r\n')
66                 break
67             sys.stdout.write(x)
68             sys.stdout.flush()
69         except socket.timeout:
70             pass
71     if sys.stdin in readable:
72         inp = sys.stdin.readline()
73         chan.sendall(inp)
74 
75 chan.close()
76 tran.close()
77 
78 完整示例(一)
完整示例(一)

3、肆意妄为(二)

 1 import paramiko
 2 import sys
 3 import os
 4 import socket
 5 import select
 6 import getpass
 7 import termios
 8 import tty
 9 from paramiko.py3compat import u
10  
11 tran = paramiko.Transport(('10.211.55.4', 22,))
12 tran.start_client()
13 tran.auth_password('wupeiqi', '123')
14  
15 # 打开一个通道
16 chan = tran.open_session()
17 # 获取一个终端
18 chan.get_pty()
19 # 激活器
20 chan.invoke_shell()
21  
22  
23 # 获取原tty属性
24 oldtty = termios.tcgetattr(sys.stdin)
25 try:
26     # 为tty设置新属性
27     # 默认当前tty设备属性:
28     #   输入一行回车,执行
29     #   CTRL+C 进程退出,遇到特殊字符,特殊处理。
30  
31     # 这是为原始模式,不认识所有特殊符号
32     # 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器
33     tty.setraw(sys.stdin.fileno())
34     chan.settimeout(0.0)
35  
36     while True:
37         # 监视 用户输入 和 远程服务器返回数据(socket)
38         # 阻塞,直到句柄可读
39         r, w, e = select.select([chan, sys.stdin], [], [], 1)
40         if chan in r:
41             try:
42                 x = u(chan.recv(1024))
43                 if len(x) == 0:
44                     print('\r\n*** EOF\r\n')
45                     break
46                 sys.stdout.write(x)
47                 sys.stdout.flush()
48             except socket.timeout:
49                 pass
50         if sys.stdin in r:
51             x = sys.stdin.read(1)
52             if len(x) == 0:
53                 break
54             chan.send(x)
55  
56 finally:
57     # 重新设置终端属性
58     termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
59  
60  
61 chan.close()
62 tran.close()
View Code
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 import paramiko
 4 import sys
 5 import os
 6 import socket
 7 import getpass
 8 import termios
 9 import tty
10 import select
11 from paramiko.py3compat import u
12 
13 
14 def interactive_shell(chan):
15     # 获取原tty属性
16     oldtty = termios.tcgetattr(sys.stdin)
17     try:
18         # 为tty设置新属性
19         # 默认当前tty设备属性:
20         #   输入一行回车,执行
21         #   CTRL+C 进程退出,遇到特殊字符,特殊处理。
22 
23         # 这是为原始模式,不认识所有特殊符号
24         # 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器
25         tty.setraw(sys.stdin.fileno())
26         tty.setcbreak(sys.stdin.fileno())
27         chan.settimeout(0.0)
28         while True:
29             r, w, e = select.select([chan, sys.stdin], [], [])
30             if chan in r:
31                 try:
32                     x = u(chan.recv(1024))
33                     if len(x) == 0:
34                         sys.stdout.write('\r\n*** EOF\r\n')
35                         break
36                     sys.stdout.write(x)
37                     sys.stdout.flush()
38                 except socket.timeout:
39                     pass
40             if sys.stdin in r:
41                 x = sys.stdin.read(1)
42                 if len(x) == 0:
43                     break
44                 chan.send(x)
45 
46     finally:
47         # 重新设置终端属性
48         termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
49 
50 
51 def run():
52     hostname = input('请输入主机名: ')
53     tran = paramiko.Transport((hostname, 22,))
54     tran.start_client()
55 
56     username = input('请输入用户名: ')
57     auth = input('请输入密码进行验证(p) 或 (r)sa Key进行验证?')
58     if auth == 'r':
59         path = input('请输入RSA key 路径: ')
60         try:
61             key = paramiko.RSAKey.from_private_key_file(path)
62         except paramiko.PasswordRequiredException:
63             password = getpass.getpass('RSA key password: ')
64             key = paramiko.RSAKey.from_private_key_file(path, password)
65         tran.auth_publickey(username, key)
66     else:
67         pw = getpass.getpass('请输入密码 %s@%s: ' % (username, hostname))
68         tran.auth_password(username, pw)
69 
70     # 打开一个通道
71     chan = tran.open_session()
72     # 获取一个终端
73     chan.get_pty()
74     # 激活器
75     chan.invoke_shell()
76 
77     interactive_shell(chan)
78 
79     chan.close()
80     tran.close()
81 
82 
83 if __name__ == '__main__':
84     run()
85 
86 基于Passwd或者RSA进行登陆操作
基于Passwd或者RSA进行登陆操作
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 import paramiko
 4 import sys
 5 import os
 6 import socket
 7 import getpass
 8 import termios
 9 import tty
10 import select
11 from paramiko.py3compat import u
12 
13 
14 def interactive_shell(chan):
15     # 获取原tty属性
16     oldtty = termios.tcgetattr(sys.stdin)
17     try:
18         # 为tty设置新属性
19         # 默认当前tty设备属性:
20         # 输入一行回车,执行
21         # CTRL+C 进程退出,遇到特殊字符,特殊处理。
22 
23         # 这是为原始模式,不认识所有特殊符号
24         # 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器
25         tty.setraw(sys.stdin.fileno())
26         tty.setcbreak(sys.stdin.fileno())
27         chan.settimeout(0.0)
28         while True:
29             r, w, e = select.select([chan, sys.stdin], [], [])
30             if chan in r:
31                 try:
32                     x = u(chan.recv(1024))
33                     if len(x) == 0:
34                         sys.stdout.write('\r\n*** EOF\r\n')
35                         break
36                     sys.stdout.write(x)
37                     sys.stdout.flush()
38                 except socket.timeout:
39                     pass
40             if sys.stdin in r:
41                 x = sys.stdin.read(1)
42                 if len(x) == 0:
43                     break
44                 chan.send(x)
45 
46     finally:
47         # 重新设置终端属性
48         termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
49 
50 
51 def run():
52     db_dict = {
53         'c1.salt.com': {
54             'root': {'user': 'root', 'auth': 'r', "cert": 'key路径'},
55             'alex': {'user': 'alex', 'auth': 'p', "cert": '密码'},
56         },
57         'c2.salt.com': {
58             'alex': {'user': 'alex', 'auth': 'p', "cert": '密码'},
59         },
60 
61     }
62 
63     for row in db_dict.keys():
64         print(row)
65 
66     hostname = input('请选择主机: ')
67     tran = paramiko.Transport((hostname, 22,))
68     tran.start_client()
69 
70     for item in db_dict[hostname].keys():
71         print(item)
72 
73     username = input('请输入用户: ')
74 
75     user_dict = db_dict[hostname][username]
76     if username['auth'] == 'r':
77         key = paramiko.RSAKey.from_private_key_file(user_dict['cert'])
78         tran.auth_publickey(username, key)
79     else:
80         pw = user_dict['cert']
81         tran.auth_password(username, pw)
82 
83     # 打开一个通道
84     chan = tran.open_session()
85     # 获取一个终端
86     chan.get_pty()
87     # 激活器
88     chan.invoke_shell()
89 
90     interactive_shell(chan)
91 
92     chan.close()
93     tran.close()
94 
95 
96 if __name__ == '__main__':
97     run()
98 
99 提示用户选择主机和用户
提示用户选择主机和用户
  1 #!/usr/bin/env python
  2 # -*- coding:utf-8 -*-
  3 import paramiko
  4 import sys
  5 import os
  6 import socket
  7 import getpass
  8 import termios
  9 import tty
 10 import select
 11 from paramiko.py3compat import u
 12 
 13 
 14 def interactive_shell(chan):
 15     # 获取原tty属性
 16     oldtty = termios.tcgetattr(sys.stdin)
 17     try:
 18         # 为tty设置新属性
 19         # 默认当前tty设备属性:
 20         # 输入一行回车,执行
 21         # CTRL+C 进程退出,遇到特殊字符,特殊处理。
 22 
 23         # 这是为原始模式,不认识所有特殊符号
 24         # 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器
 25         tty.setraw(sys.stdin.fileno())
 26         tty.setcbreak(sys.stdin.fileno())
 27         chan.settimeout(0.0)
 28 
 29         log = open('handle.log', 'a+', encoding='utf-8')
 30         flag = False
 31         temp_list = []
 32 
 33         while True:
 34             r, w, e = select.select([chan, sys.stdin], [], [])
 35             if chan in r:
 36                 try:
 37                     x = u(chan.recv(1024))
 38                     if len(x) == 0:
 39                         sys.stdout.write('\r\n*** EOF\r\n')
 40                         break
 41                     # 如果用户上一次点击的是tab键,则获取返回的内容写入在记录中
 42                     if flag:
 43                         if x.startswith('\r\n'):
 44                             pass
 45                         else:
 46                             temp_list.append(x)
 47                         flag = False
 48                     sys.stdout.write(x)
 49                     sys.stdout.flush()
 50                 except socket.timeout:
 51                     pass
 52             if sys.stdin in r:
 53                 # 读取用户在终端数据每一个字符
 54                 x = sys.stdin.read(1)
 55                 if len(x) == 0:
 56                     break
 57                 # 如果用户点击TAB键
 58                 if x == '\t':
 59                     flag = True
 60                 else:
 61                     # 未点击TAB键,则将每个操作字符记录添加到列表中,以便之后写入文件
 62                     temp_list.append(x)
 63 
 64                 # 如果用户敲回车,则将操作记录写入文件
 65                 if x == '\r':
 66                     log.write(''.join(temp_list))
 67                     log.flush()
 68                     temp_list.clear()
 69                 chan.send(x)
 70 
 71     finally:
 72         # 重新设置终端属性
 73         termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
 74 
 75 
 76 def run():
 77     db_dict = {
 78         'c1.salt.com': {
 79             'root': {'user': 'root', 'auth': 'r', "cert": 'key路径'},
 80             'alex': {'user': 'alex', 'auth': 'p', "cert": '密码'},
 81         },
 82         'c2.salt.com': {
 83             'root': {'user': 'root', 'auth': 'r', "cert": 'key路径'},
 84             'alex': {'user': 'alex', 'auth': 'p', "cert": '密码'},
 85         },
 86 
 87     }
 88 
 89     for row in db_dict.keys():
 90         print(row)
 91 
 92     hostname = input('请选择主机: ')
 93     tran = paramiko.Transport((hostname, 22,))
 94     tran.start_client()
 95 
 96     for item in db_dict[hostname].keys():
 97         print(item)
 98 
 99     username = input('请输入用户: ')
100 
101     user_dict = db_dict[hostname][username]
102     if username['auth'] == 'r':
103         key = paramiko.RSAKey.from_private_key_file(user_dict['cert'])
104         tran.auth_publickey(username, key)
105     else:
106         pw = user_dict['cert']
107         tran.auth_password(username, pw)
108 
109     # 打开一个通道
110     chan = tran.open_session()
111     # 获取一个终端
112     chan.get_pty()
113     # 激活器
114     chan.invoke_shell()
115 
116     interactive_shell(chan)
117 
118     chan.close()
119     tran.close()
120 
121 
122 if __name__ == '__main__':
123     run()
124 
125 提示用户选择主机和用户(记录操作日志)
提示用户选择主机和用户(记录操作日志)

更多参见:paramoko源码 https://github.com/paramiko/paramiko 

武沛齐:http://www.cnblogs.com/wupeiqi/p/5699254.html

Alex堡垒机:http://www.cnblogs.com/alex3714/articles/5286889.html 

 

posted @ 2017-05-15 12:03  浮光掠影转瞬间  阅读(45456)  评论(3编辑  收藏  举报