Paramiko
paramiko模块,基于SSH用于连接远程服务器并执行相关操作。
一、安装
pip3 install paramiko
二、使用
1. SSHClient
用于连接远程服务器并执行基本命令
基于用户名密码连接:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) import paramiko #创建ssh对象 ssh = paramiko.SSHClient() #允许连接不在Know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #连接服务器 ssh.connect(hostname='172.16.30.162',port=22,username='root',password='123456') #执行命令 stdin,stdout,stderr = ssh.exec_command('ls /tmp/') #获取执行结果 result = stdout.read() print(result.decode()) #返回的是bytes #关闭连接 ssh.close()
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) import paramiko transport = paramiko.Transport(('172.16.30.162',22)) transport.connect(username='root',password='123456') ssh = paramiko.SSHClient() ssh._transport = transport stdin,stdout,stderr = ssh.exec_command('df -Th') res = stdout.read() print(res.decode()) transport.close()
基于公钥密钥连接:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) import paramiko private_key = paramiko.RSAKey.from_private_key_file('/Users/daniel/.ssh/id_rsa') # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh.connect(hostname='172.16.30.162', port=22, username='root', pkey=private_key) # 执行命令 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = stdout.read() print(result.decode()) # 关闭连接 ssh.close()
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) import paramiko private_key = paramiko.RSAKey.from_private_key_file('/Users/daniel/.ssh/id_rsa') transport = paramiko.Transport(('172.16.30.162',22)) transport.connect(username='root',pkey=private_key) ssh = paramiko.SSHClient() ssh._transport = transport stdin,stdout,stderr = ssh.exec_command('df -Th') print(stdout.read().decode()) transport.close()
SFTPClient
用于连接远程服务器并执行上传下载
基于用户名密码 上传/下载
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) import paramiko transport = paramiko.Transport(('172.16.30.162',22)) transport.connect(username='root',password='123456') sftp = paramiko.SFTPClient.from_transport(transport) #上传本地文件/Users/daniel/test/zhoulibo.mp4 上传到服务器的 /tmp/zhoulibo.mp4 sftp.put('/Users/daniel/test/zhoulibo.mp4','/tmp/zhoulibo.mp4') #将远端/tmp/zhoulibo.mp4 下载到 本地 /Users/daniel/zhoulibo.mp4 sftp.get('/tmp/zhoulibo.mp4','/Users/daniel/zhoulibo.mp4') transport.close()
基于公钥/密钥的上传/下载:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) import paramiko private_key = paramiko.RSAKey.from_private_key_file('/Users/daniel/.ssh/id_rsa') transport = paramiko.Transport(('172.16.30.162',22)) transport.connect(username='root',pkey=private_key) sftp = paramiko.SFTPClient.from_transport(transport) #上传本地文件/Users/daniel/test/zhoulibo.mp4 上传到服务器的 /tmp/zhoulibo.mp4 sftp.put('/Users/daniel/test/zhoulibo.mp4','/tmp/zhoulibo.mp4') #将远端/tmp/zhoulibo.mp4 下载到 本地 /Users/daniel/zhoulibo.mp4 sftp.get('/tmp/zhoulibo.mp4','/Users/daniel/zhoulibo.mp4') transport.close()
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) import paramiko,uuid class SSHConnection: def __init__(self,host='172.16.30.162',port=22,username='root',pwd='123456'): self.host = host self.port = port self.username = username self.pwd = pwd self.__k = None def create_file(self): file_name = str(uuid.uuid4()) #生成一个'46cad739-5937-4312-9156-00753b272581'的文件名 uuid并转换成str with open(file_name,'w') as f: #打开文件,往里面写一个sb f.write('sb') return file_name def run(self): ''' 主方法 :return: ''' self.connect() self.upload('/tmp/test.py') #调用upload方法,上传到服务器的/tmp/test.py self.rename('/tmp/test.py','/tmp/sb.py') #改名为sb.py self.close() def connect(self): ''' 建立连接 :return: ''' transport = paramiko.Transport((self.host,self.port)) transport.connect(username=self.username,password=self.pwd) self.__transport = transport def close(self): ''' 关闭连接 :return: ''' self.__transport.close() def upload(self,target_path): ''' 连接,上传 :param target_path: :return: ''' file_name = self.create_file() sftp = paramiko.SFTPClient.from_transport(self.__transport) #上传本地文件 到服务器的 test.py sftp.put(file_name, target_path) def rename(self, old_path, new_path): ''' 改名, 把/tmp/test.py 改名为 sb.py :param old_path: :param new_path: :return: ''' ssh = paramiko.SSHClient() ssh._transport = self.__transport #执行命令 cmd = "mv %s %s" %(old_path,new_path) stdin,stdout,stderr = ssh.exec_command(cmd) res = stdout.read() def cmd(self,command): ''' 可以执行其他命令 :param command: :return: ''' self.connect() ssh = paramiko.SSHClient() ssh._transport = self.__transport #执行命令 stdin, stdout, stderr = ssh.exec_command(command) res = stdout.read() self.close() return res ha = SSHConnection() ha.run() res = ha.cmd('ls') print(res.decode())
# 对于更多限制命令,需要在系统中设置 /etc/sudoers Defaults requiretty Defaults:cmdb !requiretty
堡垒机
堡垒机执行流程:
- 管理员为用户在服务器上创建账号(将公钥放置服务器,或者使用用户名密码)
- 用户登陆堡垒机,输入堡垒机用户名密码,现实当前用户管理的服务器列表
- 用户选择服务器,并自动登陆
- 执行操作并同时将用户操作记录
PS:配置.brashrc实现ssh登陆后自动执行脚本,如:/usr/bin/python /home/daniel/menu.py
实现过程
1. 前奏
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) import paramiko import sys import os,socket,select,getpass transport = paramiko.Transport(('172.16.30.162',22)) transport.start_client() transport.auth_password('root','123456') #打开一个通道 channel = transport.open_session() #获取一个终端 channel.get_pty() #激活器 channel.invoke_shell() ######### # 利用sys.stdin,肆意妄为执行操作 # 用户在终端输入内容,并将内容发送至远程服务器 # 远程服务器执行命令,并将结果返回 # 用户终端显示内容 ######### channel.close() transport.close()
2. 肆意妄为(一)
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) import paramiko import sys import os,socket,select,getpass from paramiko.py3compat import u transport = paramiko.Transport(('172.16.30.162',22)) transport.start_client() transport.auth_password('root','123456') #打开一个通道 channel = transport.open_session() #获取一个终端 channel.get_pty() #激活器 channel.invoke_shell() while True: #监视用户输入和服务器的返回的数据 # sys.stdin处理用户输入 # channel 是之前创建的通道, 用户接受服务器返回的信息 readable, writeable, error = select.select([channel, sys.stdin,],[],[],1) if channel in readable: try: x = u(channel.recv(1024)) if len(x) == 0: print(' **** EOF ') break sys.stdout.write(x) sys.stdout.flush() except socket.timeout: pass if sys.stdin in readable: inp = sys.stdin.readline() channel.sendall(bytes(inp,encoding='utf-8')) channel.close() transport.close()
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) import paramiko import sys import os,socket,select,getpass from paramiko.py3compat import u default_username = getpass.getuser() #获取当前用户 username = input('Usersname[%s]:'%default_username).strip() #提示用户输入用户名 if len(username) == 0: #如果用户输入为空, 则用户名为默认当前系统用户名 username = default_username hostname = input('Hostname: ').strip() #提示输入主机名 if len(hostname) == 0: #如果为空,错误退出程序 print('*** Hostname required.') sys.exit(1) port = input('Port: [22] ').strip() #提示输入端口 if len(port) == 0: #如果为空, 端口为默认的22 port = 22 transport = paramiko.Transport((hostname,port)) transport.start_client() default_auth = "p" auth = input('Auth by (p)assword or (r)sa key [%s]' %default_auth).strip() #让用户选择是密码认证还是证书认证 if len(auth) == 0: auth = default_auth if auth == 'r': default_path = os.path.join(os.environ['HOME'],'.ssh','id_rsa') #拼接用户家目录/.ssh/id_rsa path = input('RSA key [%s]: '%default_path).strip() if len(path) == 0: path = default_path try: key = paramiko.RSAKey.from_private_key_file(path) #加载用户key except paramiko.PasswordRequiredException: password = getpass.getpass('RSA key password: ') key = paramiko.RSAKey.from_private_key_file(path,password) transport.auth_publickey(username,key) elif auth == 'p': password = getpass.getpass('Password for %s@%s '%(username, hostname)) try: transport.auth_password(username,password) except paramiko.ssh_exception.AuthenticationException: print('