场景如下:
Linux环境,PHP5.3版本,用的ThinkPHP3.1框架(老项目的源码亲喷)。
一顿编译安装之后,发现少转了GD库,就又手动从源码包里拉了GD包出来,单独编译了一遍,最后phpinfo();查看GD库安装上了。
满心欢喜,一顿刷新,操,验证码还是没出来,然后开始了百度一顿搜索,最终总结出以下几种可能性:
一、关于PHP用不了imagepng函数,导致Nginx 502 的问题
查看phpinfo()
里的GD库,是不是安装上了libpng
项,--with-png-dir=/usr/local/libpng.1.6.19
,然后看看php的依赖库,用这个:
ldd /usr/local/php/bin/php | grep libpng
具体的PHP安装路径根据自己的实际情况
我的看到是这样:
libpng12.so.0 => /usr/lib/x86_64-linux-gnu/libpng12.so.0 (0x00007fa6dbbe2000)
libpng12.so.0,其实就是说用的libpng的版本是1.2.x的
很明显libpng.1.6.19
和libpng.1.2.x
是对不上的,问题就在这里,解决的办法是:
1. 把/usr/lib/x86_64-linux-gnu/libpng12.so.0里的libpng12版本升级到libpng16,用apt-get install -y libpng16-dev,再重新编译PHP。
2. 把原来的/usr/local/libpng.1.6.19删了,重新编译安装libpng,要用1.2.x的版本,这里就不赘述libpng的安装了,将路径写到--with-png-dir=里就可以了,再重新编译PHP。
不过可惜,公司并不是这种情况。
二、不重新编译php,扩展gd库,导致nginx出现502错误,php-fpm出现exited with code 127错误
通过使用命令,批量跟踪php-fpm进程
ps -ef | grep fpm | awk '{print "-p " $2}' | xargs strace
刷新在浏览器刷新验证码页面,然后切回XShell,发现最终问题出在PHP调用GD库时报错undefined symbol: gdJpegGetVersionString
【解决方法】
修改源代码:
vim /softs/php-5.6.9/ext/gd/gd.c
下面两行放在首部:
#include "/softs/libpng-1.6.23/png.h"
#include "/softs/jpeg-9b/jpeglib.h"
尾部增加:
const char * gdJpegGetVersionString()
{
switch(JPEG_LIB_VERSION) {
case 62:
return "6b";
break;
default:
return "unknown";
}
}
const char * gdPngGetVersionString()
{
return PNG_LIBPNG_VER_STRING;
}
然后保存gd.c
,重新整合php & gd
,重启php-fpm
、nginx
,就OK了。
但公司还是不是这个问题,找到这里差点崩溃。
三、php gd freetype libjpeg support 不支持
打开phpinfo()
有时候你会发现自己装上了jpeg
、png
、gif
、但却少了个freetype
,这个主要是字体引擎相关的依赖。
先在linux运行
find / -name freetype2
一遍都会得到
/usr/include/freetype2
找到正确的依赖地址,然后重新编译GD库时,加上--with-freetype-dir=/usr/include/freetype2
安装成功,重启php-fpm后,在phpinfo()
里就能看到安装上了。
但这时候我崩溃,具体这个也不是,TMD。
突然内心一哭,难道是框架的问题?这老东西不知道靠不靠谱,直接开源码一顿梭哈再说。
打开验证码类,发现:
php
static function output($im, $type='png', $filename='') {
header("Content-type: image/" . $type);
$ImageFun = 'image' . $type;
if (empty($filename)) {
$ImageFun($im);
} else {
$ImageFun($im, $filename);
}
imagedestroy($im);
}
这老代码原来是根据不同图片类型,自动选择使用哪个image
函数库的,默认是png
。
虽然看着没问题,但由于神笔马良的探索精神,我还是直接断点一波,尝试改成jpg
类型,一顿操作之后,发现验证码居然出来了,难道是imagepng()
函数库的问题?之后function_exists('imagepng')
如我所料,得出结果是false
,又尝试换成imagegif()
,验证码还是能出来,这时候基本就可以确定是png
函数库的问题了。
逛了一波Google,有人说是PHP在编译时没有安装GD库,又或者时安装GD库时没有依赖到PNG,之后再单独编译GD库时,PNG函数库还是会无法使用,只有重新编译PHP,同时编译GD-PNG才能解决这个问题。
反正是新机器,重装PHP问题也不大,就让公司运维重新编译了一次。
重启,按下F5,果然验证码出来了,顿时心中一万只草泥马奔腾而过,只能说一句:PHP牛逼!