You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django应用如何在网页展示远程SSH命令执行结果?

问题描述

我有一个简单的Django应用,用于展示远程SSH命令的执行结果。相关代码如下:

views.py

from django.http import HttpResponse
from subprocess import *

def index(request):
    with open('/home/python/django/cron/sites.txt', 'r') as file:
        for site in file:
            # out = getoutput(f"ssh -o StrictHostKeyChecking=accept-new -p1994 root@{site} crontab -l")
            out = run(["ssh", "-o StrictHostKeyChecking=accept-new", "-p1994", f"root@{site}".strip(), "crontab", "-l"])
    return HttpResponse(out)

urls.py

from django.contrib import admin
from django.urls import path
# imported views
from cron import views

urlpatterns = [
    path('admin/', admin.site.urls),
    # configured the url
    path('',views.index, name="homepage")
]

sites.txt

1.1.1.1
2.2.2.2
3.3.3.3

访问localhost:5000时,页面仅显示CompletedProcess对象信息,而非预期的crontab命令执行结果。尝试过run和getoutput方法,但要么无法建立连接,要么输出仅显示在终端中。如何实现并在网页中展示正确的执行结果?


解决方案

核心问题分析

  1. subprocess.run()默认不捕获命令输出,返回的是CompletedProcess对象,直接返回给HttpResponse会显示对象的字符串表示,而非命令结果。
  2. 循环中每次迭代都会覆盖out变量,最终仅返回最后一台主机的结果。
  3. SSH连接可能因为缺少免密配置导致交互阻塞,或输出未被正确捕获。

修改后的代码实现

推荐使用subprocess.run()并显式捕获输出,同时收集所有主机的结果:

from django.http import HttpResponse
from subprocess import run, PIPE

def index(request):
    results = []
    with open('/home/python/django/cron/sites.txt', 'r') as file:
        for site in file:
            site = site.strip()
            if not site:
                continue  # 跳过空行,避免无效连接
            
            # 执行SSH命令,捕获标准输出与错误
            cmd_result = run(
                ["ssh", "-o", "StrictHostKeyChecking=accept-new", "-p1994", f"root@{site}", "crontab", "-l"],
                stdout=PIPE,
                stderr=PIPE,
                text=True  # 让输出以字符串形式返回,而非字节流
            )
            
            # 整理单台主机的结果内容
            host_content = f"<h3>主机 {site} 的Crontab信息</h3>"
            if cmd_result.returncode == 0:
                host_content += f"<pre>{cmd_result.stdout}</pre>"
            else:
                host_content += f"<p style='color:red;'>执行失败:{cmd_result.stderr}</p>"
            
            results.append(host_content)
    
    # 将所有结果拼接为HTML返回,确保页面展示清晰
    return HttpResponse("<br>".join(results))

关键修改点说明

  • 用results列表存储每台主机的结果,避免循环覆盖问题。
  • 通过stdout=PIPE和stderr=PIPE捕获命令的输出与错误信息,text=True简化字节流转字符串的操作。
  • 根据命令返回码判断执行状态,成功时展示Crontab内容,失败时显示错误信息,用HTML标签优化页面可读性。
  • 跳过文件中的空行,避免无效的SSH连接尝试。

可选:使用getoutput的简化实现

如果不需要判断命令执行状态,可使用getoutput(它会合并标准输出与错误):

from django.http import HttpResponse
from subprocess import getoutput

def index(request):
    results = []
    with open('/home/python/django/cron/sites.txt', 'r') as file:
        for site in file:
            site = site.strip()
            if not site:
                continue
            output = getoutput(f"ssh -o StrictHostKeyChecking=accept-new -p1994 root@{site} crontab -l")
            results.append(f"<h3>主机 {site}</h3><pre>{output}</pre>")
    return HttpResponse("<br>".join(results))

必做的前置配置

确保运行Django的用户(如服务器的www-data或本地登录用户)已配置免密SSH登录到所有远程主机,否则SSH会要求输入密码导致命令阻塞。配置命令示例:

ssh-copy-id -p1994 root@1.1.1.1

内容的提问来源于stack exchange,提问作者Saeed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 04:12:27