我有一个用 编写的遗留 Perl CGI 脚本CGI.pm
,它通过 CGI 界面打印一些文本行来回复其进度。然后,它的旧客户端将逐行读取响应并执行任何操作。
由于缓冲问题,我无法设置 nginx 使其工作。
我的设置:
- CentOS 7 + EPEL
yum install fcgi fcgi-devel spawn-fcgi
fcgiwrap
最近需要一个补丁来支持NO_BUFFERING
环境变量,以关闭缓冲。这在 ServerFault的这个答案中有所描述。然而,令人费解的是:已配置
span-fcgi
,这是\etc\sysconfig\spawn-fcgi
:
OPTIONS="-u nginx -g nginx -a 127.0.0.1 -p 9001 -P /var/run/spawn-fcgi.pid -- /usr/local/sbin/fcgiwrap -f"
nginx
为 fastcgi配置:
location ~ .cgi$ {
fastcgi_pass 127.0.0.1:9001;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_request_buffering off;
fastcgi_read_timeout 900s;
fastcgi_param NO_BUFFERING 1;
gzip off;
include /etc/nginx/fastcgi_params;
}
其他信息:
- perl 脚本就是
$| = 1;
这样做的,因为脚本本身不应该缓冲自己的输出。 - perl 脚本还发送HTTP 标头,这通常被称为禁用 nginx 缓冲所必需的,尽管在配置文件中
X-Accel-Buffering: no
不应该需要它。fastcgi_buffering off
- 通过使用
netcat
(nc -l 9001 > request.txt
) 监听 9001 端口,我检查了nginx
是否正确传递NO_BUFFERING
了请求中的变量以及所有其他参数。 - 通过这样做
cat request.txt | nc localhost 9001
,我看到fcgiwrap
了缓冲输出的原因:如果我在中途终止了生成的 cgi 进程,我将获得在那之前生成的所有输出。 - CGI 脚本已启动并且工作正常,否则只是客户端没有逐行接收数据(但我需要
fastcgi_read_timeout 900s
上面的行以避免超时)。 - 我不确定我是否完全理解
fcgiwrap
源代码,但补丁很简单:如果设置了环境变量,它只会FCGI_fflush
在每次写入后调用。NO_BUFFERING
但是,可以肯定的是,我替换unbuffered = !!getenv("NO_BUFFERING");
为unbuffered = 1;
,但没有成功。
那么有人能发现我错过了什么吗?