Python----Paramiko模块和堡垒机实战
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Python----Paramiko模块和堡垒机实战,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含25223字,纯文字阅读大概需要37分钟。
内容图文
paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实。其实它的底层是对ssh的上层代码的一个封装
一、下载安装
1
2
3
|
#pycrypto,由于 paramiko 模块内部依赖pycrypto,所以先下载安装pycrypto
tomcat@node:~$ pip install pycrypto
tomcat@node:~$ pip install paramiko
|
二、模块使用
1、SSHClient?用于连接远程服务器并执行基本命令
(1)基于用户名密码连接两种方式:
-->第一种
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import?paramiko
????
# 创建SSH对象
ssh?=?paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname=‘192.168.1.21‘, port=22, username=‘root‘, password=‘123456‘)
????
# 执行命令
stdin, stdout, stderr?=?ssh.exec_command(‘ls‘)
# 获取命令结果
result?=?stdout.read()
????
# 关闭连接
ssh.close()
|
-->二种:SSHClient 封装 Transport
1
2
3
4
5
6
7
8
9
10
11
12
|
import?paramiko
?
transport?=?paramiko.Transport((‘192.168.1.21‘,?22))
transport.connect(username=‘root‘, password=‘123456‘)
?
ssh?=?paramiko.SSHClient()
ssh._transport?=?transport
?
stdin, stdout, stderr?=?ssh.exec_command(‘df‘)
print?stdout.read()
?
transport.close()
|
(2)基于公钥密钥连接的两种方式:
-->第一种
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import?paramiko
???
private_key?=?paramiko.RSAKey.from_private_key_file(‘/root/.ssh/id_rsa‘)
???
# 创建SSH对象
ssh?=?paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname=‘192.168.1.21‘, port=22, username=‘root‘, key=private_key)
???
# 执行命令
stdin, stdout, stderr?=?ssh.exec_command(‘df‘)
# 获取命令结果
result?=?stdout.read()
???
# 关闭连接
ssh.close()
|
-->第二种:SSHClient 封装 Transport
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import?paramiko
?
private_key?=?paramiko.RSAKey.from_private_key_file(‘/root/.ssh/id_rsa‘)
?
transport?=?paramiko.Transport((‘192.168.1.21‘,?22))
transport.connect(username=‘root‘, pkey=private_key)
?
ssh?=?paramiko.SSHClient()
ssh._transport?=?transport
?
stdin, stdout, stderr?=?ssh.exec_command(‘df‘)
?
transport.close()
|
2、SFTPClient用于连接远程服务器并执行上传下载
(1)基于用户名密码上传下载:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import?paramiko
???
transport?=?paramiko.Transport((‘192.168.1.21‘,22))
transport.connect(username=‘root‘,password=‘123456‘)
???
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()
|
(2)基于公钥密钥上传下载:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import?paramiko
???
private_key?=?paramiko.RSAKey.from_private_key_file(‘/root/.ssh/id_rsa‘)
???
transport?=?paramiko.Transport((‘192.168.1.21‘,?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()
|
3、实例:通过transport实现远程执行命令和上传文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
?
import?paramiko
?
class?SSHConnection(object):
?
????def?__init__(self, host=‘192.168.1.21‘, port=22, username=‘root‘,pwd=‘123456‘):
????????self.host?=?host
????????self.port?=?port
????????self.username?=?username
????????self.pwd?=?pwd
????????self.__k?=?None
?
????def?run(self):
????????self.connect()
????????pass
????????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?cmd(self, command):
????????ssh?=?paramiko.SSHClient()
????????ssh._transport?=?self.__transport
????????# 执行命令
????????stdin, stdout, stderr?=?ssh.exec_command(command)
????????# 获取命令结果
????????result?=?stdout.read()
????????return?result
?
????def?upload(self,local_path, target_path):
????????# 连接,上传
????????sftp?=?paramiko.SFTPClient.from_transport(self.__transport)
????????# 将location.py 上传至服务器 /tmp/test.py
????????sftp.put(local_path, target_path)
?
ssh?=?SSHConnection()
ssh.connect()
r1?=?ssh.cmd(‘df‘)
print(r1.decode())
#ssh.upload(‘test.py‘, "/root/test.py")
ssh.upload(‘s13_par.py‘,?"/root/s7.py")
ssh.close()
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import paramiko import uuid class SSHConnection(object): def __init__(self, host=‘172.16.103.191‘, port=22, username=‘wupeiqi‘,pwd=‘123‘): self.host = host self.port = port self.username = username self.pwd = pwd self.__k = None def create_file(self): file_name = str(uuid.uuid4()) with open(file_name,‘w‘) as f: f.write(‘sb‘) return file_name def run(self): self.connect() self.upload(‘/home/wupeiqi/tttttttttttt.py‘) self.rename(‘/home/wupeiqi/tttttttttttt.py‘, ‘/home/wupeiqi/ooooooooo.py) 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,target_path): # 连接,上传 file_name = self.create_file() sftp = paramiko.SFTPClient.from_transport(self.__transport) # 将location.py 上传至服务器 /tmp/test.py sftp.put(file_name, target_path) def rename(self, old_path, new_path): ssh = paramiko.SSHClient() ssh._transport = self.__transport # 执行命令 cmd = "mv %s %s" % (old_path, new_path,) stdin, stdout, stderr = ssh.exec_command(cmd) # 获取命令结果 result = stdout.read() def cmd(self, command): ssh = paramiko.SSHClient() ssh._transport = self.__transport # 执行命令 stdin, stdout, stderr = ssh.exec_command(command) # 获取命令结果 result = stdout.read() return result ha = SSHConnection() ha.run()
1
2
3
4
5
6
|
# 对于更多限制命令,需要在系统中设置
/etc/sudoers
???
Defaults??? requiretty
Defaults:cmdb??? !requiretty
?Demo
|
堡垒机执行流程:
- 管理员为用户在服务器上创建账号(将公钥放置服务器,或者使用用户名密码)
- 用户登陆堡垒机,输入堡垒机用户名密码,现实当前用户管理的服务器列表
- 用户选择服务器,并自动登陆
- 执行操作并同时将用户操作记录
注:配置.brashrc实现ssh登陆后自动执行脚本,如:/usr/bin/python /home/wupeiqi/menu.py
实现过程(前戏)
# 利用sys.stdin,肆意妄为执行操作
# 用户在终端输入内容,并将内容发送至远程服务器
# 远程服务器执行命令,并将结果返回
# 用户终端显示内容
版本一:能连上远程服务器在终端任意输入命令,但无法做到tab键补全命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | import?paramiko import?sys import?os import?socket import?select import?getpass from?paramiko.py3compat?import?u ?? tran?=?paramiko.Transport((‘192.168.1.21‘,?22,)) tran.start_client() tran.auth_password(‘root‘,?‘123456‘) ?? # 打开一个通道 chan?=?tran.open_session() # 获取一个终端 chan.get_pty() # 激活器 chan.invoke_shell() ?? while?True: ????# 监视用户输入和服务器返回数据 ????# sys.stdin 处理用户输入 ????# chan 是之前创建的通道,用于接收服务器返回信息 ????readable, writeable, error?=?select.select([chan, sys.stdin, ],[],[],1) ????if?chan?in?readable: ????????try: ????????????x?=?u(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?readable: ????????inp?=?sys.stdin.readline() ????????chan.sendall(inp) ?? chan.close() tran.close() |
版本二:在版本一上增加了命令补全功能和命令记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | import?paramiko import?sys import?os import?socket import?select import?getpass import?termios import?tty from?paramiko.py3compat?import?u ?? tran?=?paramiko.Transport((‘192.168.1.21‘,?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设置新属性 ????# 默认当前tty设备属性: ????#?? 输入一行回车,执行 ????#?? CTRL+C 进程退出,遇到特殊字符,特殊处理。 ?? ????# 这是为原始模式,不认识所有特殊符号 ????# 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器 ????tty.setraw(sys.stdin.fileno()) ????chan.settimeout(0.0) ?? ????while?True: ????????# 监视 用户输入 和 远程服务器返回数据(socket) ????????# 阻塞,直到句柄可读 ????????r, w, e?=?select.select([chan, sys.stdin], [], [],?1) ????????if?chan?in?r: ????????????try: ????????????????x?=?u(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 ????????????chan.send(x) ?? finally: ????# 重新设置终端属性 ????termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) ?? ?? chan.close() tran.close() |
版本三:windows、linux通用版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | import?paramiko import?sys import?os import?socket import?getpass ? from?paramiko.py3compat?import?u ? # windows does not have termios... try: ????import?termios ????import?tty ????has_termios?=?True except?ImportError: ????has_termios?=?False ? ? def?interactive_shell(chan): ????if?has_termios: ????????posix_shell(chan) ????else: ????????windows_shell(chan) ? ? def?posix_shell(chan): ????import?select ? ????oldtty?=?termios.tcgetattr(sys.stdin) ????try: ????????tty.setraw(sys.stdin.fileno()) ????????tty.setcbreak(sys.stdin.fileno()) ????????chan.settimeout(0.0) ????????log?=?open(‘handle.log‘,?‘a+‘, encoding=‘utf-8‘) ????????flag?=?False ????????temp_list?=?[] ????????while?True: ????????????r, w, e?=?select.select([chan, sys.stdin], [], []) ????????????if?chan?in?r: ????????????????try: ????????????????????x?=?u(chan.recv(1024)) ????????????????????if?len(x)?==?0: ????????????????????????sys.stdout.write(‘\r\n*** EOF\r\n‘) ????????????????????????break ????????????????????if?flag: ????????????????????????if?x.startswith(‘\r\n‘): ????????????????????????????pass ????????????????????????else: ????????????????????????????temp_list.append(x) ????????????????????????flag?=?False ????????????????????sys.stdout.write(x) ????????????????????sys.stdout.flush() ????????????????except?socket.timeout: ????????????????????pass ????????????if?sys.stdin?in?r: ????????????????x?=?sys.stdin.read(1) ????????????????import?json ? ????????????????if?len(x)?==?0: ????????????????????break ? ????????????????if?x?==?‘\t‘: ????????????????????flag?=?True ????????????????else: ????????????????????temp_list.append(x) ????????????????if?x?==?‘\r‘: ????????????????????log.write(‘‘.join(temp_list)) ????????????????????log.flush() ????????????????????temp_list.clear() ????????????????chan.send(x) ? ????finally: ????????termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) ? ? 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 ? ? def?run(): ????default_username?=?getpass.getuser() ????username?=?input(‘Username [%s]: ‘?%?default_username) ????if?len(username)?==?0: ????????username?=?default_username ? ? ????hostname?=?input(‘Hostname: ‘) ????if?len(hostname)?==?0: ????????print(‘*** Hostname required.‘) ????????sys.exit(1) ? ????tran?=?paramiko.Transport((hostname,?22,)) ????tran.start_client() ? ????default_auth?=?"p" ????auth?=?input(‘Auth by (p)assword or (r)sa 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?=?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) ????????tran.auth_publickey(username, key) ????else: ????????pw?=?getpass.getpass(‘Password for %s@%s: ‘?%?(username, hostname)) ????????tran.auth_password(username, pw) ? ????# 打开一个通道 ????chan?=?tran.open_session() ????# 获取一个终端 ????chan.get_pty() ????# 激活器 ????chan.invoke_shell() ? ????interactive_shell(chan) ? ????chan.close() ????tran.close() ? ? if?__name__?==?‘__main__‘: ????run() |
更多参见:paramoko源码 https://github.com/paramiko/paramiko
paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实。其实它的底层是对ssh的上层代码的一个封装
一、下载安装
1
2
3
|
#pycrypto,由于 paramiko 模块内部依赖pycrypto,所以先下载安装pycrypto
tomcat@node:~$ pip install pycrypto
tomcat@node:~$ pip install paramiko
|
二、模块使用
1、SSHClient?用于连接远程服务器并执行基本命令
(1)基于用户名密码连接两种方式:
-->第一种
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import?paramiko
????
# 创建SSH对象
ssh?=?paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname=‘192.168.1.21‘, port=22, username=‘root‘, password=‘123456‘)
????
# 执行命令
stdin, stdout, stderr?=?ssh.exec_command(‘ls‘)
# 获取命令结果
result?=?stdout.read()
????
# 关闭连接
ssh.close()
|
-->二种:SSHClient 封装 Transport
1
2
3
4
5
6
7
8
9
10
11
12
|
import?paramiko
?
transport?=?paramiko.Transport((‘192.168.1.21‘,?22))
transport.connect(username=‘root‘, password=‘123456‘)
?
ssh?=?paramiko.SSHClient()
ssh._transport?=?transport
?
stdin, stdout, stderr?=?ssh.exec_command(‘df‘)
print?stdout.read()
?
transport.close()
|
(2)基于公钥密钥连接的两种方式:
-->第一种
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import?paramiko
???
private_key?=?paramiko.RSAKey.from_private_key_file(‘/root/.ssh/id_rsa‘)
???
# 创建SSH对象
ssh?=?paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname=‘192.168.1.21‘, port=22, username=‘root‘, key=private_key)
???
# 执行命令
stdin, stdout, stderr?=?ssh.exec_command(‘df‘)
# 获取命令结果
result?=?stdout.read()
???
# 关闭连接
ssh.close()
|
-->第二种:SSHClient 封装 Transport
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import?paramiko
?
private_key?=?paramiko.RSAKey.from_private_key_file(‘/root/.ssh/id_rsa‘)
?
transport?=?paramiko.Transport((‘192.168.1.21‘,?22))
transport.connect(username=‘root‘, pkey=private_key)
?
ssh?=?paramiko.SSHClient()
ssh._transport?=?transport
?
stdin, stdout, stderr?=?ssh.exec_command(‘df‘)
?
transport.close()
|
2、SFTPClient用于连接远程服务器并执行上传下载
(1)基于用户名密码上传下载:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import?paramiko
???
transport?=?paramiko.Transport((‘192.168.1.21‘,22))
transport.connect(username=‘root‘,password=‘123456‘)
???
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()
|
(2)基于公钥密钥上传下载:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import?paramiko
???
private_key?=?paramiko.RSAKey.from_private_key_file(‘/root/.ssh/id_rsa‘)
???
transport?=?paramiko.Transport((‘192.168.1.21‘,?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()
|
3、实例:通过transport实现远程执行命令和上传文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
?
import?paramiko
?
class?SSHConnection(object):
?
????def?__init__(self, host=‘192.168.1.21‘, port=22, username=‘root‘,pwd=‘123456‘):
????????self.host?=?host
????????self.port?=?port
????????self.username?=?username
????????self.pwd?=?pwd
????????self.__k?=?None
?
????def?run(self):
????????self.connect()
????????pass
????????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?cmd(self, command):
????????ssh?=?paramiko.SSHClient()
????????ssh._transport?=?self.__transport
????????# 执行命令
????????stdin, stdout, stderr?=?ssh.exec_command(command)
????????# 获取命令结果
????????result?=?stdout.read()
????????return?result
?
????def?upload(self,local_path, target_path):
????????# 连接,上传
????????sftp?=?paramiko.SFTPClient.from_transport(self.__transport)
????????# 将location.py 上传至服务器 /tmp/test.py
????????sftp.put(local_path, target_path)
?
ssh?=?SSHConnection()
ssh.connect()
r1?=?ssh.cmd(‘df‘)
print(r1.decode())
#ssh.upload(‘test.py‘, "/root/test.py")
ssh.upload(‘s13_par.py‘,?"/root/s7.py")
ssh.close()
|
#!/usr/bin/env python # -*- coding:utf-8 -*- import paramiko import uuid class SSHConnection(object): def __init__(self, host=‘172.16.103.191‘, port=22, username=‘wupeiqi‘,pwd=‘123‘): self.host = host self.port = port self.username = username self.pwd = pwd self.__k = None def create_file(self): file_name = str(uuid.uuid4()) with open(file_name,‘w‘) as f: f.write(‘sb‘) return file_name def run(self): self.connect() self.upload(‘/home/wupeiqi/tttttttttttt.py‘) self.rename(‘/home/wupeiqi/tttttttttttt.py‘, ‘/home/wupeiqi/ooooooooo.py) 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,target_path): # 连接,上传 file_name = self.create_file() sftp = paramiko.SFTPClient.from_transport(self.__transport) # 将location.py 上传至服务器 /tmp/test.py sftp.put(file_name, target_path) def rename(self, old_path, new_path): ssh = paramiko.SSHClient() ssh._transport = self.__transport # 执行命令 cmd = "mv %s %s" % (old_path, new_path,) stdin, stdout, stderr = ssh.exec_command(cmd) # 获取命令结果 result = stdout.read() def cmd(self, command): ssh = paramiko.SSHClient() ssh._transport = self.__transport # 执行命令 stdin, stdout, stderr = ssh.exec_command(command) # 获取命令结果 result = stdout.read() return result ha = SSHConnection() ha.run()
1
2
3
4
5
6
|
# 对于更多限制命令,需要在系统中设置
/etc/sudoers
???
Defaults??? requiretty
Defaults:cmdb??? !requiretty
?Demo
|
堡垒机执行流程:
- 管理员为用户在服务器上创建账号(将公钥放置服务器,或者使用用户名密码)
- 用户登陆堡垒机,输入堡垒机用户名密码,现实当前用户管理的服务器列表
- 用户选择服务器,并自动登陆
- 执行操作并同时将用户操作记录
注:配置.brashrc实现ssh登陆后自动执行脚本,如:/usr/bin/python /home/wupeiqi/menu.py
实现过程(前戏)
# 利用sys.stdin,肆意妄为执行操作
# 用户在终端输入内容,并将内容发送至远程服务器
# 远程服务器执行命令,并将结果返回
# 用户终端显示内容
版本一:能连上远程服务器在终端任意输入命令,但无法做到tab键补全命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | import?paramiko import?sys import?os import?socket import?select import?getpass from?paramiko.py3compat?import?u ?? tran?=?paramiko.Transport((‘192.168.1.21‘,?22,)) tran.start_client() tran.auth_password(‘root‘,?‘123456‘) ?? # 打开一个通道 chan?=?tran.open_session() # 获取一个终端 chan.get_pty() # 激活器 chan.invoke_shell() ?? while?True: ????# 监视用户输入和服务器返回数据 ????# sys.stdin 处理用户输入 ????# chan 是之前创建的通道,用于接收服务器返回信息 ????readable, writeable, error?=?select.select([chan, sys.stdin, ],[],[],1) ????if?chan?in?readable: ????????try: ????????????x?=?u(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?readable: ????????inp?=?sys.stdin.readline() ????????chan.sendall(inp) ?? chan.close() tran.close() |
版本二:在版本一上增加了命令补全功能和命令记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | import?paramiko import?sys import?os import?socket import?select import?getpass import?termios import?tty from?paramiko.py3compat?import?u ?? tran?=?paramiko.Transport((‘192.168.1.21‘,?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设置新属性 ????# 默认当前tty设备属性: ????#?? 输入一行回车,执行 ????#?? CTRL+C 进程退出,遇到特殊字符,特殊处理。 ?? ????# 这是为原始模式,不认识所有特殊符号 ????# 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器 ????tty.setraw(sys.stdin.fileno()) ????chan.settimeout(0.0) ?? ????while?True: ????????# 监视 用户输入 和 远程服务器返回数据(socket) ????????# 阻塞,直到句柄可读 ????????r, w, e?=?select.select([chan, sys.stdin], [], [],?1) ????????if?chan?in?r: ????????????try: ????????????????x?=?u(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 ????????????chan.send(x) ?? finally: ????# 重新设置终端属性 ????termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) ?? ?? chan.close() tran.close() |
版本三:windows、linux通用版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | import?paramiko import?sys import?os import?socket import?getpass ? from?paramiko.py3compat?import?u ? # windows does not have termios... try: ????import?termios ????import?tty ????has_termios?=?True except?ImportError: ????has_termios?=?False ? ? def?interactive_shell(chan): ????if?has_termios: ????????posix_shell(chan) ????else: ????????windows_shell(chan) ? ? def?posix_shell(chan): ????import?select ? ????oldtty?=?termios.tcgetattr(sys.stdin) ????try: ????????tty.setraw(sys.stdin.fileno()) ????????tty.setcbreak(sys.stdin.fileno()) ????????chan.settimeout(0.0) ????????log?=?open(‘handle.log‘,?‘a+‘, encoding=‘utf-8‘) ????????flag?=?False ????????temp_list?=?[] ????????while?True: ????????????r, w, e?=?select.select([chan, sys.stdin], [], []) ????????????if?chan?in?r: ????????????????try: ????????????????????x?=?u(chan.recv(1024)) ????????????????????if?len(x)?==?0: ????????????????????????sys.stdout.write(‘\r\n*** EOF\r\n‘) ????????????????????????break ????????????????????if?flag: ????????????????????????if?x.startswith(‘\r\n‘): ????????????????????????????pass ????????????????????????else: ????????????????????????????temp_list.append(x) ????????????????????????flag?=?False ????????????????????sys.stdout.write(x) ????????????????????sys.stdout.flush() ????????????????except?socket.timeout: ????????????????????pass ????????????if?sys.stdin?in?r: ????????????????x?=?sys.stdin.read(1) ????????????????import?json ? ????????????????if?len(x)?==?0: ????????????????????break ? ????????????????if?x?==?‘\t‘: ????????????????????flag?=?True ????????????????else: ????????????????????temp_list.append(x) ????????????????if?x?==?‘\r‘: ????????????????????log.write(‘‘.join(temp_list)) ????????????????????log.flush() ????????????????????temp_list.clear() ????????????????chan.send(x) ? ????finally: ????????termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) ? ? 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 ? ? def?run(): ????default_username?=?getpass.getuser() ????username?=?input(‘Username [%s]: ‘?%?default_username) ????if?len(username)?==?0: ????????username?=?default_username ? ? ????hostname?=?input(‘Hostname: ‘) ????if?len(hostname)?==?0: ????????print(‘*** Hostname required.‘) ????????sys.exit(1) ? ????tran?=?paramiko.Transport((hostname,?22,)) ????tran.start_client() ? ????default_auth?=?"p" ????auth?=?input(‘Auth by (p)assword or (r)sa 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?=?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) ????????tran.auth_publickey(username, key) ????else: ????????pw?=?getpass.getpass(‘Password for %s@%s: ‘?%?(username, hostname)) ????????tran.auth_password(username, pw) ? ????# 打开一个通道 ????chan?=?tran.open_session() ????# 获取一个终端 ????chan.get_pty() ????# 激活器 ????chan.invoke_shell() ? ????interactive_shell(chan) ? ????chan.close() ????tran.close() ? ? if?__name__?==?‘__main__‘: ????run() |
更多参见:paramoko源码 https://github.com/paramiko/paramiko?
内容总结
以上是互联网集市为您收集整理的Python----Paramiko模块和堡垒机实战全部内容,希望文章能够帮你解决Python----Paramiko模块和堡垒机实战所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。