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

如何在IIS部署调用subprocess执行PowerShell命令的Flask应用

Flask应用IIS部署问题排查与解决

问题概述

该Flask应用通过Web界面接收用户输入的主机名,调用testssl.sh脚本执行安全扫描,通过subprocess模块调用PowerShell执行命令序列。开发环境(localhost:5000)运行正常,但部署到Microsoft IIS后出现两类问题:

  • 使用HttpPlatformHandler部署时,应用无法正常启动,日志提示「系统找不到指定路径」(开发环境无此问题)。
  • 使用FastCGIHandler部署时,出现Stack Overflow相关帖子提及的错误,即使按帖子方案修改后仍无法工作,日志仅记录wfastcgi.py的启动与关闭信息。

Flask应用代码

from flask import Flask, render_template, request, jsonify, url_for, send_file
import subprocess
import os
import datetime

onlytime = datetime.datetime.now().strftime("%H%M")
app = Flask(__name__)  # Flask应用实例名称


@app.route("/")  # 默认路由
def index():
    return render_template("Internal_Scanner.html")


@app.route(
    "/scan", methods=["POST"]
)  # 网页点击「开始扫描」按钮触发的路由
def scan():
    # 从表单获取主机名参数
    hostname = request.form.get("hostname")
    if len(hostname) > 50:
        return jsonify({"return_output": "主机名过长,请输入50字符以内的内容。"})
    elif hostname.find(" ") != -1:
        return jsonify(
            {
                "return_output": "输入的主机名包含空格,格式无效。"
            }
        )
    else:
        # 根据主机名格式生成报告文件名
        if hostname.find(":") == -1:
            htmlfilename = "{}_{}.html".format(hostname, onlytime)
        else:
            htmlfilename = "{}_{}.html".format((hostname.split(":"))[0], onlytime)
        
        # 构造PowerShell执行命令序列
        comm = "cd ..; cd .\Ubuntu\Ubuntu_2004.2021.825.0_x64\; .\ubuntu.exe run 'cd ..; cd ..; cd testssl.sh-3.1dev/; ./testssl.sh --htmlfile ../scanner/reports/scans/{} {}'" .format(htmlfilename, hostname)

        subprocess.run(['powershell.exe','-Command',comm], shell=True)
        return_output = f"主机名 {hostname} 扫描完成。"
        download_link = f"/api/download/{htmlfilename}"
        return jsonify(return_output=return_output, download_link=download_link)


@app.route(
    "/api/download/<string:filename>", methods=["GET"]
)  # 扫描报告下载路由
def download_report(filename):
    # 从指定目录读取报告文件
    file_path = os.path.join(r"C:\inetpub\wwwroot\scanner\reports\scans", filename)
    if os.path.isfile(file_path):
        return send_file(file_path, as_attachment=True)
    else:
        return jsonify({"error": "文件未找到,请确认扫描已完成。"})

if __name__ == "__main__":
    app.run()

HttpPlatformHandler 配置文件(web.config)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpPlatform processPath="C:\Users\PRATEEK\AppData\Local\Programs\Python\Python311\python.exe" arguments="-m flask run --port %HTTP_PLATFORM_PORT%" stdoutLogEnabled="true" stdoutLogFile="C:\inetpub\wwwroot\scanner\logs\app.log" />
        <handlers>
            <add name="HphHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
        </handlers>
    </system.webServer>
</configuration>

FastCGIHandler 配置文件(web.config)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <add name="ScannerFCGIPowershellHandler" path="C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" verb="*" modules="CgiModule" scriptProcessor="C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" resourceType="Unspecified" requireAccess="Execute" />
            <add name="ScannerFCGI" path="*" verb="*" modules="FastCgiModule" scriptProcessor="C:\inetpub\wwwroot\scanner\env\Scripts\python.exe|C:\inetpub\wwwroot\scanner\env\Lib\site-packages\wfastcgi.py" resourceType="Unspecified" requireAccess="Script" />
        </handlers>
    </system.webServer>
    <appSettings>
        <add key="WSGI_HANDLER" value="app.app" /> <!-- {文件名}.{Flask应用实例名}-->
        <add key="PYTHONPATH" value="C:\inetpub\wwwroot\scanner" />
        <add key="WSGI_LOG" value="C:\inetpub\wwwroot\scanner\logs\app.log" />
    </appSettings>
</configuration>

问题解决方案

1. HttpPlatformHandler「系统找不到指定路径」问题

核心原因

  • IIS应用池默认用户(IIS AppPool\<应用池名称>)无权限访问用户目录下的Python程序,或相对路径解析与开发环境不一致。
  • 命令中使用cd ..等相对路径,IIS部署时的工作目录与本地开发环境不同,导致路径跳转失败。

修复步骤

  • 迁移Python到公共路径:将Python安装到公共目录(如C:\Python311),并给IIS AppPool\<应用池名称>账户分配该目录的读取、执行权限。
  • 指定工作目录:在httpPlatform节点添加workingDirectory属性,固定应用根目录:
    <httpPlatform processPath="C:\Python311\python.exe" 
                  arguments="-m flask run --port %HTTP_PLATFORM_PORT%" 
                  stdoutLogEnabled="true" 
                  stdoutLogFile="C:\inetpub\wwwroot\scanner\logs\app.log"
                  workingDirectory="C:\inetpub\wwwroot\scanner" />
    
  • 替换相对路径为绝对路径:修改comm变量中的路径为绝对路径,避免工作目录差异导致的错误:
    comm = "cd C:\path\to\Ubuntu\Ubuntu_2004.2021.825.0_x64; .\ubuntu.exe run 'cd /absolute/path/to/testssl.sh-3.1dev/; ./testssl.sh --htmlfile /absolute/path/to/scanner/reports/scans/{} {}'" .format(htmlfilename, hostname)
    
  • 配置目录权限:给C:\inetpub\wwwroot\scanner、Ubuntu安装目录及testssl.sh目录添加IIS AppPool\<应用池名称>的读取、执行权限。

2. FastCGIHandler部署后无有效日志且无法工作问题

核心原因

  • 额外添加的PowerShell CGI Handler导致请求路由冲突,干扰Flask应用的请求处理。
  • wfastcgi日志未记录详细错误,且subprocess调用未捕获异常,无法定位问题。
  • IIS应用池用户权限不足,无法调用PowerShell或访问扫描相关路径。

修复步骤

  • 移除多余的CGI Handler:删除web.config中的ScannerFCGIPowershellHandler节点,避免路由干扰。
  • 添加异常捕获与日志:修改subprocess调用代码,捕获执行错误并返回详细信息:
    try:
        result = subprocess.run(['powershell.exe','-Command',comm], shell=True, check=True, capture_output=True, text=True)
    except subprocess.CalledProcessError as e:
        return jsonify({"return_output": f"扫描失败:{e.stderr}"})
    
  • 提升应用池权限:将应用池身份改为本地系统账户,或具有足够权限的专用服务账户,确保该账户能访问PowerShell、Python、Ubuntu及testssl.sh的所有相关路径。
  • 验证FastCGI配置:确认scriptProcessor中的Python和wfastcgi.py路径完全正确,且应用池用户对这些文件有读取权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 23:12:49