0

我见过很多类似的问题,但我仍然失败了。我有 win XP、Apache 2.2、Django 1.4、Python 2.7 和 mod_wsgi 3.3。我要做的就是当您点击 bat 文件执行的页面并回显 hi。这在我在 django 内部开发服务器上运行时有效。但是当我到达 Apache 时,它​​失败了,并且在 error.log 中我收到了消息

系统无法写入指定的设备。
系统无法写入指定的设备。
系统无法写入指定的设备。
系统无法写入指定的设备。
系统无法写入指定的设备。

我在其他许多地方都没有看到这个错误。大多数人似乎得到“权限被拒绝”。我仍然认为权限是错误的。所以当我运行它是我在控制台中得到的 django 内部服务器:

验证模型...


使用设置 'testsite.settings'发现 0 个错误Django 版本 1.4
开发服务器正在 http://127.0.0.1:8000/ 上运行
使用 CTRL-BREAK 退出服务器。

C:\Sites\cprm>echo hi
hi
[18/Sep/2012 14:58:45] "GET / HTTP/1.1" 200 63

这似乎很好。唯一让我失望的是我是从 /testsite 而不是 /cprm 运行的。我可以 cd .. 之前。无论如何,因为在内部服务器中它正在写入控制台,我想我需要在 apache 中做同样的事情。我不确定 apache 控制台在哪里。我尝试向 apache 日志文件添加权限,因为这是生成错误的地方。我不确定这是否等同于常规控制台。

我的 Apache 文件如下所示(忽略反引号):

<`VirtualHost *>

ServerName http://example.com:80

WSGIScriptAlias /cprm "C:/sites/cprm/wsgi.py"
WSGIScriptAlias /testsite "C:/sites/testsite/wsgi.py"

<Directory "C:/sites">
        AllowOverride None
        Options None
        Order allow,deny
        Allow from all
</Directory>

<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/logs">
        AllowOverride None
        Options None
        Order allow,deny
        Allow from all
</Directory>

<`/VirtualHost>

我的观点看起来像这样:

from django.http import HttpResponse
import datetime, os

def home(request):
    os.system('C:/Sites/testsite/testsite/test.bat')
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

这基本上只是我尝试做的一个快速测试。


编辑

嗨,帕查。感谢您的回复。我现在已经阅读了一些关于这个主题的内容。所以我做了你指出的改变。我的 wsgi.py 文件如下所示:

导入操作系统、系统

path = 'C:/Sites/testsite'

如果路径不在 sys.path:
sys.path.append(path)


os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testsite.settings")
sys.stdout = sys.stderr
print 'hi'
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

然后,当我转到 error.log 时,我确实看到打印了“hi”。所以这很好。但是,带有 echo hello 的 test.bat 文件没有执行,我仍然收到相同的消息。并感谢您的许可建议。我现在不再使用虚拟。我还没有准备好。关于我可以尝试的任何其他想法?

4

2 回答 2

0

您的问题似乎与标准输出的处理方式有关。WSGI 默认禁用标准输出。这就是为什么您的程序在开发服务器中运行良好(它将输出重定向到启动服务器的终端)但不适用于 Apache。

您可以使用放入虚拟主机 conf 文件中的配置指令(与其他 WSGI 指令一起)在 WSGI 中启用标准输出:

WSGIRestrictStdout Off

但是,请考虑到 Apache 没有与任何终端关联。如果您想查看程序的输出,那么您可以做的一件事是将标准输出重定向到标准错误流,方法是将其添加到您的 WSGI 文件中:

sys.stdout = sys.stderr

重新启动 Apache,您应该会在 Apache 的 error.log 文件中看到应用程序的任何输出(或任何子进程,如您的情况)。

注意:不要将 Apache 日志文件目录添加到您的虚拟主机配置中。您没有授予 Apache 对这些文件的权限,而是允许任何人查看它们,这是您可以想象的不小的安全风险。


更新

避免权限问题

您可能想尝试在守护程序模式下使用 WSGI。这样,Web 应用程序就可以在您的用户名下执行(很像使用内部开发服务器时)。在您的情况下,配置指令应该是这样的:

WSGIDaemonProcess site1 user=<USERNAME> group=<GROUP> processes=1 threads=1
WSGIScriptAlias /testsite "C:/sites/testsite/wsgi.py"

<Directory "C:/sites/testsite/">
    WSGIProcessGroup site1
    WSGIApplicationGroup %{GLOBAL}
    Order allow,deny
    Allow from all
</Directory>

您必须在您的 Windows 机器中用您的用户名和组进行替换(尽管它可能只通过设置用户名来工作)<USERNAME><GROUP>这通常是避免权限问题的好方法,因为您的应用程序将以与开发服务器执行的方式非常相似的方式执行。(请注意,我们只使用一个进程和一个线程只是为了使 Apache 的行为更加接近开发服务器的行为。您肯定希望在生产中将这些值更改为更高的值)。

您可以在此处查看守护程序模式文档

执行你的脚本

要从 Python 代码调用外部程序,模块subprocess通常优于os.system调用。前者允许您更好地控制新进程的执行方式,而后者只是将调用传递给操作系统。

你可以试试这个subprocess.check_output功能。它执行脚本/程序并允许您捕获其输出:

print subprocess.check_output(['C:\Sites\testsite\testsite\test.bat'], shell=True)

它还有一个额外的优势,即您可以在字符串变量中捕获输出。(顺便说一句,在调用 bat 脚本时,您可能需要也可能不需要shell=TrueWindows 中的参数,我不确定)。

于 2012-09-18T23:25:52.457 回答
0

检查事项

  1. 权限 文件 C:/Sites/testsite/testsite/test.bat 的用户权限是什么?

它们是为运行 Apache 进程的同一用户读取的吗?

  1. 您是否为所有登录用户安装了 python,而不仅仅是为了?

  2. 您是否查看过您的 Apache conf 指令?用户/组:运行 httpd 的用户/组的名称(或#number)。与大多数系统服务一样,创建一个专门的用户和组来运行 httpd 通常是一种很好的做法。

    用户 carlos 组管理员

同一用户是否有权读取文件系统上的文件?

<Directory "C:/Sites/testsite/testsite/">
    AllowOverride None
    Options None
    Order deny,allow
   Allow from all
</Directory>
于 2012-09-21T01:38:24.957 回答