網站遷移至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都不要指定目錄到以前的舊版本了。