Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
J
jumpserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
jumpserver
Commits
24730ebd
Commit
24730ebd
authored
Nov 07, 2015
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
web terminal记录日志
parent
43c07707
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
216 additions
and
161 deletions
+216
-161
connect.py
connect.py
+147
-112
settings.py
jumpserver/settings.py
+1
-1
run_websocket.py
run_websocket.py
+55
-33
log_online.html
templates/jlog/log_online.html
+13
-15
No files found.
connect.py
View file @
24730ebd
...
@@ -201,26 +201,6 @@ def deal_command(str_r, ssh):
...
@@ -201,26 +201,6 @@ def deal_command(str_r, ssh):
else
:
else
:
return
''
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
):
def
newline_code_in
(
strings
):
for
i
in
[
'
\r
'
,
'
\r\n
'
,
'
\n
'
]:
for
i
in
[
'
\r
'
,
'
\r\n
'
,
'
\n
'
]:
...
@@ -230,44 +210,54 @@ def newline_code_in(strings):
...
@@ -230,44 +210,54 @@ def newline_code_in(strings):
return
False
return
False
class
Jt
ty
(
object
):
class
T
ty
(
object
):
"""
"""
A virtual tty class
A virtual tty class
一个虚拟终端类,实现连接ssh和记录日志
一个虚拟终端类,实现连接ssh和记录日志
,基类
"""
"""
def
__init__
(
self
,
username
,
ip
):
def
__init__
(
self
,
username
,
asset_name
):
self
.
chan
=
None
self
.
username
=
username
self
.
username
=
username
self
.
ip
=
ip
self
.
asset_name
=
asset_name
# self.user = user
self
.
ip
=
None
# self.asset = asset
self
.
port
=
22
self
.
channel
=
None
self
.
user
=
None
self
.
asset
=
None
self
.
role
=
None
self
.
ssh
=
None
self
.
connect_info
=
None
self
.
login_type
=
'ssh'
@staticmethod
@staticmethod
def
get_win_size
():
def
is_output
(
strings
):
"""
newline_char
=
[
'
\n
'
,
'
\r
'
,
'
\r\n
'
]
This function use to get the size of the windows!
for
char
in
newline_char
:
获得terminal窗口大小
if
char
in
strings
:
"""
return
True
if
'TIOCGWINSZ'
in
dir
(
termios
):
return
False
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
):
@staticmethod
def
remove_control_char
(
str_r
):
"""
"""
This function use to set the window size of the terminal!
处理日志特殊字符
设置terminal窗口大小
"""
"""
try
:
control_char
=
re
.
compile
(
r"""
win_size
=
self
.
get_win_size
()
\x1b[ #
%
()*+\-.\/]. |
self
.
chan
.
resize_pty
(
height
=
win_size
[
0
],
width
=
win_size
[
1
])
\r | #匹配 回车符(CR)
except
Exception
:
(?:\x1b\[|\x9b) [ -?]* [@-~] | #匹配 控制顺序描述符(CSI)... Cmd
pass
(?:\x1b\]|\x9d) .*? (?:\x1b\\|[\a\x9c]) | \x07 | #匹配 操作系统指令(OSC)...终止符或振铃符(ST|BEL)
(?:\x1b[P^_]|[\x90\x9e\x9f]) .*? (?:\x1b\\|\x9c) | #匹配 设备控制串或私讯或应用程序命令(DCS|PM|APC)...终止符(ST)
def
log_record
(
self
):
\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
get_log_file
(
self
):
"""
"""
Logging user command and output.
Logging user command and output.
记录用户的日志
记录用户的日志
...
@@ -277,35 +267,114 @@ class Jtty(object):
...
@@ -277,35 +267,114 @@ class Jtty(object):
date_start
=
time
.
strftime
(
'
%
Y
%
m
%
d'
,
time
.
localtime
(
timestamp_start
))
date_start
=
time
.
strftime
(
'
%
Y
%
m
%
d'
,
time
.
localtime
(
timestamp_start
))
time_start
=
time
.
strftime
(
'
%
H
%
M
%
S'
,
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
)
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
))
log_file_path
=
os
.
path
.
join
(
today_connect_log_dir
,
'
%
s_
%
s_
%
s'
%
(
self
.
username
,
self
.
asset_name
,
time_start
))
pid
=
os
.
getpid
()
pts
=
os
.
popen
(
"ps axu | grep
%
s | grep -v grep | awk '{ print $7 }'"
%
pid
)
.
read
()
.
strip
()
if
self
.
login_type
==
'ssh'
:
ip_list
=
os
.
popen
(
"who | grep
%
s | awk '{ print $5 }'"
%
pts
)
.
read
()
.
strip
(
'()
\n
'
)
pid
=
os
.
getpid
()
remote_ip
=
os
.
popen
(
"who -m | awk '{ print $5 }'"
)
.
read
()
.
strip
(
'()
\n
'
)
else
:
pid
=
0
remote_ip
=
'Web'
try
:
try
:
is_dir
(
today_connect_log_dir
)
is_dir
(
today_connect_log_dir
,
mode
=
0777
)
except
OSError
:
except
OSError
:
raise
ServerError
(
'Create
%
s failed, Please modify
%
s permission.'
%
(
today_connect_log_dir
,
tty_log_dir
))
raise
ServerError
(
'Create
%
s failed, Please modify
%
s permission.'
%
(
today_connect_log_dir
,
tty_log_dir
))
try
:
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_file_f
=
open
(
log_file_path
+
'.log'
,
'a'
)
log_time_f
=
open
(
log_file_path
+
'.time'
,
'a'
)
log_time_f
=
open
(
log_file_path
+
'.time'
,
'a'
)
except
IOError
:
except
IOError
:
raise
ServerError
(
'Create logfile failed, Please modify
%
s permission.'
%
today_connect_log_dir
)
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
=
Log
(
user
=
self
.
username
,
host
=
self
.
asset_name
,
remote_ip
=
remote_ip
,
log_path
=
log_file_path
,
start_time
=
datetime
.
datetime
.
now
(),
pid
=
pid
)
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_file_f
.
write
(
'Start
at
%
s
\n
'
%
datetime
.
datetime
.
now
())
log
.
save
()
log
.
save
()
return
log_file_f
,
log_time_f
,
ip_list
,
log
return
log_file_f
,
log_time_f
,
log
def
get_connect_info
(
self
):
"""
获取需要登陆的主机的信息和映射用户的账号密码
"""
# 1. get ip, port
# 2. get 映射用户
# 3. get 映射用户的账号,密码或者key
# self.connect_info = {'user': '', 'asset': '', 'ip': '', 'port': 0, 'role_name': '', 'role_pass': '', 'role_key': ''}
self
.
connect_info
=
{
'user'
:
'a'
,
'asset'
:
'b'
,
'ip'
:
'127.0.0.1'
,
'port'
:
22
,
'role_name'
:
'root'
,
'role_pass'
:
'redhat'
,
'role_key'
:
''
}
return
self
.
connect_info
def
posix_shell
(
self
,
ssh
):
def
get_connection
(
self
):
"""
获取连接成功后的ssh
"""
connect_info
=
self
.
get_connect_info
()
# 发起ssh连接请求 Make a ssh connection
ssh
=
paramiko
.
SSHClient
()
ssh
.
load_system_host_keys
()
ssh
.
set_missing_host_key_policy
(
paramiko
.
AutoAddPolicy
())
try
:
if
connect_info
.
get
(
'role_pass'
):
ssh
.
connect
(
connect_info
.
get
(
'ip'
),
port
=
connect_info
.
get
(
'port'
),
username
=
connect_info
.
get
(
'role_name'
),
password
=
connect_info
.
get
(
'role_pass'
),
look_for_keys
=
False
)
else
:
ssh
.
connect
(
connect_info
.
get
(
'ip'
),
port
=
connect_info
.
get
(
'port'
),
username
=
connect_info
.
get
(
'role_name'
),
key_filename
=
connect_info
.
get
(
'role_key'
),
look_for_keys
=
False
)
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
:
self
.
ssh
=
ssh
return
ssh
class
SshTty
(
Tty
):
"""
A virtual tty class
一个虚拟终端类,实现连接ssh和记录日志
"""
@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
.
channel
.
resize_pty
(
height
=
win_size
[
0
],
width
=
win_size
[
1
])
except
Exception
:
pass
def
posix_shell
(
self
):
"""
"""
Use paramiko channel connect server interactive.
Use paramiko channel connect server interactive.
使用paramiko模块的channel,连接后端,进入交互式
使用paramiko模块的channel,连接后端,进入交互式
"""
"""
log_file_f
,
log_time_f
,
ip_list
,
log
=
self
.
log_record
()
log_file_f
,
log_time_f
,
log
=
self
.
get_log_file
()
old_tty
=
termios
.
tcgetattr
(
sys
.
stdin
)
old_tty
=
termios
.
tcgetattr
(
sys
.
stdin
)
pre_timestamp
=
time
.
time
()
pre_timestamp
=
time
.
time
()
input_r
=
''
input_r
=
''
...
@@ -314,29 +383,29 @@ class Jtty(object):
...
@@ -314,29 +383,29 @@ class Jtty(object):
try
:
try
:
tty
.
setraw
(
sys
.
stdin
.
fileno
())
tty
.
setraw
(
sys
.
stdin
.
fileno
())
tty
.
setcbreak
(
sys
.
stdin
.
fileno
())
tty
.
setcbreak
(
sys
.
stdin
.
fileno
())
self
.
chan
.
settimeout
(
0.0
)
self
.
chan
nel
.
settimeout
(
0.0
)
while
True
:
while
True
:
try
:
try
:
r
,
w
,
e
=
select
.
select
([
self
.
chan
,
sys
.
stdin
],
[],
[])
r
,
w
,
e
=
select
.
select
([
self
.
chan
nel
,
sys
.
stdin
],
[],
[])
except
Exception
:
except
Exception
:
pass
pass
if
self
.
chan
in
r
:
if
self
.
chan
nel
in
r
:
try
:
try
:
x
=
self
.
chan
.
recv
(
1024
)
x
=
self
.
chan
nel
.
recv
(
1024
)
if
len
(
x
)
==
0
:
if
len
(
x
)
==
0
:
break
break
sys
.
stdout
.
write
(
x
)
sys
.
stdout
.
write
(
x
)
sys
.
stdout
.
flush
()
sys
.
stdout
.
flush
()
log_file_f
.
write
(
x
)
now_timestamp
=
time
.
time
()
now_timestamp
=
time
.
time
()
log_time_f
.
write
(
'
%
s
%
s
\n
'
%
(
round
(
now_timestamp
-
pre_timestamp
,
4
),
len
(
x
)))
log_time_f
.
write
(
'
%
s
%
s
\n
'
%
(
round
(
now_timestamp
-
pre_timestamp
,
4
),
len
(
x
)))
log_file_f
.
write
(
x
)
pre_timestamp
=
now_timestamp
pre_timestamp
=
now_timestamp
log_file_f
.
flush
()
log_file_f
.
flush
()
log_time_f
.
flush
()
log_time_f
.
flush
()
if
input_mode
and
not
newline_code_in
(
x
):
if
input_mode
and
not
self
.
is_output
(
x
):
input_r
+=
x
input_r
+=
x
except
socket
.
timeout
:
except
socket
.
timeout
:
...
@@ -348,14 +417,16 @@ class Jtty(object):
...
@@ -348,14 +417,16 @@ class Jtty(object):
input_mode
=
True
input_mode
=
True
if
str
(
x
)
in
[
'
\r
'
,
'
\n
'
,
'
\r\n
'
]:
if
str
(
x
)
in
[
'
\r
'
,
'
\n
'
,
'
\r\n
'
]:
input_r
=
deal_command
(
input_r
,
ssh
)
# input_r = deal_command(input_r,ssh)
input_r
=
self
.
remove_control_char
(
input_r
)
TtyLog
(
log
=
log
,
datetime
=
datetime
.
datetime
.
now
(),
cmd
=
input_r
)
.
save
()
TtyLog
(
log
=
log
,
datetime
=
datetime
.
datetime
.
now
(),
cmd
=
input_r
)
.
save
()
input_r
=
''
input_r
=
''
input_mode
=
False
input_mode
=
False
if
len
(
x
)
==
0
:
if
len
(
x
)
==
0
:
break
break
self
.
chan
.
send
(
x
)
self
.
chan
nel
.
send
(
x
)
finally
:
finally
:
termios
.
tcsetattr
(
sys
.
stdin
,
termios
.
TCSADRAIN
,
old_tty
)
termios
.
tcsetattr
(
sys
.
stdin
,
termios
.
TCSADRAIN
,
old_tty
)
...
@@ -365,42 +436,6 @@ class Jtty(object):
...
@@ -365,42 +436,6 @@ class Jtty(object):
log
.
end_time
=
datetime
.
datetime
.
now
()
log
.
end_time
=
datetime
.
datetime
.
now
()
log
.
save
()
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
):
def
connect
(
self
):
"""
"""
Connect server.
Connect server.
...
@@ -415,7 +450,7 @@ class Jtty(object):
...
@@ -415,7 +450,7 @@ class Jtty(object):
# 获取连接的隧道并设置窗口大小 Make a channel and set windows size
# 获取连接的隧道并设置窗口大小 Make a channel and set windows size
global
channel
global
channel
win_size
=
self
.
get_win_size
()
win_size
=
self
.
get_win_size
()
self
.
chan
=
channel
=
ssh
.
invoke_shell
(
height
=
win_size
[
0
],
width
=
win_size
[
1
]
)
self
.
chan
nel
=
channel
=
ssh
.
invoke_shell
(
height
=
win_size
[
0
],
width
=
win_size
[
1
],
term
=
'xterm'
)
try
:
try
:
signal
.
signal
(
signal
.
SIGWINCH
,
self
.
set_win_size
)
signal
.
signal
(
signal
.
SIGWINCH
,
self
.
set_win_size
)
except
:
except
:
...
@@ -424,17 +459,17 @@ class Jtty(object):
...
@@ -424,17 +459,17 @@ class Jtty(object):
# 设置PS1并提示 Set PS1 and msg it
# 设置PS1并提示 Set PS1 and msg it
#channel.send(ps1)
#channel.send(ps1)
#channel.send(login_msg)
#channel.send(login_msg)
channel
.
send
(
'echo ${SSH_TTY}
\n
'
)
#
channel.send('echo ${SSH_TTY}\n')
global
SSH_TTY
#
global SSH_TTY
while
not
channel
.
recv_ready
():
#
while not channel.recv_ready():
time
.
sleep
(
1
)
#
time.sleep(1)
tmp
=
channel
.
recv
(
1024
)
#
tmp = channel.recv(1024)
#print 'ok'+tmp+'ok'
#print 'ok'+tmp+'ok'
# SSH_TTY = re.search(r'(?<=/dev/).*', tmp).group().strip()
# SSH_TTY = re.search(r'(?<=/dev/).*', tmp).group().strip()
SSH_TTY
=
''
#
SSH_TTY = ''
channel
.
send
(
'clear
\n
'
)
channel
.
send
(
'clear
\n
'
)
# Make ssh interactive tunnel
# Make ssh interactive tunnel
self
.
posix_shell
(
ssh
)
self
.
posix_shell
()
# Shutdown channel socket
# Shutdown channel socket
channel
.
close
()
channel
.
close
()
...
...
jumpserver/settings.py
View file @
24730ebd
...
@@ -15,7 +15,7 @@ import getpass
...
@@ -15,7 +15,7 @@ import getpass
config
=
ConfigParser
.
ConfigParser
()
config
=
ConfigParser
.
ConfigParser
()
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
dirname
(
__file__
))
BASE_DIR
=
os
.
path
.
abspath
(
os
.
path
.
dirname
(
os
.
path
.
dirname
(
__file__
)
))
config
.
read
(
os
.
path
.
join
(
BASE_DIR
,
'jumpserver.conf'
))
config
.
read
(
os
.
path
.
join
(
BASE_DIR
,
'jumpserver.conf'
))
DB_HOST
=
config
.
get
(
'db'
,
'host'
)
DB_HOST
=
config
.
get
(
'db'
,
'host'
)
...
...
run_websocket.py
View file @
24730ebd
# coding: utf-8
# coding: utf-8
import
time
import
time
import
datetime
import
json
import
json
import
os
import
os
import
sys
import
sys
...
@@ -25,6 +26,8 @@ from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE
...
@@ -25,6 +26,8 @@ from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE
import
struct
,
fcntl
,
signal
,
socket
,
select
,
fnmatch
import
struct
,
fcntl
,
signal
,
socket
,
select
,
fnmatch
import
paramiko
import
paramiko
from
connect
import
Tty
from
connect
import
TtyLog
try
:
try
:
import
simplejson
as
json
import
simplejson
as
json
...
@@ -124,12 +127,6 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
...
@@ -124,12 +127,6 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
MonitorHandler
.
threads
.
append
(
thread
)
MonitorHandler
.
threads
.
append
(
thread
)
self
.
stream
.
set_nodelay
(
True
)
self
.
stream
.
set_nodelay
(
True
)
print
len
(
MonitorHandler
.
threads
),
len
(
MonitorHandler
.
clients
)
def
on_message
(
self
,
message
):
self
.
write_message
(
'Connect WebSocket Success. <br/>'
)
# 监控日志,发生变动发向客户端
try
:
try
:
for
t
in
MonitorHandler
.
threads
:
for
t
in
MonitorHandler
.
threads
:
if
t
.
is_alive
():
if
t
.
is_alive
():
...
@@ -143,6 +140,12 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
...
@@ -143,6 +140,12 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
MonitorHandler
.
clients
.
remove
(
self
)
MonitorHandler
.
clients
.
remove
(
self
)
MonitorHandler
.
threads
.
remove
(
MonitorHandler
.
threads
[
client_index
])
MonitorHandler
.
threads
.
remove
(
MonitorHandler
.
threads
[
client_index
])
print
len
(
MonitorHandler
.
threads
),
len
(
MonitorHandler
.
clients
)
def
on_message
(
self
,
message
):
# 监控日志,发生变动发向客户端
pass
def
on_close
(
self
):
def
on_close
(
self
):
# 客户端主动关闭
# 客户端主动关闭
# self.close()
# self.close()
...
@@ -153,28 +156,34 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
...
@@ -153,28 +156,34 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
MonitorHandler
.
threads
.
remove
(
MonitorHandler
.
threads
[
client_index
])
MonitorHandler
.
threads
.
remove
(
MonitorHandler
.
threads
[
client_index
])
class
WebTty
(
Tty
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
WebTty
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
login_type
=
'web'
self
.
ws
=
None
self
.
input_r
=
''
self
.
input_mode
=
False
class
WebTerminalHandler
(
tornado
.
websocket
.
WebSocketHandler
):
class
WebTerminalHandler
(
tornado
.
websocket
.
WebSocketHandler
):
tasks
=
[]
tasks
=
[]
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
chan
=
None
self
.
term
=
None
self
.
ssh
=
None
self
.
channel
=
None
self
.
log_file_f
=
None
self
.
log_time_f
=
None
self
.
log
=
None
super
(
WebTerminalHandler
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
super
(
WebTerminalHandler
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
def
check_origin
(
self
,
origin
):
def
check_origin
(
self
,
origin
):
return
True
return
True
def
open
(
self
):
def
open
(
self
):
self
.
ssh
=
paramiko
.
SSHClient
()
self
.
term
=
WebTty
(
'a'
,
'b'
)
self
.
ssh
.
set_missing_host_key_policy
(
paramiko
.
AutoAddPolicy
())
self
.
term
.
get_connection
()
try
:
self
.
channel
=
self
.
term
.
ssh
.
invoke_shell
(
term
=
'xterm'
)
self
.
ssh
.
connect
(
'127.0.0.1'
,
22
,
'root'
,
'redhat'
)
WebTerminalHandler
.
tasks
.
append
(
MyThread
(
target
=
self
.
forward_outbound
))
except
:
self
.
write_message
(
json
.
loads
({
'data'
:
'Connect server Error'
}))
self
.
close
()
self
.
chan
=
self
.
ssh
.
invoke_shell
(
term
=
'xterm'
)
WebTerminalHandler
.
tasks
.
append
(
threading
.
Thread
(
target
=
self
.
_forward_outbound
))
for
t
in
WebTerminalHandler
.
tasks
:
for
t
in
WebTerminalHandler
.
tasks
:
if
t
.
is_alive
():
if
t
.
is_alive
():
...
@@ -186,37 +195,50 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
...
@@ -186,37 +195,50 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
data
=
json
.
loads
(
message
)
data
=
json
.
loads
(
message
)
if
not
data
:
if
not
data
:
return
return
if
'resize'
in
data
:
if
data
.
get
(
'data'
):
self
.
chan
.
resize_pty
(
self
.
term
.
input_mode
=
True
data
[
'resize'
]
.
get
(
'width'
,
80
),
if
str
(
data
[
'data'
])
in
[
'
\r
'
,
'
\n
'
,
'
\r\n
'
]:
data
[
'resize'
]
.
get
(
'height'
,
24
))
TtyLog
(
log
=
self
.
log
,
datetime
=
datetime
.
datetime
.
now
(),
cmd
=
self
.
term
.
remove_control_char
(
self
.
term
.
input_r
))
.
save
()
if
'data'
in
data
:
self
.
term
.
input_r
=
''
self
.
chan
.
send
(
data
[
'data'
])
self
.
term
.
input_mode
=
False
self
.
channel
.
send
(
data
[
'data'
])
def
on_close
(
self
):
def
on_close
(
self
):
self
.
write_message
(
json
.
dumps
({
'data'
:
'close websocket'
}))
print
'On_close'
self
.
log_file_f
.
write
(
'End time is
%
s'
%
datetime
.
datetime
.
now
())
def
_forward_outbound
(
self
):
self
.
log
.
is_finished
=
True
""" Forward outbound traffic (ssh -> websockets) """
self
.
log
.
end_time
=
datetime
.
datetime
.
now
()
self
.
log
.
save
()
self
.
close
()
def
forward_outbound
(
self
):
self
.
log_file_f
,
self
.
log_time_f
,
self
.
log
=
self
.
term
.
get_log_file
()
try
:
try
:
data
=
''
data
=
''
pre_timestamp
=
time
.
time
()
while
True
:
while
True
:
r
,
w
,
e
=
select
.
select
([
self
.
chan
,
sys
.
stdin
],
[],
[])
r
,
w
,
e
=
select
.
select
([
self
.
channel
,
sys
.
stdin
],
[],
[])
if
self
.
chan
in
r
:
if
self
.
channel
in
r
:
recv
=
self
.
chan
.
recv
(
1024
)
recv
=
self
.
channel
.
recv
(
1024
)
print
recv
if
not
len
(
recv
):
if
not
len
(
recv
):
return
return
data
+=
recv
data
+=
recv
try
:
try
:
self
.
write_message
(
json
.
dumps
({
'data'
:
data
}))
self
.
write_message
(
json
.
dumps
({
'data'
:
data
}))
now_timestamp
=
time
.
time
()
self
.
log_time_f
.
write
(
'
%
s
%
s
\n
'
%
(
round
(
now_timestamp
-
pre_timestamp
,
4
),
len
(
data
)))
self
.
log_file_f
.
write
(
data
)
pre_timestamp
=
now_timestamp
self
.
log_file_f
.
flush
()
self
.
log_time_f
.
flush
()
if
self
.
term
.
input_mode
and
not
self
.
term
.
is_output
(
data
):
self
.
term
.
input_r
+=
data
data
=
''
data
=
''
except
UnicodeDecodeError
:
except
UnicodeDecodeError
:
pass
pass
finally
:
finally
:
self
.
close
()
self
.
close
()
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
tornado
.
options
.
parse_command_line
()
tornado
.
options
.
parse_command_line
()
app
=
Application
()
app
=
Application
()
...
...
templates/jlog/log_online.html
View file @
24730ebd
...
@@ -127,8 +127,20 @@
...
@@ -127,8 +127,20 @@
var
file_path
=
obj
.
attr
(
'file_path'
);
var
file_path
=
obj
.
attr
(
'file_path'
);
var
wsUri
=
'{{ web_monitor_uri }}'
;
var
wsUri
=
'{{ web_monitor_uri }}'
;
var
socket
=
new
WebSocket
(
wsUri
+
'?file_path='
+
file_path
);
var
socket
=
new
WebSocket
(
wsUri
+
'?file_path='
+
file_path
);
var
term
=
new
Terminal
({
cols
:
80
,
rows
:
24
,
screenKeys
:
false
});
var
tag
=
$
(
'<div id="term" style="height:500px; overflow: auto;background-color: rgba(0, 0, 0, 0);border: none"></div>'
);
term
.
open
();
term
.
resize
(
80
,
24
);
socket
.
onopen
=
function
(
evt
){
socket
.
onopen
=
function
(
evt
){
socket
.
send
(
file_path
)
socket
.
send
(
'hello'
);
term
.
write
(
'~.~ Connect WebSocket Success.~.~
\
r
\
n'
);
};
};
window
.
onbeforeunload
=
function
(){
window
.
onbeforeunload
=
function
(){
...
@@ -138,29 +150,15 @@
...
@@ -138,29 +150,15 @@
var
username
=
obj
.
closest
(
'tr'
).
find
(
'#username'
).
text
();
var
username
=
obj
.
closest
(
'tr'
).
find
(
'#username'
).
text
();
var
ip
=
obj
.
closest
(
'tr'
).
find
(
'#ip'
).
text
();
var
ip
=
obj
.
closest
(
'tr'
).
find
(
'#ip'
).
text
();
BootstrapDialog
.
show
({
message
:
function
(){
BootstrapDialog
.
show
({
message
:
function
(){
//服务器端认证
//服务器端认证
{
#
socket
.
send
(
'login'
,
{
userid
:
message
.
id
,
filename
:
message
.
filename
,
username
:
username
,
seed
:
seed
});
#
}
{
#
socket
.
send
(
'login'
,
{
userid
:
message
.
id
,
filename
:
message
.
filename
,
username
:
username
,
seed
:
seed
});
#
}
var
term
=
new
Terminal
({
cols
:
80
,
rows
:
24
,
screenKeys
:
false
});
var
tag
=
$
(
'<div id="term" style="height:500px; overflow: auto;background-color: rgba(0, 0, 0, 0);border: none"></div>'
);
term
.
open
();
term
.
resize
(
80
,
24
);
window
.
setTimeout
(
function
(){
window
.
setTimeout
(
function
(){
$
(
'.terminal'
).
detach
().
appendTo
(
'#term'
);
$
(
'.terminal'
).
detach
().
appendTo
(
'#term'
);
socket
.
onmessage
=
function
(
evt
){
socket
.
onmessage
=
function
(
evt
){
term
.
write
(
evt
.
data
);
term
.
write
(
evt
.
data
);
}},
1000
);
}},
1000
);
tag
[
0
].
style
.
color
=
"#00FF00"
;
return
tag
[
0
];
return
tag
[
0
];
}
,
}
,
title
:
'Jumpserver实时监控 '
+
' 登录用户名: '
+
'<span class="text-info">'
+
username
+
'</span>'
+
' 登录主机: '
+
'<span class="text-info">'
+
ip
,
title
:
'Jumpserver实时监控 '
+
' 登录用户名: '
+
'<span class="text-info">'
+
username
+
'</span>'
+
' 登录主机: '
+
'<span class="text-info">'
+
ip
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment