我继承了自编写的CGI应用程序的维护 文档,从未见过原作者。应用程序 停止在Debian 8工作,但在Debian 7和CentOS 5工作 主要的变化是从Apache 2.2升级(Debian 7& CentOS 5)到Apache 2.4(由Debian 8使用)和从perl升级 5.8(在CentOS 5中)分别为perl 5.14(在Debian 7中)到perl 5.20。 有问题的部分归结为以下脚本(a 302重定向):
#!/usr/bin/perl
$|=1; # activate auto-flushing of stdout
use strict;
use warnings;
my $CRLF = "\015\012";
print STDOUT "Status: 302 Moved Temporarily$CRLF" .
"Location: /does_not_matter$CRLF" .
"URI: /does_not_matter$CRLF" .
"Connection: close$CRLF" .
"Content-type: text/html; charset=UTF-8$CRLF$CRLF";
close STDOUT;
while(1) {
sleep 1;
}
观察到的行为是重定向永远不会到达客户端
只要脚本仍在运行与Apache 2.4一起使用,但是
Apache的error.log中没有错误消息。我改变了客户端
(Firefox,Chromium,wget),Apache模块(mod_cgid& mod_cgi),
发送了其他标头,删除了close STDOUT
,删除了
$|=1
,将$CRLF
替换为\n
并制作了脚本
fork并退出父进程(以便Apache不再是
父进程),一切都无济于事。唯一有效的方法:使用
Apache 2.2,将脚本转换为NPH-CGI脚本(必须发送
完整的HTTP标头,Apache不会以任何方式修改,即使
它们包含错误),使脚本退出而不是输入
无尽的循环。我通过tcpdump确认了包的
在脚本被杀死之前,重定向确实永远不会离开服务器。
并从响应中的日期行和最终的时间
到达我收集Apache立即收到我的输出(&
立即将日期行添加到标题中,但不发送
回应客户。
不要回答,我已经自己解决了解决方案 并会写一个答案。我只想提供解决方案 对可能遇到同样问题的其他人。
答案 0 :(得分:1)
问题是缺少邮件正文。 302重定向可能包含
消息体(参见RFC 2616,第4.3节(消息体):"所有其他
响应确实包含一个消息体,尽管它可能为零
长度"),但Content-Length-line是可选的(RFC的第4.4节)
2616表示消息体长度可以通过关闭来确定
连接如果缺少Content-Length-line)。既然Apache可以
不知道我是否要发送邮件正文,它必须等待
直到我关闭连接或实际发送邮件正文
(Apache 2.2显然在这里错误地表现为不等待
邮件正文 - 或者close STDOUT;
在perl中没有
5.20它在旧的perl版本中做了什么)。正确的脚本应该
因此看起来像这样(经过验证可以在Apache 2.2和
Apache 2.4) - 唯一的区别是额外的$CRLF
终止零长度的消息体:
#!/usr/bin/perl
$|=1; # activate auto-flushing of stdout
use strict;
use warnings;
my $CRLF = "\015\012";
print STDOUT "Status: 302 Moved Temporarily$CRLF" .
"Location: /doesNotMatter$CRLF" .
"URI: /doesNotMatter$CRLF" .
"Connection: close$CRLF" .
"Content-type: text/html; charset=UTF-8$CRLF$CRLF$CRLF";
close STDOUT;
while(1) {
sleep 1;
}