如今LNMP架构很流行,php
然而有时咱们会遇到一个莫名其妙的问题,nginx
就是咱们访问php页面时服务器返回"HTTP/1.1 500 Internal Server Error"错误web
这个错误让人匪夷所思,还觉得是nginx出问题了呢?chrome
实际上是php代码语法错误致使的api
默认状况下,若是被访问的php脚本中包含语法错误,服务器会返回一个空的“200 ok”页面安全
在php.ini中的fastcgi.error_header选项容许在这种状况下产生一个HTTP错误码服务器
以使web服务器能够正确拦截并处理这个错误码,相似直接在php代码中调用header()返回500状态码,如cookie
header("HTTP/1.1 500 Internal Server Error");session
经过php源码也能够看出来,本次使用的php版本是:php-5.3.26架构
源文件是:php-5.3.26/main/main.c
第1110行,以下:
if(!PG(display_errors) && !SG(headers_sent) && SG(sapi_headers).http_response_code == 200){ sapi_header_line ctr = {0}; ctr.line = "HTTP/1.0 500 Internal Server Error"; ctr.line_len = strlen(ctr.line); sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); }
经过if条件能够得知,在知足 display_errors=0 和 headers_sent=0即空白页和
http_response_code=200的条件下返回500错误
初看这个500错误容易误认为nginx出错,能够适当调整为其它响应码
只要在php.ini中设置 fastcgi.error_header 选项便可,如返回503:
fastcgi.error_header = "HTTP/1.1 503 PHP Parse Error"
这样就能够显示出错误的根本缘由,能够在部署LNMP时加上
没加这个选项时,能够经过下面方法调试:
将访问出错的页面拷贝一个,成测试文件,防止影响线上业务和安全问题
如:cp index.php index.test.php
打开 display_errors 选项,在文件开头加入以下内容:
ini_set('display_errors','1'); error_reporting(E_ALL);
这样就能够将错误暴露出来,完毕!
前几天就遇到了这个500错误问题,状况是这样的:
有开发人员说网站访问出现500错误,他说ie和chrome都访问不了,只有firefox能够访问,我本身也试了试,ie和chrome确实不能访问,我机器没装firefox,因此没试,我忽然想起之前公司也遇到过这个问题,因此想到了cookie的问题,就上服务器上排查php程序代码,最后发现这么一段代码:
protected function __construct($domain){ ... session_name(self::sess_name); $this->sess_id = empty($_COOKIE[session_name()]) ? $this->gen_sid() : $_COOKIE[session_name()]; ... } private function gen_sid(){ return md5(uniqid(microtime() . getClientIP(), true)); }
当程序执行到第9行的时候就会发生500错误,最大的可能就是 getClientIP 函数致使的,直接调用这个函数仍然返回500错误,用var_dump(function_exists('getClientIP'))调试,输出false,问题就在这里了,定义好这个函数就解决了。但是为何firefox能够访问,而ie和chrome不能访问呢?这是由于firefox里面存在cookie了,而ie和chrome都是第一次访问,没有cookie,那为何没有cookie就会出现这个问题呢?这要归责于:
$this->sess_id = empty($_COOKIE[session_name()]) ? $this->gen_sid() : $_COOKIE[session_name()];
第一次访问没有cookie,因此empty($_COOKIE[session_name()])为true,
就会调用$this->gen_sid(),就会出现上面找不到getClientIP函数的错误,而cookie存在的话就不会调用$this->gen_sid(),而是返回冒号后面的$_COOKIE[session_name()],就没问题了,呵呵!其实这么排查有点啰嗦,直接打开错误报告,错误就会显现出来,如:
ini_set('display_errors','1'); error_reporting(E_ALL);
显示以下错误信息,很容易就发现问题了,good
Fatal error: Call to undefined function getClientIP()
另外在 php-fpm.conf 中设置的php.ini选项优先于在php.ini中设置的选项,如
在 php.ini 中设置 display_errors = on
在 php-fpm.conf 中设置 php_flag[display_errors] = off
那么结果是 off