使用Apache显示长时间运行的shell进程

时间:2010-08-23 12:26:09

标签: apache http shell cgi

我有一个CGI脚本,大约需要1分钟才能运行。现在Apache只在进程完成后才将结果返回给浏览器。

如何让它显示输出,就像它在终端上运行一样?

这是展示问题的example

我希望看到数字1到5在打印时出现。

2 个答案:

答案 0 :(得分:6)

我不得不禁用mod_deflate以使块模式与apache一起使用

我没有找到另一种方法让我的cgi禁用gzip的自动编码。

答案 1 :(得分:3)

这里有几个因素在起作用。为了消除一些问题,Apache和bash不会缓冲任何输出。您可以使用此脚本进行验证:

#!/bin/sh

cat <<END
Content-Type: text/plain

END

for i in $(seq 1 10)
do
    echo $i
    sleep 1
done

坚持将Apache配置为执行CGI脚本,并使用netcat进行测试:

$ nc localhost 80
GET /cgi-bin/chunkit.cgi HTTP/1.1
Host: localhost

HTTP/1.1 200 OK
Date: Tue, 24 Aug 2010 23:26:24 GMT
Server: Apache/2.2.14 (Unix) mod_ssl/2.2.14 OpenSSL/0.9.7l DAV/2
Transfer-Encoding: chunked
Content-Type: text/plain

2
1

2
2

2
3

2
4

2
5

2
6

2
7

2
8

2
9

3
10

0

当我这样做时,我在netcat中看到每个数字每秒出现一次,如预期的那样。

请注意,我的Apache版本至少会自动应用分块传输编码,大概是因为我没有包含Content-Length;如果您自己返回Transfer-Encoding: chunked标题,则需要在分块传输编码中对脚本的输出进行编码。即使在shell脚本中,这也很简单:

chunk () {
    printf '%x\r\n' "${#1}"  # Length of the chunk in hex, CRLF
    printf '%s\r\n' "$1"     # Chunk itself, CRLF
}

chunk $'1\n' # This is a Bash-ism, since it's pretty hard to get a newline
chunk $'2\n' # character portably.

但是,将此服务提供给浏览器,您将根据浏览器获得不同的结果。在我的系统Mac OS X 10.5.8上,我看到浏览器之间存在不同的行为。在Safari,Chrome和Firefox 4测试版中,在我发送大约1000个字符之前我没有开始看到输出(我猜想1024包括标题,或类似的东西,但我没有缩小到确切的行为)。在Firefox 3.6中,它立即开始显示。

我猜这个延迟是由content type sniffingcharacter encoding sniffing引起的,它们正处于标准化过程中。我试图通过指定正确的内容类型和字符编码来确定是否可以解决延迟,但没有运气。您可能必须发送一些填充数据(如果您使用HTML而不是纯文本,这将非常容易隐藏),以超越该初始缓冲区。

一旦开始流式传输HTML而不是纯文本,HTML的结构也很重要。有些内容可以逐步显示,有些则不能。例如,将<div>向下流入正文,没有样式,工作正常,并且可以在到达时逐步显示。如果您尝试打开<pre>标记,并将内容流式传输到该标记中,基于Webkit的浏览器将等到他们看到close标记以尝试解决该问题,而Firefox很乐意逐步显示它。我不知道所有的角落案件;你必须尝试看看哪些对你有用。

无论如何,我希望这可以帮助你开始。如果您还有其他问题,请与我们联系!