Skip to content

Commit

Permalink
ver1.6.0 新增web终端实时查看在线会话()
Browse files Browse the repository at this point in the history
  • Loading branch information
root committed Aug 16, 2019
1 parent 55a69ed commit 87aa2e3
Show file tree
Hide file tree
Showing 59 changed files with 898 additions and 408 deletions.
192 changes: 103 additions & 89 deletions .idea/workspace.xml

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ sh start_docker.sh
![效果](https://github.com/leffss/devops/blob/master/screenshots/33.PNG?raw=true)
![效果](https://github.com/leffss/devops/blob/master/screenshots/34.PNG?raw=true)
![效果](https://github.com/leffss/devops/blob/master/screenshots/35.PNG?raw=true)
![效果](https://github.com/leffss/devops/blob/master/screenshots/36.PNG?raw=true)
![效果](https://github.com/leffss/devops/blob/master/screenshots/37.JPG?raw=true)


# TODO LISTS
Expand Down Expand Up @@ -93,7 +95,9 @@ sh start_docker.sh
- [ ] 批量脚本
- [x] webssh终端
- [x] webtelnet终端
- [x] 查看在线会话
- [x] 查看在线会话列表
- [x] 实时查看在线会话
- [ ] 锁定实时在线会话
- [x] 强制关闭在线会话
- [ ] 文件上传
- [ ] 文件下载
Expand Down
Binary file modified db.sqlite3
Binary file not shown.
13 changes: 9 additions & 4 deletions layer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
""" 初始化创建 admin 账号"""
import os
import sys

Expand All @@ -10,14 +11,18 @@ def main():
# 让django初始化
import django
django.setup()

from user.models import User
from util.tool import hash_code

from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
channel_layer = get_channel_layer()
async_to_sync(channel_layer.send)("specific.FEfncEYP!bFdhrEmvyBIV", {
async_to_sync(channel_layer.send)('specific.WjcnLeaL!oejCJLfYFOdT', {
"type": "chat.message",
"text": '{"status":2, "message":"\\n\\rAdministrator forcibly interrupts your connection"}',
"text": '{"status":3, "message":"系统即将关闭,请退出当前会话!"}',
})


if __name__ == '__main__':
main()
27 changes: 27 additions & 0 deletions layer_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env python
import os
import sys


def main():
# 使用django配置文件进行设置
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'devops.settings')

# 让django初始化
import django
django.setup()

from user.models import User
from util.tool import hash_code

from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)('session_NbxeEnGcUv', {
"type": "chat.message",
"text": '{"status":3, "message":"系统即将关闭,请退出当前会话!- 来自组"}',
})


if __name__ == '__main__':
main()
Binary file added screenshots/36.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/37.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 15 additions & 4 deletions static/webssh/webssh.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function websocket() {
var status = data.status;
if (status === 0) {
term.write(message)
} else {
} else if (status === 1 || status === 2 ) {
//window.location.reload() 端口连接后刷新页面
//term.clear()
term.write(message)
Expand All @@ -71,21 +71,32 @@ function websocket() {
//term.dispose()
//$('#django-webssh-terminal').addClass('hide');
//$('#form').removeClass('hide');
}
} else if (status === 3 ) {
console.log(message);
toastr.options.closeButton = true;
toastr.options.showMethod = 'slideDown';
toastr.options.hideMethod = 'fadeOut';
toastr.options.closeMethod = 'fadeOut';
toastr.options.timeOut = 0;
toastr.options.extendedTimeOut = 0;
toastr.options.progressBar = true;
toastr.options.positionClass = 'toast-top-right';
toastr.warning(message);
};
});

/*
* status 为 0 时, 将用户输入的数据通过 websocket 传递给后台, data 为传递的数据, 忽略 cols 和 rows 参数
* status 为 1 时, resize pty ssh 终端大小, cols 为每行显示的最大字数, rows 为每列显示的最大字数, 忽略 data 参数
*/
var message = {'status': 0, 'data': null, 'cols': null, 'rows': null};

// 向服务器端发送数据
term.on('data', function (data) {
message['status'] = 0;
message['data'] = data;
var send_data = JSON.stringify(message);
sock.send(send_data)
sock.send(send_data);
});

// 监听浏览器窗口, 根据浏览器窗口大小修改终端大小
Expand Down
115 changes: 115 additions & 0 deletions static/webssh/webssh.view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
function checkwindow() {
event.returnValue=false;
}

function get_connect_info() {
var group = $.trim($('#group').text());
var connect_info = 'group=' + group;
return connect_info
}

function get_term_size() {
var init_width = 9;
var init_height = 17;

var windows_width = $(window).width();
var windows_height = $(window).height();

return {
cols: Math.floor(windows_width / init_width),
rows: Math.floor(windows_height / init_height),
}
}

function websocket() {
var cols = get_term_size().cols;
var rows = get_term_size().rows;
var connect_info = get_connect_info();

var term = new Terminal(
{
cols: cols,
rows: rows,
useStyle: true,
cursorBlink: true
}
),
protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://',
socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/webssh/view/?' + connect_info;

var sock;
sock = new WebSocket(socketURL);

// 打开 websocket 连接, 打开 web 终端
sock.addEventListener('open', function () {
//$('#django-webssh-terminal').removeClass('hide');
term.open(document.getElementById('terminal'));
//term.focus();
//term.write('Connecting...\n\r');
$("body").attr("onbeforeunload",'checkwindow()'); //增加刷新关闭提示属性

});

// 读取服务器端发送的数据并写入 web 终端
sock.addEventListener('message', function (recv) {
var data = JSON.parse(recv.data);
var message = data.message;
var status = data.status;
if (status === 0) {
term.write(message)
} else if (status === 1 || status === 2 ) {
//window.location.reload() 端口连接后刷新页面
//term.clear()
term.write(message)
$("body").removeAttr("onbeforeunload"); //删除刷新关闭提示属性

//$(document).keyup(function(event){ // 监听回车按键事件
// if(event.keyCode == 13){
//window.location.reload();
// }
//});
//term.dispose()
//$('#django-webssh-terminal').addClass('hide');
//$('#form').removeClass('hide');
} else if (status === 3 ) {
console.log(message);
toastr.options.closeButton = true;
toastr.options.showMethod = 'slideDown';
toastr.options.hideMethod = 'fadeOut';
toastr.options.closeMethod = 'fadeOut';
toastr.options.timeOut = 0;
toastr.options.extendedTimeOut = 0;
toastr.options.progressBar = true;
toastr.options.positionClass = 'toast-top-right';
toastr.warning(message);
} else if (status === 5 ) {
term.write(message)
};
});

/*
* status 为 0 时, 将用户输入的数据通过 websocket 传递给后台, data 为传递的数据, 忽略 cols 和 rows 参数
* status 为 1 时, resize pty ssh 终端大小, cols 为每行显示的最大字数, rows 为每列显示的最大字数, 忽略 data 参数
*/
var message = {'status': 0, 'data': null, 'cols': null, 'rows': null};

// 向服务器端发送数据
term.on('data', function (data) {
//message['status'] = 0;
//message['data'] = data;
//var send_data = JSON.stringify(message);
//sock.send(send_data);
});

// 监听浏览器窗口, 根据浏览器窗口大小修改终端大小
$(window).resize(function () {
var cols = get_term_size().cols;
var rows = get_term_size().rows;
//message['status'] = 1;
//message['cols'] = cols;
//message['rows'] = rows;
//var send_data = JSON.stringify(message);
//sock.send(send_data);
term.resize(cols, rows)
})
}
15 changes: 13 additions & 2 deletions static/webtelnet/webtelnet.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function websocket() {
var status = data.status;
if (status === 0) {
term.write(message)
} else {
} else if (status === 1 || status === 2 ) {
//window.location.reload() 端口连接后刷新页面
//term.clear()
term.write(message)
Expand All @@ -73,7 +73,18 @@ function websocket() {
//term.dispose()
//$('#django-webssh-terminal').addClass('hide');
//$('#form').removeClass('hide');
}
} else if (status === 3 ) {
console.log(message);
toastr.options.closeButton = true;
toastr.options.showMethod = 'slideDown';
toastr.options.hideMethod = 'fadeOut';
toastr.options.closeMethod = 'fadeOut';
toastr.options.timeOut = 0;
toastr.options.extendedTimeOut = 0;
toastr.options.progressBar = true;
toastr.options.positionClass = 'toast-top-right';
toastr.warning(message);
};
});

/*
Expand Down
6 changes: 4 additions & 2 deletions templates/server/host.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@
{% endblock navheader %}

{% block content %}
<div class="card">
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">主机信息</h3>
<div class="card-tools">
{% if request.session.issuperuser %}
<a class="btn btn-tool" href="{% url 'server:host_edit' host.id %}" title="编辑">
<!--i class="fas fa-wrench"></i-->编辑
</a>
{% endif %}
<button type="button" class="btn btn-tool" data-widget="collapse">
<i class="fas fa-minus"></i>
</button>
Expand All @@ -52,7 +54,7 @@ <h3 class="card-title">主机信息</h3>
<div class="col-3 pt-1 pb-1 border-bottom">系统/型号:</div><div class="col-9 pt-1 pb-1 border-bottom">{{ host.release }}</div>
<div class="col-3 pt-1 pb-1 border-bottom">用户名:</div><div class="col-9 pt-1 pb-1 border-bottom">{{ host.remote_user.username }}</div>
<div class="col-3 pt-1 pb-1 border-bottom">添加时间:</div><div class="col-9 pt-1 pb-1 border-bottom">{{ host.create_time | date:"Y/m/d H:i:s" }}</div>
<div class="col-3 pt-1 pb-1 border-bottom">是否启用:</div><div class="col-9 pt-1 pb-1 border-bottom">{% if host.enabled %}启用{% else %}<span style="color:red">禁用</span>{% endif %}</div>
<div class="col-3 pt-1 pb-1 border-bottom">是否启用:</div><div class="col-9 pt-1 pb-1 border-bottom">{% if host.enabled %}<span class="badge badge-success">启用</span>{% else %}<span class="badge badge-danger">禁用</span>{% endif %}</div>
<div class="col-3 pt-1 pb-1">备注:</div><div class="col-9 pt-1 pb-1">{{ host.memo | default:'' }}</div>
</div>
<!-- /.card-body -->
Expand Down
4 changes: 2 additions & 2 deletions templates/server/host_add.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
{% endblock navheader %}

{% block content %}
<div class="card">
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">添加主机</h3>
<div class="card-tools">
Expand Down Expand Up @@ -93,7 +93,7 @@ <h3 class="card-title">添加主机</h3>
<label class="custom-control-label" for="enabled">启用</label>
</div>
</div>
<div class="offset-2 col-10 pt-2"><button class="btn btn-default" type="reset">重置</button><button class="btn btn-success ml-2" onclick="changeuserprofile(this);">提交</button><span id="feed_error" class="ml-2" style="color:red;"></span></div>
<div class="offset-2 col-10 pt-2"><a class="btn btn-default" href="{% url 'server:hosts' %}">返回</a> <button class="btn btn-success ml-2" onclick="changeuserprofile(this);">提交</button><span id="feed_error" class="ml-2" style="color:red;"></span></div>
</div>
<!-- /.card-body -->
</div>
Expand Down
4 changes: 2 additions & 2 deletions templates/server/host_edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
{% endblock navheader %}

{% block content %}
<div class="card">
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">主机编辑</h3>
<div class="card-tools">
Expand Down Expand Up @@ -93,7 +93,7 @@ <h3 class="card-title">主机编辑</h3>
<label class="custom-control-label" for="enabled">启用</label>
</div>
</div>
<div class="offset-2 col-10 pt-2"><button class="btn btn-default" type="reset">重置</button><button class="btn btn-success ml-2" onclick="changeuserprofile(this);">提交</button><span id="feed_error" class="ml-2" style="color:red;"></span></div>
<div class="offset-2 col-10 pt-2"><a class="btn btn-default" href="{% url 'server:hosts' %}">返回</a> <button class="btn btn-success ml-2" onclick="changeuserprofile(this);">提交</button><span id="feed_error" class="ml-2" style="color:red;"></span></div>
</div>
<!-- /.card-body -->
</div>
Expand Down
14 changes: 8 additions & 6 deletions templates/server/hosts.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
{% endblock navheader %}

{% block content %}
<div class="card">
<div class="card card-primary card-outline">
<div class="card-header">
<h3 class="card-title">
主机列表{% if request.session.issuperuser %}<a href="{% url 'server:host_add' %}" class="btn btn-sm btn-outline-success ml-3 addsoft">新增 + </a>{% endif %}
主机列表{% if request.session.issuperuser %}<a href="{% url 'server:host_add' %}" class="btn btn-sm btn-outline-success ml-3 addsoft"><i class="fas fa-plus fa-sm"></i> 新增</a>{% endif %}
</h3>
<div class="card-tools">
<button type="button" class="btn btn-tool" data-widget="collapse">
Expand Down Expand Up @@ -59,12 +59,12 @@ <h3 class="card-title">
<tbody>
{% for host in hosts %}
<tr id="host-{{ host.id }}">
<td><a href="{% url 'server:host' host.id %}">{{ host.hostname }}</a></td>
<td>{{ host.hostname }}</td>
<td>{{ host.get_type_display }}</td>
<td>{{ host.get_env_display }}</td>
<td>{{ host.ip }}</td>
<td>{% if host.enabled %}启用{% else %}<span style="color:red">禁用</span>{% endif %}</td>
<td>{{ host.get_protocol_display }}</td>
<td>{% if host.enabled %}<span class="badge badge-success">启用</span>{% else %}<span class="badge badge-danger">禁用</span>{% endif %}</td>
<td><span class="badge badge-success">{{ host.get_protocol_display }}</span></td>
<td>{{ host.port }}</td>
<td>{{ host.release }}</td>
{% if host.remote_user %}
Expand All @@ -73,7 +73,9 @@ <h3 class="card-title">
<td></td>
{% endif %}
<td>{{ host.create_time|date:"Y/m/d H:i:s" }}</td>
<td><a href="{% url 'server:host' host.id %}">详细</a> {% if request.session.issuperuser %}<a href="{% url 'server:host_edit' host.id %}">编辑</a> <a href="javascript:void(0)" id="{{ host.id }}" title="{{ host.hostname }}" onclick="createdeletemodal(this);">删除</a>{% endif %}</td>
<td><a href="{% url 'server:host' host.id %}" class="btn btn-primary btn-sm"><i class="fas fa-folder"></i> 详细</a>
{% if request.session.issuperuser %}&nbsp;&nbsp;<a href="{% url 'server:host_edit' host.id %}" class="btn btn-info btn-sm"><i class="fas fa-pencil-alt"></i> 编辑</a>&nbsp;&nbsp;<a href="javascript:void(0)" id="{{ host.id }}" title="{{ host.hostname }}" onclick="createdeletemodal(this);" class="btn btn-danger btn-sm"><i class="fas fa-trash"></i> 删除</a>{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
Expand Down
4 changes: 2 additions & 2 deletions templates/server/user.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
{% endblock navheader %}

{% block content %}
<div class="card">
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">用户信息</h3>
<div class="card-tools">
Expand All @@ -45,7 +45,7 @@ <h3 class="card-title">用户信息</h3>
<div class="col-3 pt-1 pb-1 border-bottom">名称:</div><div class="col-9 pt-1 pb-1 border-bottom">{{ user.name }}</div>
<div class="col-3 pt-1 pb-1 border-bottom">用户名:</div><div class="col-9 pt-1 pb-1 border-bottom">{{ user.username }}</div>
<div class="col-3 pt-1 pb-1 border-bottom">密码:</div><div class="col-9 pt-1 pb-1 border-bottom">{{ user.password }}</div>
<div class="col-3 pt-1 pb-1 border-bottom">登陆后是否su跳转超级用户:</div><div class="col-9 pt-1 pb-1 border-bottom">{% if user.enabled %}{% else %}<span style="color:red"><span>{% endif %}</div>
<div class="col-3 pt-1 pb-1 border-bottom">登陆后是否su跳转超级用户:</div><div class="col-9 pt-1 pb-1 border-bottom">{% if user.enabled %}<span class="badge badge-success"></span>{% else %}<span class="badge badge-danger"></span>{% endif %}</div>
{% if user.enabled %}
<div class="col-3 pt-1 pb-1 border-bottom">超级用户:</div><div class="col-9 pt-1 pb-1 border-bottom">{{ user.superusername | default:'' }}</div>
<div class="col-3 pt-1 pb-1 border-bottom">超级密码:</div><div class="col-9 pt-1 pb-1 border-bottom">{{ user.superpassword | default:'' }}</div>
Expand Down
Loading

0 comments on commit 87aa2e3

Please sign in to comment.