Web方式执行系统命令和结果显示,就是在 Web页面上输入 Windows 或 Linux 的系统命令或脚本执行,把执行结果显示在 Web 页面上。
1. 开发环境
Windows 10 Home (20H2) or Ubuntu 18.04
Python 3.8.1
Pip 21.3.1
Django: 4.0
Windows下搭建开发环境,请参考Windows下搭建 Django 3.x 开发和运行环境
Ubuntu下搭建开发环境,请参考Ubuntu下搭建 Django 3.x 开发和运行环境
2. 创建 Django 项目
> django-admin startproject djangoShellDemo
3. 添加 App
> cd djangoShellDemo
> python manage.py startapp home
生成的项目目录结构,参考如何在Django中使用template和Bootstrap
修改 djangoShellDemo/settings.py
ALLOWED_HOSTS = ['localhost', '192.168.0.5']
...
INSTALLED_APPS = [
...
'home',
]
...
# Create static folder
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
4. 静态资源和模板
1) 静态资源
从 https://jquery.com/ 下载 jQuery 包, 添加到 :
static/js/jquery-1.12.2.min.js
* static 等中间目录如果不存在,请新建它们,下同。
2) 添加 home/templates/home.html
{% load static %}
Home Page
console.log("Home Page");
$(document).ready(function() {
changeType();
$("#os_type").change(function(e) {
changeType();
});
$("#cmd_type").change(function(e) {
changeType();
});
});
function changeType() {
var osType = $("#os_type").val();
var cmdType = $("#cmd_type").val();
var cmdStrNode = $("#cmd_str");
if (osType == "windows") {
if (cmdType == "system_cmd_shell") {
cmdStrNode.val("dir C:\\");
cmdStrNode.removeAttr("disabled");
} else if (cmdType == "django_cmd_shell") {
cmdStrNode.val("DirCommand C:\\");
cmdStrNode.attr("disabled", "disabled");
} else {
}
} else if (osType == "ubuntu") {
if (cmdType == "system_cmd_shell") {
cmdStrNode.val("dir /");
cmdStrNode.removeAttr("disabled");
} else if (cmdType == "django_cmd_shell") {
cmdStrNode.val("DirCommand /");
cmdStrNode.attr("disabled", "disabled");
} else {
}
} else {
}
}
function execCmd() {
var cmdType = $("#cmd_type").val();
var cmdStr = $("#cmd_str").val();
if (cmdStr == '') {
alert("Please enter command or shell");
$("#cmd_str").focus();
return;
}
var node = $("#cmd_result");
node.html("Executing command or shell ... ");
$.ajax({
type: 'POST',
url: "{% url 'exec_cmd' %}",
data: {
cmd_type: cmdType,
cmd_str: cmdStr,
csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
},
success: function(response) {
console.log(response);
if (response.ret == 'success') {
node.html(response.data);
} else if (response.ret == 'error') {
node.html(response.description);
} else {
node.html("Unknow error");
}
},
error: function(err) {
console.log(err);
node.html("Network error");
},
});
}
5. 视图和路由
1) 添加 home/utils.py
import subprocess
def systemExecuteLines(rsyncStr, shell=True, b_print=True):
#print(rsyncStr)
p = subprocess.Popen(rsyncStr, shell=shell, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
return out.decode("gbk", "ignore").splitlines(), err.decode("gbk", "ignore").splitlines()
def systemExecute(rsyncStr, shell=True, b_print=True):
#print(rsyncStr)
p = subprocess.Popen(rsyncStr, shell=shell, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
return out.decode("gbk", "ignore"), err.decode("gbk", "ignore")
* 显示中文时需要 decode 设置为 gbk
2) 修改 home/views.py
from django.shortcuts import render, HttpResponse
from django.http import JsonResponse
from home.utils import systemExecuteLines
# Create your views here.
def home(request):
return render(request, "home.html")
def exec_cmd(request):
if request.method == "POST":
cmdType = request.POST.get("cmd_type", "")
cmdStr = request.POST.get("cmd_str", "")
print(cmdType)
print(cmdStr)
if cmdType == "system_cmd_shell":
data,err = systemExecuteLines(cmdStr)
if err:
result = {"ret": "error", "description": err}
else:
result = {"ret": "success", "data": data}
elif cmdType == "django_cmd_shell":
data,err = systemExecuteLines("python manage.py " + cmdStr)
if err:
result = {"ret": "error", "description": err}
else:
result = {"ret": "success", "data": data}
else:
result = {"ret": "error", "description": "Invalid cmd type"}
return JsonResponse(result)
3) 修改 djangoShellDemo/urls.py
from django.contrib import admin
from django.urls import path, include
from home import views
urlpatterns = [
path('', views.home, name='home'),
path('exec/cmd/', views.exec_cmd, name='exec_cmd'),
...
]
6. Django 自定义命令
1) 添加 home/management/commands/DirCommand.py
from django.core.management.base import BaseCommand
from home.utils import systemExecute
class Command(BaseCommand):
help = "Run 'dir' command on Windows or Linux."
def add_arguments(self, parser):
parser.add_argument("path")
def handle(self, *args, **options):
data,err = systemExecute("dir " + options["path"])
if err:
print(err)
else:
print(data)
2) 命令行方式运行 DirCommand
> python manage.py DirCommand c:\ # On Windows
Volume in drive C is WINDOWS
Volume Serial Number is D46B-07AC
Directory of c:\
2021/12/28 10:57
2021/12/28 13:50
2021/12/20 12:15
2021/12/29 11:26
2022/01/05 18:18
0 File(s) 0 bytes
...
$ python manage.py DirCommand / # On Ubuntu
bin dev root usr etc lib mnt var
home lib64 opt sbin sys cdrom
...
7. 运行
> python manage.py runserver
访问 http://localhost:8000/
运行系统命令或脚本,请输入短时内返回结果的命令,比如 ubuntu 下的 ls -la /
> python manage.py runserver 192.168.0.5:8080
访问 http://192.168.0.5:8080/
本实例支持短时内返回结果的命令,长时运行(阻塞式)的命令和脚本,需要使用 Websocket 来实现。下篇文章实现 Websocket 方式运行系统命令。