嵌入式boa服务器:502 Bad Gateway The CGI was not CGI/1.1 compliant.

JamesHou84 2012-03-18 04:06:25
若感觉这个页面不友好,欢迎到博客里面看看,哪里界面还可以接受,谢谢http://blog.csdn.net/jameshou84/article/details/7366079
嵌入式boa服务器:502 Bad Gateway The CGI was not CGI/1.1 compliant.
这段时间做boa嵌入式服务器移植,一直出现这个错误排除不了。

一、问题:

网页显示:

502 Bad Gateway

The CGI was not CGI/1.1 compliant.

终端错误输出为:

[18/Mar/2012:00:46:02 +0000] cgi_header: unable to find LFLF

cgi程序文件内容如下test_cgi.c:

#include <stdio.h>
#include <stdio.h>[cpp] view plaincopyprint?int main(void)
{
printf("Content-type: text/html;charset=gb2312\n\n");
printf("\r\n");
printf("<html>\n");
printf("<body>\n");
printf("123456789\n");
printf("</body>\n");
printf("</html>\n");
return 0;
}

交叉编译该文件:/usr/local/arm/4.4.3/bin/arm-linux-gcc -static -o test.cgi test_cgi.c

在虚拟机上(gcc -static -o test.cgi test_cgi.c)运行良好可以显示正确的结果,但是 移植到开发板上面就不可以了。

开发板情况:飞凌公司OK6410,内核linux-2.6.36.2,s3c64xx,yaffs2;虚拟机Ubuntu10.04,内核2.6.32-24-generic,gcc version 4.4.3

配置文件/etc/boa/boa.config为:

Port 80
User nobody
Group 0
ErrorLog /var/log/boa/error_log
AccessLog /var/log/boa/access_log
ServerName www.your.org.here
DocumentRoot /usr/local/boa
#DocumentRoot /var/www
UserDir public_html
DirectoryIndex index.html
#DirectoryMaker /usr/lib/boa/boa_indexer
KeepAliveMax 1000
KeepAliveTimeout 10
MimeTypes /etc/mime.types
DefaultType text/plain
CGIPath /bin:/usr/bin:/usr/local/bin
Alias /doc /usr/doc
#ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
#ScriptAlias /cgi-bin/ /var/www/cgi-bin/
ScriptAlias /cgi-bin/ /usr/local/boa/cgi-bin
Port 80
User nobody
Group 0
ErrorLog /var/log/boa/error_log
AccessLog /var/log/boa/access_log
ServerName www.your.org.here
DocumentRoot /usr/local/boa
#DocumentRoot /var/www
UserDir public_html
DirectoryIndex index.html
#DirectoryMaker /usr/lib/boa/boa_indexer
KeepAliveMax 1000
KeepAliveTimeout 10
MimeTypes /etc/mime.types
DefaultType text/plain
CGIPath /bin:/usr/bin:/usr/local/bin
Alias /doc /usr/doc
#ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
#ScriptAlias /cgi-bin/ /var/www/cgi-bin/
ScriptAlias /cgi-bin/ /usr/local/boa/cgi-bin
二、原因分析与失败的尝试:

1、经查找,打印出错信息“cgi_header: unable to find LFLF”的地方在cgi_header.c文件中。

[cpp] view plaincopyprint?int process_cgi_header(request * req)
{
char *buf;
char *c;

if (req->cgi_status != CGI_DONE)
req->cgi_status = CGI_BUFFER;

buf = req->header_line;

c = strstr(buf, "\n\r\n");
if (c == NULL) {
c = strstr(buf, "\n\n");
if (c == NULL) {
log_error_time();
67 fprintf(stderr, "\n\"%s\"\n", buf);
68 <strong>fputs("cgi_header: unable to find LFLF\n", stderr);//图终端显示</strong>
#ifdef FASCIST_LOGGING
log_error_time();
fprintf(stderr, "\"%s\"\n", buf);
#endif
73 send_r_bad_gateway(req);
return 0;
}
}
……
}
int process_cgi_header(request * req)
{
char *buf;
char *c;

if (req->cgi_status != CGI_DONE)
req->cgi_status = CGI_BUFFER;

buf = req->header_line;

c = strstr(buf, "\n\r\n");
if (c == NULL) {
c = strstr(buf, "\n\n");
if (c == NULL) {
log_error_time();
67 fprintf(stderr, "\n\"%s\"\n", buf);
68 <strong>fputs("cgi_header: unable to find LFLF\n", stderr);//图终端显示</strong>
#ifdef FASCIST_LOGGING
log_error_time();
fprintf(stderr, "\"%s\"\n", buf);
#endif
73 send_r_bad_gateway(req);
return 0;
}
}
……
}


分析且通过输出信息到error_log文件得知,buf为空,即req->header_line为空。既然是它为空,说明可执行文件执行的时候没有打印到管道文件,或者读取管道文件失败。

2、可执行文件的执行在cgi.c文件

