无法使用 nginx、fastcgi 和 bash 在 cgi 上禁用缓冲
Can't disable buffering on a cgi using nginx, fastcgi and bash
我想制作一个 CGI 来启动程序并在 real-time 中的 web-browser 中显示输出。 Real-time 这里的意思是当程序产生一行输出时,它应该显示在浏览器页面上。
我选择把它写在bash中来包装程序执行,这样我就可以处理请求参数了。
webbrowser -> nginx+fastcgi -> bash -> program
我有一个测试程序,每半秒输出一行,10次。
我想我可以在响应中声明一个纯文本上下文类型 header 然后执行程序。
不幸的是,输出仅在执行结束时一次性出现在浏览器中。我在 Firefox 和 curl 中测试了它。
我已经测试了很多选项和它们的任意组合来解决这个问题:
- 使用
fastcgi_buffering off
指令禁用 nginx 中的缓冲
- 添加
X-Accel-Buffering
header
- 使用
stdbuf -oL program
- 使用 xml http 请求 (XHR) + 服务器端事件 (SSE) 而不是纯文本。
没有任何效果。
我想缓冲问题是在 nginx 和 bash 之间,但我找不到禁用它的方法。
我可以尝试什么?
我找不到解决链中缓冲问题的方法。我尝试了 perl 而不是 bash 但没有运气。
所以我选择填充缓冲区:在受控程序的每一行输出之后,我回显一堆'\0'。由于 Web 浏览器无法将此内容作为纯文本处理,因此我使用服务器发送事件方法。
#!/bin/sh
printf "HTTP/1.0 200 OK\r\n"
printf "Content-type: text/event-stream\r\n"
printf "Cache-Control: no-cache\r\n"
printf "X-Accel-Buffering: no\r\n"
printf "\r\n"
flush() {
padding=4100
dd if=/dev/zero bs=$padding count=1 2>/dev/null
}
subprogram | while read l;
do
printf "data: ${l}\n\n"
flush
done
包装页看起来像这样:
<html>
<head>
<meta charset="UTF-8">
<title>Server-sent events demo</title>
</head>
<body>
<pre></pre>
<script>
var evtSource = new EventSource('/sse.sh?subprogram');
var pre = document.querySelector('pre');
evtSource.onmessage = function(e) {
pre.textContent += e.data + '\n';
}
</script>
</body>
</html>
在这种情况下,Web 浏览器负责删除多余的“\0”。
缺点是cgi输出远大于程序输出
我想制作一个 CGI 来启动程序并在 real-time 中的 web-browser 中显示输出。 Real-time 这里的意思是当程序产生一行输出时,它应该显示在浏览器页面上。
我选择把它写在bash中来包装程序执行,这样我就可以处理请求参数了。
webbrowser -> nginx+fastcgi -> bash -> program
我有一个测试程序,每半秒输出一行,10次。
我想我可以在响应中声明一个纯文本上下文类型 header 然后执行程序。
不幸的是,输出仅在执行结束时一次性出现在浏览器中。我在 Firefox 和 curl 中测试了它。
我已经测试了很多选项和它们的任意组合来解决这个问题:
- 使用
fastcgi_buffering off
指令禁用 nginx 中的缓冲 - 添加
X-Accel-Buffering
header - 使用
stdbuf -oL program
- 使用 xml http 请求 (XHR) + 服务器端事件 (SSE) 而不是纯文本。
没有任何效果。
我想缓冲问题是在 nginx 和 bash 之间,但我找不到禁用它的方法。
我可以尝试什么?
我找不到解决链中缓冲问题的方法。我尝试了 perl 而不是 bash 但没有运气。
所以我选择填充缓冲区:在受控程序的每一行输出之后,我回显一堆'\0'。由于 Web 浏览器无法将此内容作为纯文本处理,因此我使用服务器发送事件方法。
#!/bin/sh
printf "HTTP/1.0 200 OK\r\n"
printf "Content-type: text/event-stream\r\n"
printf "Cache-Control: no-cache\r\n"
printf "X-Accel-Buffering: no\r\n"
printf "\r\n"
flush() {
padding=4100
dd if=/dev/zero bs=$padding count=1 2>/dev/null
}
subprogram | while read l;
do
printf "data: ${l}\n\n"
flush
done
包装页看起来像这样:
<html>
<head>
<meta charset="UTF-8">
<title>Server-sent events demo</title>
</head>
<body>
<pre></pre>
<script>
var evtSource = new EventSource('/sse.sh?subprogram');
var pre = document.querySelector('pre');
evtSource.onmessage = function(e) {
pre.textContent += e.data + '\n';
}
</script>
</body>
</html>
在这种情况下,Web 浏览器负责删除多余的“\0”。
缺点是cgi输出远大于程序输出