嵌入式boa服务器:502 Bad Gateway The CGI was not CGI/1.1 compliant.
嵌入式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
相关推荐
基于恒阻抗负荷模型与母线三相短路扰动条件下三机九节点系统多频段电力系统稳定器暂态稳定性能评估(Simulink仿真实现)
内容概要:本文系统阐述了一套基于优先级规划与Petri网融合的多机器人路径规划(MAPF)MATLAB代码库,该框架将求解过程划分为几何解析、拓扑构建、调度优化与可视化呈现四个层次,实现了从地图解析、四邻域拓扑与Petri网建模,到基于优先级启发式的路径搜索、时间同步与冲突消解,再到动画与视频输出的完整闭环。其核心创新在于采用Petri网将“多机器人无冲突”这一动态时间约束转化为“每库所至多一标记”的静态容量约束,从而支持整数规划求解;并通过动态边权膨胀机制避免因硬封锁导致的虚假不可解问题,结合节点预留历史与几何惩罚驱动的局部同步策略,显著提升了冲突查询效率与调度性能。框架还支持双坐标系统与全流程可视化,便于算法行为分析与结果验证。; 适合人群:具备一定编程基础和机器人路径规划基础知识的研究生、科研人员及工程技术人员,尤其适合从事仓储物流、自动驾驶、无人机编队等多智能体系统研究的专业人士。; 使用场景及目标:① 在大规模多机器人系统中快速生成无冲突路径,适用于自动化仓库调度等工业场景;② 作为教学与研究工具,深入理解MAPF中的优先级规划、Petri网建模、冲突消解机制及其数学本质;③ 支持算法复现与扩展,可用于对比不同启发式策略、同步算法与规划框架的性能差异。; 阅读建议:建议读者按照文中组织结构顺序阅读,重点关注各模块之间的接口设计与信息传递机制,结合提供的代码实例进行调试与运行,深入理解动态边权膨胀、Petri网容量约束转化、节点预留历史与几何惩罚驱动同步等关键技术的设计意图与实现细节。
机械三维3D设计图-打铁扣自动机.zip
机械三维3D设计图-打铁扣自动机.zip
机械三维3D设计图-光伏铝板自动打标码垛线step.zip
机械三维3D设计图-光伏铝板自动打标码垛线step.zip
译页:一款支持大模型翻译的浏览器网页翻译插件
机器翻译及大模型翻译,需要到浏览器扩展中心开启开发者后加载未打包扩展程序
日式式样书最新版本no.4模版免费模版
日式式样书最新版本no.4模版版免费模版


