【发布时间】:2021-07-14 04:31:04
【问题描述】:
我无法让 Python CGI 脚本在虚拟 Ubuntu 18 服务器上运行的 apache2 网络服务器上正确执行。托管服务提供商是 DreamCompute,如果这很重要的话。我得到了在var/www/html/apps/cgi-bin/ 下工作的 CGI 脚本。 helloworld.py 和 helloworld.pl 在 SSH 终端和浏览器 (Microsoft Edge) 中都能正常执行。
给我带来麻烦的脚本是一个 Python 脚本,它访问 MySQL 数据库,从中读取数据,然后使用该数据填充一些列表并随机生成一些简单的输出(桌面 RPG 具有随机效果的魔法咒语) .
拼写生成器脚本在 SSH 中也可以正常执行,但是当我尝试在浏览器中查看它时会引发 500 内部服务器错误。 apache 错误日志告诉我问题是end of script output before headers。我环顾四周,但找不到任何有类似问题和配置的人。
编辑:错误日志中的完整条目是:
[Tue Apr 20 00:20:25.324101 2021] [cgid:error] [pid 17275:tid 140105176721152] [client 2607:fea8:1d41:b800:7dca:305:b11a:447f:62505] End of script output before headers: spell_generator.py, referer: http://my.website/apps/cgi-bin/
在添加和删除部分 Python 脚本以查看它在浏览器中的行为之后,我相信我已经隔离了问题:连接到 MySQL 数据库的脚本部分。该数据库也托管在同一个 Ubuntu 虚拟机上,其中肯定包含正确类型的数据(只是字符串和 ID;没什么特别的)。
这是 Python 代码。我已经删除了一些文档 cmets,但它应该非常简单:
#!/usr/bin/python3
print("Content-type: text/html\n\n");
# The above two lines are boilerplate to ensure no print statements cause
# problems later in the program.
# Import statements
import cgi
import cgitb
cgitb.enable();
from random import choice
import mysql.connector
import sys
from enum import Enum
# Initialize enums for system comparison
class Ruleset(Enum):
GENERIC = "GENERIC"
GENERIC_DB = "generic_attributes"
DND_5 = "DND5e"
DND_5_DB = "dnd5e_attributes"
PATHFINDER_1 = "PF1e"
PATHFINDER_1_DB = "pathfinder1e_attributes"
# Determine what system to use, generic by default
spellSystem = Ruleset.GENERIC.value;
if (len(sys.argv)) > 1:
if (sys.argv[1] == Ruleset.DND_5.value):
spellSystem = Ruleset.DND_5.value;
if (sys.argv[1] == Ruleset.PATHFINDER_1.value):
spellSystem = Ruleset.PATHFINDER_1.value;
# === PROBLEM HERE ===
# Initialize SQL cursor, defaulting to generic
if spellSystem == Ruleset.DND_5.value:
spellDB = mysql.connector.connect(
host = "localhost",
user = "RemoteUser",
password = "password",
database = Ruleset.DND_5_DB.value
)
elif spellSystem == Ruleset.PATHFINDER_1.value:
spellDB = mysql.connector.connect(
host = "localhost",
user = "RemoteUser",
password = "password",
database = Ruleset.PATHFINDER_1_DB.value
)
else:
spellDB = mysql.connector.connect(
host = "localhost",
user = "RemoteUser",
password = "password",
database = Ruleset.GENERIC_DB.value
)
spellCursor = spellDB.cursor();
spellCursor.execute("SELECT ElementName FROM Element");
listHolder = spellCursor.fetchall();
# === CODE BELOW DOES NOT CAUSE PROBLEMS ===
#
# [logic that uses the SQL data]
#
# Output HTML page
print("<html> <head> <title>TEST - Magic Spell Generator</title> <link rel='stylesheet' href='../../css/style.css'> </head>");
print("<body> body contents");
print("</body>");
print("</html>");
RemoteUser 是 SQL 服务器上的用户帐户,“外部”(非根)程序使用它来访问数据库。实际部署的脚本中的password 是加密安全密码。
我不是 Python 专家,但是当我从 SSH 终端执行代码时,代码运行没有问题,所以我不认为糟糕的代码是罪魁祸首(尽管我肯定是错的)。这是我已经尝试过的事情的列表:
- 检查是否有太多活动 SQL 连接(似乎只有一个,即 root 用户)。
- 确保脚本文件具有正确的权限(
chmod 755,与其他文件相同)。 - 确保已安装必要的 Python 模块(它们已安装,并且 Python-MySQL 连接器是与我正在使用的 Python 版本配合使用的最新版本)。
- 正在重新启动 apache2。
我今天大部分时间都在寻找答案。欢迎任何帮助或潜在线索。
【问题讨论】:
-
apache 错误日志应该说明的不仅仅是您在问题中引用的内容,还应该指出潜在的错误。没有它,我们只能猜测。
-
@Shadow 我编辑了帖子以显示完整的错误日志条目。可以的话就看看吧。