网站迁移至Nginx php-fpm下运行,发现验证码显示红叉,无法使用。检查phpinfo(),确定GD模块已经加载。查看日志,发现报错

PHP Fatal error: Call to undefined function imagettfbbox() in …

1、重新编译PHP

加上–with-freetype-dir和–enable-gd-native-ttf参数,该错误日志消失。但仍未解决问题,直接访问验证码url,显示Nginx 502报错。

2、怀疑Nginx中FastCGI Buffer缓存设置不足

在nginx.conf的server{…}中加入以下设置

fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on

无效。静下来想想,502的错误其实不是nginx的问题,要从后端找原因。php-cgi进程数不够用、php执行时间长、或者是php-cgi进程死掉,都会出现502错误。

检查php/logs/php-fpm.log,果然发现只要一请求验证码,php-cgi进程就挂掉重启:

WARNING: [pool www] child 3496 exited on signal 11 (SIGSEGV) after 4104 seconds from start

3、重新安装CAPTCHA验证码功能模块

该功能由Text_CAPTCHA提供,这是一个由pear安装的库。怀疑版本过旧,重新安装之。

pear install Image_Text
pear install Text_CAPTCHA
pear install Text_Password

未能解决问题。

搜索到国外一个问答网站,同样的验证码问题,有关办法并未解决我的问题,但解决思路很好可以借鉴。检查与验证码有关的php代码,虽然不太可能是php源码的问题(在Apache下可以正常运行),只有顺藤摸瓜了。

4、测试GD模块

注释代码块,最终把502错误的根源缩小范围定位到一个函数imagepng()。凡是验证码生成都会用到这个函数,那么我们来写点代码测试一下吧。
test_png.php

<?php
$im = imagecreatetruecolor(120, 20);
$text_color = imagecolorallocate($im, 255, 0, 0);
imagestring($im, 1, 5, 5,  'A Simple Text String', $text_color);
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
?>

部署到服务器环境,访问之,仍旧502出错。再试试下面这个呢
test_jpeg.php

<?php
// Create a blank image and add some text
$im = imagecreatetruecolor(120, 20);
$text_color = imagecolorallocate($im, 233, 14, 91);
imagestring($im, 1, 5, 5,  'A Simple Text String', $text_color);
// Set the content type header - in this case image/jpeg
header('Content-Type: image/jpeg');
// Output the image
imagejpeg($im);
// Free up memory
imagedestroy($im);
?>

部署到服务器环境,访问之,显示出图片了!我勒个去,看来是GD库的libpng出了问题。好办了,把生成验证码相关的imagepng()统统换成imagejpeg(),搞定。

感谢党和国家!

服务器上的PHP版本为5.3.6,是目前的最新版,很多第三方插件还没有兼容。最后尽量使用PHP内置源码来安装类似GD这样的库,也就是说编译时–with-gd –with-png-dir都不要指定目录到以前的旧版本了。