移动api中关于tty到connect.py

pull/26/head
ibuler 2015-11-04 17:04:25 +08:00
parent c8c0061244
commit 618aed3278
2 changed files with 369 additions and 364 deletions

View File

@ -8,18 +8,33 @@ sys.setdefaultencoding('utf8')
import os import os
import re import re
import time import time
import datetime
import textwrap import textwrap
import getpass import getpass
import readline import readline
import django import django
from multiprocessing import Pool from multiprocessing import Pool
import paramiko
import struct, fcntl, signal, socket, select, fnmatch
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
if django.get_version() != '1.6': if django.get_version() != '1.6':
django.setup() django.setup()
from jumpserver.api import ServerError, User, Asset, Jtty, get_object from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object
from jumpserver.api import logger from jumpserver.api import logger, is_dir, Log, TtyLog
from jumpserver.settings import log_dir
try:
import termios
import tty
except ImportError:
print '\033[1;31m仅支持类Unix系统 Only unix like supported.\033[0m'
time.sleep(3)
sys.exit()
VIM_FLAG = False
VIM_COMMAND = ''
SSH_TTY = ''
login_user = get_object(User, username=getpass.getuser()) login_user = get_object(User, username=getpass.getuser())
@ -81,6 +96,358 @@ def verify_connect(user, option):
jtty.connect() jtty.connect()
def check_vim_status(command, ssh):
global SSH_TTY
print command
if command == '':
return True
else:
command_str= 'ps -ef |grep "%s" | grep "%s"|grep -v grep |wc -l' % (command,SSH_TTY)
print command_str
stdin, stdout, stderr = ssh.exec_command(command_str)
ps_num = stdout.read()
print ps_num
if int(ps_num) == 0:
return True
else:
return False
def deal_command(str_r, ssh):
"""
处理命令中特殊字符
"""
str_r = re.sub('\x07','',str_r) #删除响铃
patch_char = re.compile('\x08\x1b\[C') #删除方向左右一起的按键
while patch_char.search(str_r):
str_r = patch_char.sub('', str_r.rstrip())
result_command = '' #最后的结果
pattern_str = '' #模式中间中的字符串
backspace_num = 0 #光标移动的个数
reach_backspace_flag = False #没有检测到光标键则为true
end_flag = False
while str_r:
tmp = re.match(r'\w', str_r)
if tmp:
if reach_backspace_flag:
pattern_str += str(tmp.group(0))
str_r = str_r[1:]
continue
else:
result_command += str(tmp.group(0))
str_r = str_r[1:]
continue
tmp = re.match(r'\x1b\[K[\x08]*', str_r)
if tmp:
if backspace_num > 0:
if backspace_num > len(result_command) :
result_command += pattern_str
result_command = result_command[0:-backspace_num]
else:
result_command = result_command[0:-backspace_num]
result_command += pattern_str
del_len = len(str(tmp.group(0)))-3
if del_len > 0:
result_command = result_command[0:-del_len]
reach_backspace_flag = False
backspace_num =0
pattern_str=''
str_r = str_r[len(str(tmp.group(0))):]
continue
if re.match(r'\x08', str_r):
backspace_num += 1
reach_backspace_flag = True
str_r = str_r[1:]
if len(str_r) == 0:
end_flag = True
continue
if reach_backspace_flag :
pattern_str += str_r[0]
else :
result_command += str_r[0]
str_r = str_r[1:]
if backspace_num > 0 and not end_flag:
result_command = result_command[:-backspace_num]
result_command += pattern_str
control_char = re.compile(r"""
\x1b[ #%()*+\-.\/]. |
\r | #匹配 回车符(CR)
(?:\x1b\[|\x9b) [ -?]* [@-~] | #匹配 控制顺序描述符(CSI)... Cmd
(?:\x1b\]|\x9d) .*? (?:\x1b\\|[\a\x9c]) | \x07 | #匹配 操作系统指令(OSC)...终止符或振铃符(ST|BEL)
(?:\x1b[P^_]|[\x90\x9e\x9f]) .*? (?:\x1b\\|\x9c) | #匹配 设备控制串或私讯或应用程序命令(DCS|PM|APC)...终止符(ST)
\x1b. #匹配 转义过后的字符
[\x80-\x9f] #匹配 所有控制字符
""", re.X)
result_command = control_char.sub('', result_command.strip())
global VIM_FLAG
global VIM_COMMAND
if not VIM_FLAG:
if result_command.startswith('vim') or result_command.startswith('vi') :
VIM_FLAG = True
VIM_COMMAND = result_command
return result_command.decode('utf8',"ignore")
else:
if check_vim_status(VIM_COMMAND, ssh):
VIM_FLAG = False
VIM_COMMAND=''
return result_command.decode('utf8',"ignore")
else:
return ''
def remove_control_char(str_r):
"""
处理日志特殊字符
"""
control_char = re.compile(r"""
\x1b[ #%()*+\-.\/]. |
\r | #匹配 回车符(CR)
(?:\x1b\[|\x9b) [ -?]* [@-~] | #匹配 控制顺序描述符(CSI)... Cmd
(?:\x1b\]|\x9d) .*? (?:\x1b\\|[\a\x9c]) | \x07 | #匹配 操作系统指令(OSC)...终止符或振铃符(ST|BEL)
(?:\x1b[P^_]|[\x90\x9e\x9f]) .*? (?:\x1b\\|\x9c) | #匹配 设备控制串或私讯或应用程序命令(DCS|PM|APC)...终止符(ST)
\x1b. #匹配 转义过后的字符
[\x80-\x9f] #匹配 所有控制字符
""", re.X)
backspace = re.compile(r"[^\b][\b]")
line_filtered = control_char.sub('', str_r.rstrip())
while backspace.search(line_filtered):
line_filtered = backspace.sub('', line_filtered)
return line_filtered
def newline_code_in(strings):
for i in ['\r', '\r\n', '\n']:
if i in strings:
#print "new line"
return True
return False
class Jtty(object):
"""
A virtual tty class
一个虚拟终端类实现连接ssh和记录日志
"""
def __init__(self, username, ip):
self.chan = None
self.username = username
self.ip = ip
# self.user = user
# self.asset = asset
@staticmethod
def get_win_size():
"""
This function use to get the size of the windows!
获得terminal窗口大小
"""
if 'TIOCGWINSZ' in dir(termios):
TIOCGWINSZ = termios.TIOCGWINSZ
else:
TIOCGWINSZ = 1074295912L
s = struct.pack('HHHH', 0, 0, 0, 0)
x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s)
return struct.unpack('HHHH', x)[0:2]
def set_win_size(self, sig, data):
"""
This function use to set the window size of the terminal!
设置terminal窗口大小
"""
try:
win_size = self.get_win_size()
self.chan.resize_pty(height=win_size[0], width=win_size[1])
except Exception:
pass
def log_record(self):
"""
Logging user command and output.
记录用户的日志
"""
tty_log_dir = os.path.join(log_dir, 'tty')
timestamp_start = int(time.time())
date_start = time.strftime('%Y%m%d', time.localtime(timestamp_start))
time_start = time.strftime('%H%M%S', time.localtime(timestamp_start))
today_connect_log_dir = os.path.join(tty_log_dir, date_start)
log_file_path = os.path.join(today_connect_log_dir, '%s_%s_%s' % (self.username, self.ip, time_start))
pid = os.getpid()
pts = os.popen("ps axu | grep %s | grep -v grep | awk '{ print $7 }'" % pid).read().strip()
ip_list = os.popen("who | grep %s | awk '{ print $5 }'" % pts).read().strip('()\n')
try:
is_dir(today_connect_log_dir)
except OSError:
raise ServerError('Create %s failed, Please modify %s permission.' % (today_connect_log_dir, tty_log_dir))
try:
# log_file_f = open('/opt/jumpserver/logs/tty/20151102/a_b_191034.log', 'a')
log_file_f = open(log_file_path + '.log', 'a')
log_time_f = open(log_file_path + '.time', 'a')
except IOError:
raise ServerError('Create logfile failed, Please modify %s permission.' % today_connect_log_dir)
log = Log(user=self.username, host=self.ip, remote_ip=ip_list,
log_path=log_file_path, start_time=datetime.datetime.now(), pid=pid)
log_file_f.write('Start time is %s\n' % datetime.datetime.now())
log.save()
return log_file_f, log_time_f, ip_list, log
def posix_shell(self,ssh):
"""
Use paramiko channel connect server interactive.
使用paramiko模块的channel连接后端进入交互式
"""
log_file_f, log_time_f, ip_list, log = self.log_record()
old_tty = termios.tcgetattr(sys.stdin)
pre_timestamp = time.time()
input_r = ''
input_mode = False
try:
tty.setraw(sys.stdin.fileno())
tty.setcbreak(sys.stdin.fileno())
self.chan.settimeout(0.0)
while True:
try:
r, w, e = select.select([self.chan, sys.stdin], [], [])
except Exception:
pass
if self.chan in r:
try:
x = self.chan.recv(1024)
if len(x) == 0:
break
sys.stdout.write(x)
sys.stdout.flush()
log_file_f.write(x)
now_timestamp = time.time()
log_time_f.write('%s %s\n' % (round(now_timestamp-pre_timestamp, 4), len(x)))
pre_timestamp = now_timestamp
log_file_f.flush()
log_time_f.flush()
if input_mode and not newline_code_in(x):
input_r += x
except socket.timeout:
pass
if sys.stdin in r:
x = os.read(sys.stdin.fileno(), 1)
if not input_mode:
input_mode = True
if str(x) in ['\r', '\n', '\r\n']:
input_r = deal_command(input_r,ssh)
TtyLog(log=log, datetime=datetime.datetime.now(), cmd=input_r).save()
input_r = ''
input_mode = False
if len(x) == 0:
break
self.chan.send(x)
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
log_file_f.write('End time is %s' % datetime.datetime.now())
log_file_f.close()
log.is_finished = True
log.end_time = datetime.datetime.now()
log.save()
def get_connect_item(self):
"""
get args for connect: ip, port, username, passwd
获取连接需要的参数也就是服务ip, 端口, 用户账号和密码
"""
# if not self.asset.is_active:
# raise ServerError('该主机被禁用 Host %s is not active.' % self.ip)
#
# if not self.user.is_active:
# raise ServerError('该用户被禁用 User %s is not active.' % self.username)
# password = CRYPTOR.decrypt(self.])
# return self.username, password, self.ip, int(self.asset.port)
return 'root', 'redhat', '127.0.0.1', 22
def get_connection(self):
"""
Get the ssh connection for reuse
获取连接套接字
"""
username, password, ip, port = self.get_connect_item()
logger.debug("username: %s, password: %s, ip: %s, port: %s" % (username, password, ip, port))
# 发起ssh连接请求 Make a ssh connection
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(ip, port=port, username=username, password=password)
except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException:
raise ServerError('认证错误 Authentication Error.')
except socket.error:
raise ServerError('端口可能不对 Connect SSH Socket Port Error, Please Correct it.')
else:
return ssh
def connect(self):
"""
Connect server.
连接服务器
"""
ps1 = "PS1='[\u@%s \W]\$ '\n" % self.ip
login_msg = "clear;echo -e '\\033[32mLogin %s done. Enjoy it.\\033[0m'\n" % self.ip
# 发起ssh连接请求 Make a ssh connection
ssh = self.get_connection()
# 获取连接的隧道并设置窗口大小 Make a channel and set windows size
global channel
win_size = self.get_win_size()
self.chan = channel = ssh.invoke_shell(height=win_size[0], width=win_size[1])
try:
signal.signal(signal.SIGWINCH, self.set_win_size)
except:
pass
# 设置PS1并提示 Set PS1 and msg it
#channel.send(ps1)
#channel.send(login_msg)
channel.send('echo ${SSH_TTY}\n')
global SSH_TTY
while not channel.recv_ready():
time.sleep(1)
tmp = channel.recv(1024)
#print 'ok'+tmp+'ok'
SSH_TTY = re.search(r'(?<=/dev/).*', tmp).group().strip()
channel.send('clear\n')
# Make ssh interactive tunnel
self.posix_shell(ssh)
# Shutdown channel socket
channel.close()
ssh.close()
def execute(self, cmd):
"""
execute cmd on the asset
执行命令
"""
pass
def print_prompt(): def print_prompt():
""" """
Print prompt Print prompt

