将CGI错误输出从STDERR重定向到文件(python和perl)

将CGI错误输出从STDERR重定向到文件(python和perl),python,perl,cgi,stderr,hostmonster,Python,Perl,Cgi,Stderr,Hostmonster,我正在将一个网站移动到Hostmonster,并询问服务器日志的位置,以便我可以自动扫描它的CGI错误。有人告诉我,“很抱歉,我们没有cgi错误,请转到您可以访问的任何文件。” 出于组织上的原因,我一直使用Hostmonster和这个糟糕的策略,因此作为一种解决方法,我想也许我应该修改CGI脚本,将STDERR重定向到一个自定义日志文件 我有很多脚本(269),所以我需要用Python和Perl的简单方法将STDERR重定向到自定义日志文件 可以显式或隐式地解释文件锁定,因为理论上,如果多个脚本

我正在将一个网站移动到Hostmonster,并询问服务器日志的位置,以便我可以自动扫描它的CGI错误。有人告诉我,“很抱歉,我们没有cgi错误,请转到您可以访问的任何文件。”

出于组织上的原因,我一直使用Hostmonster和这个糟糕的策略,因此作为一种解决方法,我想也许我应该修改CGI脚本,将STDERR重定向到一个自定义日志文件

我有很多脚本(269),所以我需要用Python和Perl的简单方法将STDERR重定向到自定义日志文件

可以显式或隐式地解释文件锁定,因为理论上,如果多个脚本同时失败,共享CGI错误日志文件可以由多个脚本同时写入

(我想使用共享的错误日志,这样我可以每晚通过电子邮件将其内容发送给自己,然后将其存档或删除。)

我知道我可能必须修改每个文件(grrr),这就是为什么我要寻找一些优雅的东西,只需要几行代码。谢谢。

Python:。在脚本顶部,在其他导入之前:

import cgitb
cgitb.enable(False, '/home/me/www/myapp/logs/errors')
('errors'是web服务器用户有写访问权的目录。)

在Perl中,请尝试


对于Perl,只需关闭并重新打开
STDERR
,指向您选择的文件

close STDERR;
open STDERR, '>>', '/path/to/your/log.txt' 
  or die "Couldn't redirect STDERR: $!";

warn "this will go to log.txt";

或者,您也可以查看文件句柄多路复用器,例如。

Python具有您可能想要查看的sys.stderr模块

>>>help(sys.__stderr__.read)
Help on built-in function read:

read(...)
    read([size]) -> read at most size bytes, returned as a string.

    If the size argument is negative or omitted, read until EOF is reached.
    Notice that when in non-blocking mode, less data than what was requested
    may be returned, even if no size parameter was given.
您可以将其输出存储在字符串中,然后将该字符串写入文件

希望这对python有所帮助:

import sys

sys.stderr = open('file_path_with_write_permission/filename', 'a')

在我的Perl CGI程序中,我通常

BEGIN {
  open(STDERR,'>>','stderr.log');
}

就在shebang行和“使用严格;使用警告;”之后。如果需要,可以在文件名中附加$0。但这并不能解决多个程序的问题,因为一个程序的多个副本可能同时运行。对于每个程序组,我通常只有几个输出文件。

我最终使用的解决方案与以下类似,位于我所有脚本的顶部:

Perl:

Python:

sys.stderr = open("/path/to/my/cgi-error.log", "a")
find . -type f -name "*.py" -exec perl -pi.bak -e 's%^(import os, sys.*)%$1\nsys.stderr = open("/path/to/my/cgi-error.log", "a")%' {} \;
显然,在Perl中,在重新打开STDERR句柄之前不需要关闭它

通常我会关闭它作为一个最佳实践,但正如我在问题中所说的,我有269个脚本,我正在努力减少更改。(另外,重新打开打开的文件句柄似乎更为完美,听起来很糟糕。)

如果将来有其他人有类似的情况,我将立即更新所有脚本:

Perl:

Python:

sys.stderr = open("/path/to/my/cgi-error.log", "a")
find . -type f -name "*.py" -exec perl -pi.bak -e 's%^(import os, sys.*)%$1\nsys.stderr = open("/path/to/my/cgi-error.log", "a")%' {} \;
我发布这些命令的原因是,我花了大量的语法处理才能让这些命令正常工作(例如,将cannot改为cannot,将#!/usr/bin/perl改为just/usr/bin/perl,这样shell就不会将!解释为历史字符,使用$OS\u ERROR代替$!,等等)


感谢所有发表评论的人。由于没有人同时回答Perl和Python问题,我无法真正“接受”任何一个给定的答案,但我确实投票给了那些引导我走向正确方向的答案。再次感谢

另一个问题是,它们可能也不允许您创建文件。我很确定您可以在您的主页或web(public_html)树中创建文件。我想到的另一个方面是,如果我有269个脚本,并且我要附加到我自己的日志文件中,也许我需要担心自定义日志文件上的文件锁定。我还有一个疯狂的想法,这要么很酷,要么很疯狂。这些脚本都以#开头/usr/bin/python或perl。如果我创建了自己的包装器,比如/home/user/bin/mypython或myperl,该怎么办。然后可以重定向stderr,并将脚本的其余部分传递给“真正的”perl或python。如果这真的是一个好主意(不是一个可怕的主意),我只是不知道“将[cgi]脚本的其余部分传递给真正的perl/python”的机制。(我突然想到,这可能是不可移植的,因为一些主机,甚至可能是Hostmonster,可能不喜欢CGI脚本调用像/home/user/bin/myperl这样奇怪的东西——它们可能会有安全问题,尽管它们本身并不应该)关于许多错误日志/文件锁定的问题:只需在发送电子邮件之前追加或压缩文件->问题已解决?如果您希望日志事件按时间顺序排列,只需编写一个简单的脚本来遍历日志。这非常酷,因为它使用内置模块,不需要更多的代码行。唯一的方法是ng是,似乎每个回溯/错误转储都会写入自己的文件。虽然这很好地解决了文件锁定问题(我在发布问题后想到,使用自定义错误日志,我不得不担心脚本可能同时失败,从而导致文件锁定),我想要一个共享的错误日志文件,我可以定期扫描(并给自己发电子邮件,然后存档)这是一个基本的,可能是愚蠢的问题,但是在那里简单地打开/追加写到STDRR,Perl隐式地处理文件锁定吗?我问,因为在发布这个问题之后,我想到了,理论上用共享的日志文件,我可能必须考虑多个脚本一次失败的可能性。(因此,文件锁定问题)在Unix上,如果您在
O\u APPEND
模式下打开文件,则查找和写入操作以原子方式执行,因此不需要锁定。如果我理解正确,您说的是sys.\u stderr\uuu.read()在发生错误后,是否允许我检索stderr流的内容。但我不需要知道要检索的错误消息的长度,以便获取该信息吗?也许我没有正确理解您的建议。我认为您指的是[size]参数。参数“[]'表示该参数是可选的。如帮助文本所述,如果未指定大小,则它将一直读取,直到达到EOF。我的理解是,如果
find . -type f -name "*.py" -exec perl -pi.bak -e 's%^(import os, sys.*)%$1\nsys.stderr = open("/path/to/my/cgi-error.log", "a")%' {} \;