[cpp] view plaincopyprint?492 if (!cgi_log_fd)//cgi_log_fd=0
<strong>493 dup2(devnullfd, STDERR_FILENO);</strong>
494 else
495 dup2(cgi_log_fd, STDERR_FILENO);
496
497 if (req->is_cgi) {
498 char *aargv[CGI_ARGC_MAX + 1];
499 create_argv(req, aargv);
500 <strong> execve(req->pathname, aargv, req->cgi_env);</strong>//req->pathname=/usr/local/boa/cgi-bin/test.cgi
492 if (!cgi_log_fd)//cgi_log_fd=0
<strong>493 dup2(devnullfd, STDERR_FILENO);</strong>
494 else
495 dup2(cgi_log_fd, STDERR_FILENO);
496
497 if (req->is_cgi) {
498 char *aargv[CGI_ARGC_MAX + 1];
499 create_argv(req, aargv);
500 <strong> execve(req->pathname, aargv, req->cgi_env);</strong>//req->pathname=/usr/local/boa/cgi-bin/test.cgi

难道是execve(req->pathname, aargv, req->cgi_env);执行失败,但是我无法查证,因为在493行前可以打印信息,在其后就不可以了,这样execve()函数的是否执行成功就无法验证。

3、查看读管道文件的程序,在pipe.c中

[cpp] view plaincopyprint?int read_from_pipe(request * req)
{
int bytes_read, bytes_to_read =//4096
BUFFER_SIZE - (req->header_end - req->buffer);//(req->header_end - req->buffer)=4096

if (bytes_to_read == 0) { /* buffer full */
if (req->cgi_status == CGI_PARSE) { /* got+parsed header */
req->cgi_status = CGI_BUFFER;
return process_cgi_header(req); /* cgi_status will change */
}
req->status = PIPE_WRITE;
return 1;
}

<strong>bytes_read = read(req->data_fd, req->header_end, bytes_to_read);</strong>
int read_from_pipe(request * req)
{
int bytes_read, bytes_to_read =//4096
BUFFER_SIZE - (req->header_end - req->buffer);//(req->header_end - req->buffer)=4096

if (bytes_to_read == 0) { /* buffer full */
if (req->cgi_status == CGI_PARSE) { /* got+parsed header */
req->cgi_status = CGI_BUFFER;
return process_cgi_header(req); /* cgi_status will change */
}
req->status = PIPE_WRITE;
return 1;
}

<strong>bytes_read = read(req->data_fd, req->header_end, bytes_to_read);</strong>[cpp] view plaincopyprint?<strong> //</strong>req->data_fd=7=pipe[0],bytes_read = -1 or 0
if (bytes_read == -1) {
if (errno == EINTR)
return 1;
else if (errno == EWOULDBLOCK || errno == EAGAIN)
return -1; /* request blocked at the pipe level, but keep going */
else {
req->status = DEAD;
log_error_doc(req);
perror("pipe read");
return 0;
}
} <strong>else if (bytes_read == 0)</strong> { /* eof, write rest of buffer */
req->status = PIPE_WRITE;
if (req->cgi_status == CGI_PARSE) { /* hasn't processed header yet */
req->cgi_status = CGI_DONE;
*req->header_end = '\0'; /* points to end of read data */
return process_cgi_header(req); /* cgi_status will change */
}
req->cgi_status = CGI_DONE;
return 1;
}
req->header_end += bytes_read;
return 1;
}
<strong> //</strong>req->data_fd=7=pipe[0],bytes_read = -1 or 0
if (bytes_read == -1) {
if (errno == EINTR)
return 1;
else if (errno == EWOULDBLOCK || errno == EAGAIN)
return -1; /* request blocked at the pipe level, but keep going */
else {
req->status = DEAD;
log_error_doc(req);
perror("pipe read");
return 0;
}
} <strong>else if (bytes_read == 0)</strong> { /* eof, write rest of buffer */
req->status = PIPE_WRITE;
if (req->cgi_status == CGI_PARSE) { /* hasn't processed header yet */
req->cgi_status = CGI_DONE;
*req->header_end = '\0'; /* points to end of read data */
return process_cgi_header(req); /* cgi_status will change */
}
req->cgi_status = CGI_DONE;
return 1;
}
req->header_end += bytes_read;
return 1;
}
由上面分析看,第一次读取管道失败;第二次读取管道返回值为0,说明管道为空,或者已经读取到了文件末尾。

虚拟机上面我也做过类似的验证,情况和上面的一样,但是虚拟机上面可以的显示网页,而开发板不行,又可以说明是因为是管道文件为空。

3、此外test.cg的权限为0777, /usr/loca/boa 权限为0755,//usr/loca/boa/cgi-bin 权限为0755.

三、求解决之道,将不胜感激:

QQ:552457836,email:houqi0803@163.com

...全文
4070 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
钱国正 2012-04-09
  • 打赏
  • 举报
回复
我也遇到了,但是没有您分析的透彻啊,
智慧光 2012-04-01
  • 打赏
  • 举报
回复
这样写就可以了。
/usr/local/arm/4.4.3/bin/arm-linux-gcc -static -o test test_cgi.c

2,204

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 CGI
社区管理员
  • CGI社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