View File

@ -8,8 +8,6 @@ import hashlib
import datetime import datetime
import random import random
import subprocess import subprocess
import paramiko
import struct, fcntl, signal, socket, select, fnmatch
from settings import * from settings import *
from django.core.paginator import Paginator, EmptyPage, InvalidPage from django.core.paginator import Paginator, EmptyPage, InvalidPage
@ -25,17 +23,7 @@ from django.shortcuts import render_to_response
from django.core.mail import send_mail from django.core.mail import send_mail
import json import json
import logging import logging
VIM_FLAG = False
VIM_COMMAND = ''
SSH_TTY = ''
try:
import termios
import tty
except ImportError:
print '\033[1;31m仅支持类Unix系统 Only unix like supported.\033[0m'
time.sleep(3)
sys.exit()
def set_log(level): def set_log(level):
@ -97,356 +85,6 @@ def pages(post_objects, request):
# 所有对象, 分页器, 本页对象, 所有页码, 本页页码,是否显示第一页,是否显示最后一页 # 所有对象, 分页器, 本页对象, 所有页码, 本页页码,是否显示第一页,是否显示最后一页
return post_objects, paginator, page_objects, page_range, current_page, show_first, show_end return post_objects, paginator, page_objects, page_range, current_page, show_first, show_end
def check_vim_status(command, ssh):
global SSH_TTY
print command
if command == '':
return True
else:
command_str= 'ps -ef |grep "%s" | grep "%s"|grep -v grep |wc -l' % (command,SSH_TTY)
print command_str
stdin, stdout, stderr = ssh.exec_command(command_str)
ps_num = stdout.read()
print ps_num
if int(ps_num) == 0:
return True
else:
return False
def deal_command(str_r, ssh):
"""
处理命令中特殊字符
"""
str_r = re.sub('\x07','',str_r) #删除响铃
patch_char = re.compile('\x08\x1b\[C') #删除方向左右一起的按键
while patch_char.search(str_r):
str_r = patch_char.sub('', str_r.rstrip())
result_command = '' #最后的结果
pattern_str = '' #模式中间中的字符串
backspace_num = 0 #光标移动的个数
reach_backspace_flag = False #没有检测到光标键则为true
end_flag = False
while str_r:
tmp = re.match(r'\w', str_r)
if tmp:
if reach_backspace_flag:
pattern_str += str(tmp.group(0))
str_r = str_r[1:]
continue
else:
result_command += str(tmp.group(0))
str_r = str_r[1:]
continue
tmp = re.match(r'\x1b\[K[\x08]*', str_r)
if tmp:
if backspace_num > 0:
if backspace_num > len(result_command) :
result_command += pattern_str
result_command = result_command[0:-backspace_num]
else:
result_command = result_command[0:-backspace_num]
result_command += pattern_str
del_len = len(str(tmp.group(0)))-3
if del_len > 0:
result_command = result_command[0:-del_len]
reach_backspace_flag = False
backspace_num =0
pattern_str=''
str_r = str_r[len(str(tmp.group(0))):]
continue
if re.match(r'\x08', str_r):
backspace_num += 1
reach_backspace_flag = True
str_r = str_r[1:]
if len(str_r) == 0:
end_flag = True
continue
if reach_backspace_flag :
pattern_str += str_r[0]
else :
result_command += str_r[0]
str_r = str_r[1:]
if backspace_num > 0 and not end_flag:
result_command = result_command[:-backspace_num]
result_command += pattern_str
control_char = re.compile(r"""
\x1b[ #%()*+\-.\/]. |
\r | #匹配 回车符(CR)
(?:\x1b\[|\x9b) [ -?]* [@-~] | #匹配 控制顺序描述符(CSI)... Cmd
(?:\x1b\]|\x9d) .*? (?:\x1b\\|[\a\x9c]) | \x07 | #匹配 操作系统指令(OSC)...终止符或振铃符(ST|BEL)
(?:\x1b[P^_]|[\x90\x9e\x9f]) .*? (?:\x1b\\|\x9c) | #匹配 设备控制串或私讯或应用程序命令(DCS|PM|APC)...终止符(ST)
\x1b. #匹配 转义过后的字符
[\x80-\x9f] #匹配 所有控制字符
""", re.X)
result_command = control_char.sub('', result_command.strip())
global VIM_FLAG
global VIM_COMMAND
if not VIM_FLAG:
if result_command.startswith('vim') or result_command.startswith('vi') :
VIM_FLAG = True
VIM_COMMAND = result_command
return result_command.decode('utf8',"ignore")
else:
if check_vim_status(VIM_COMMAND, ssh):
VIM_FLAG = False
VIM_COMMAND=''
return result_command.decode('utf8',"ignore")
else:
return ''
def remove_control_char(str_r):
"""
处理日志特殊字符
"""
control_char = re.compile(r"""
\x1b[ #%()*+\-.\/]. |
\r | #匹配 回车符(CR)
(?:\x1b\[|\x9b) [ -?]* [@-~] | #匹配 控制顺序描述符(CSI)... Cmd
(?:\x1b\]|\x9d) .*? (?:\x1b\\|[\a\x9c]) | \x07 | #匹配 操作系统指令(OSC)...终止符或振铃符(ST|BEL)
(?:\x1b[P^_]|[\x90\x9e\x9f]) .*? (?:\x1b\\|\x9c) | #匹配 设备控制串或私讯或应用程序命令(DCS|PM|APC)...终止符(ST)
\x1b. #匹配 转义过后的字符
[\x80-\x9f] #匹配 所有控制字符
""", re.X)
backspace = re.compile(r"[^\b][\b]")
line_filtered = control_char.sub('', str_r.rstrip())
while backspace.search(line_filtered):
line_filtered = backspace.sub('', line_filtered)
return line_filtered
def newline_code_in(strings):
for i in ['\r', '\r\n', '\n']:
if i in strings:
#print "new line"
return True
return False
class Jtty(object):
"""
A virtual tty class
一个虚拟终端类实现连接ssh和记录日志
"""
def __init__(self, username, ip):
self.chan = None
self.username = username
self.ip = ip
# self.user = user
# self.asset = asset
@staticmethod
def get_win_size():
"""
This function use to get the size of the windows!
获得terminal窗口大小
"""
if 'TIOCGWINSZ' in dir(termios):
TIOCGWINSZ = termios.TIOCGWINSZ
else:
TIOCGWINSZ = 1074295912L
s = struct.pack('HHHH', 0, 0, 0, 0)
x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s)
return struct.unpack('HHHH', x)[0:2]
def set_win_size(self, sig, data):
"""
This function use to set the window size of the terminal!
设置terminal窗口大小
"""
try:
win_size = self.get_win_size()
self.chan.resize_pty(height=win_size[0], width=win_size[1])
except Exception:
pass
def log_record(self):
"""
Logging user command and output.
记录用户的日志
"""
tty_log_dir = os.path.join(log_dir, 'tty')
timestamp_start = int(time.time())
date_start = time.strftime('%Y%m%d', time.localtime(timestamp_start))
time_start = time.strftime('%H%M%S', time.localtime(timestamp_start))
today_connect_log_dir = os.path.join(tty_log_dir, date_start)
log_file_path = os.path.join(today_connect_log_dir, '%s_%s_%s' % (self.username, self.ip, time_start))
pid = os.getpid()
pts = os.popen("ps axu | grep %s | grep -v grep | awk '{ print $7 }'" % pid).read().strip()
ip_list = os.popen("who | grep %s | awk '{ print $5 }'" % pts).read().strip('()\n')
try:
is_dir(today_connect_log_dir)
except OSError:
raise ServerError('Create %s failed, Please modify %s permission.' % (today_connect_log_dir, tty_log_dir))
try:
# log_file_f = open('/opt/jumpserver/logs/tty/20151102/a_b_191034.log', 'a')
log_file_f = open(log_file_path + '.log', 'a')
log_time_f = open(log_file_path + '.time', 'a')
except IOError:
raise ServerError('Create logfile failed, Please modify %s permission.' % today_connect_log_dir)
log = Log(user=self.username, host=self.ip, remote_ip=ip_list,
log_path=log_file_path, start_time=datetime.datetime.now(), pid=pid)
log_file_f.write('Start time is %s\n' % datetime.datetime.now())
log.save()
return log_file_f, log_time_f, ip_list, log
def posix_shell(self,ssh):
"""
Use paramiko channel connect server interactive.
使用paramiko模块的channel连接后端进入交互式
"""
log_file_f, log_time_f, ip_list, log = self.log_record()
old_tty = termios.tcgetattr(sys.stdin)
pre_timestamp = time.time()
input_r = ''
input_mode = False
try:
tty.setraw(sys.stdin.fileno())
tty.setcbreak(sys.stdin.fileno())
self.chan.settimeout(0.0)
while True:
try:
r, w, e = select.select([self.chan, sys.stdin], [], [])
except Exception:
pass
if self.chan in r:
try:
x = self.chan.recv(1024)
if len(x) == 0:
break
sys.stdout.write(x)
sys.stdout.flush()
log_file_f.write(x)
now_timestamp = time.time()
log_time_f.write('%s %s\n' % (round(now_timestamp-pre_timestamp, 4), len(x)))
pre_timestamp = now_timestamp
log_file_f.flush()
log_time_f.flush()
if input_mode and not newline_code_in(x):
input_r += x
except socket.timeout:
pass
if sys.stdin in r:
x = os.read(sys.stdin.fileno(), 1)
if not input_mode:
input_mode = True
if str(x) in ['\r', '\n', '\r\n']:
input_r = deal_command(input_r,ssh)
TtyLog(log=log, datetime=datetime.datetime.now(), cmd=input_r).save()
input_r = ''
input_mode = False
if len(x) == 0:
break
self.chan.send(x)
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
log_file_f.write('End time is %s' % datetime.datetime.now())
log_file_f.close()
log.is_finished = True
log.end_time = datetime.datetime.now()
log.save()
def get_connect_item(self):
"""
get args for connect: ip, port, username, passwd
获取连接需要的参数也就是服务ip, 端口, 用户账号和密码
"""
# if not self.asset.is_active:
# raise ServerError('该主机被禁用 Host %s is not active.' % self.ip)
#
# if not self.user.is_active:
# raise ServerError('该用户被禁用 User %s is not active.' % self.username)
# password = CRYPTOR.decrypt(self.])
# return self.username, password, self.ip, int(self.asset.port)
return 'root', 'redhat', '127.0.0.1', 22
def get_connection(self):
"""
Get the ssh connection for reuse
获取连接套接字
"""
username, password, ip, port = self.get_connect_item()
logger.debug("username: %s, password: %s, ip: %s, port: %s" % (username, password, ip, port))
# 发起ssh连接请求 Make a ssh connection
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(ip, port=port, username=username, password=password)
except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException:
raise ServerError('认证错误 Authentication Error.')
except socket.error:
raise ServerError('端口可能不对 Connect SSH Socket Port Error, Please Correct it.')
else:
return ssh
def connect(self):
"""
Connect server.
连接服务器
"""
ps1 = "PS1='[\u@%s \W]\$ '\n" % self.ip
login_msg = "clear;echo -e '\\033[32mLogin %s done. Enjoy it.\\033[0m'\n" % self.ip
# 发起ssh连接请求 Make a ssh connection
ssh = self.get_connection()
# 获取连接的隧道并设置窗口大小 Make a channel and set windows size
global channel
win_size = self.get_win_size()
self.chan = channel = ssh.invoke_shell(height=win_size[0], width=win_size[1])
try:
signal.signal(signal.SIGWINCH, self.set_win_size)
except:
pass
# 设置PS1并提示 Set PS1 and msg it
#channel.send(ps1)
#channel.send(login_msg)
channel.send('echo ${SSH_TTY}\n')
global SSH_TTY
while not channel.recv_ready():
time.sleep(1)
tmp = channel.recv(1024)
#print 'ok'+tmp+'ok'
SSH_TTY = re.search(r'(?<=/dev/).*', tmp).group().strip()
channel.send('clear\n')
# Make ssh interactive tunnel
self.posix_shell(ssh)
# Shutdown channel socket
channel.close()
ssh.close()
def execute(self, cmd):
"""
execute cmd on the asset
执行命令
"""
pass
class PyCrypt(object): class PyCrypt(object):