Ubuntu 下 PHP curl https 段錯誤(或者nginx502)

昨天下午在平常寫代碼的時候遇到一個問題。就是在調用curl_exec()後出現502。而後立刻編寫了一個測試腳本:php

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.baidu.com');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$res = curl_exec($ch);
print_r($res);exit;

發現,只要連接是https的,必然出現段錯誤,這也是致使502的緣由。而http連接能夠正常訪問。css

php[15304]: segfault at 7f43cf4b7c00 ip 00007f43cf4b7c00 sp 00007ffda84c57d8 error 15 in libssl.so.1.1[7f43cf4b4000+4000]

上面的日誌是我經過系統的日誌程序來查看的,我用的是Linux Mint操做系統,打開方式爲:菜單->日誌。而後搜索關鍵詞php,以下圖所示:html

clipboard.png

而後也能夠經過gdp來查看段錯誤,linux

首先,開啓dump選項git

ulimit -c unlimited

而後,運行PHP生成core文件,redis

php test.php

而後在當前目錄會生成core文件,用如下命令查看dump的內容:ubuntu

gdb php -c core

這是顯示結果:curl

GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from php...done.
[New LWP 11242]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `php test.php'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007fe27bd51c00 in ?? () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1

注意到最後一行了嗎,提示咱們libssl有問題。測試

解決問題的靈感從這裏來的:
https://bugs.php.net/bug.php?...fetch

也有人出現了相同的問題,官方提示說是系統curl使用的ssl庫和php編譯時使用的ssl庫(opsnssl)不一至致使的。而後我查找了phpinfo信息,發現php使用的curl版本以及它使用的ssl庫(openssl)版本:

clipboard.png

而後查看PHP編譯時的openssl版本:

clipboard.png

這兩個軟件的openssl版本明顯不一致,因此,下一步就是要麼重新編譯PHP,使用系統的openssl版本1.1.0g,要麼從新編譯安裝curl,使用openssl版本1.0.2o,我選擇了後者。

下面是安裝新版curl的過程。

首先下載新版curl

wget https://curl.haxx.se/download/curl-7.62.0.tar.gz

而後解壓並安裝

tar vxzf curl-7.62.0.tar.gz
cd curl-7.62.0
sudo ./configure --with-ssl=/usr/local/openssl --prefix=/usr/local #php的openssl在這個目錄,因此指定這個
sudo make
sudo make install

而後重新打開一個terminal

curl -V
curl 7.62.0 (x86_64-pc-linux-gnu) libcurl/7.62.0 OpenSSL/1.0.2o zlib/1.2.11
Release-Date: 2018-10-31
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP UnixSockets HTTPS-proxy

發現系統的curl版本已經升級成功,而且openssl的版本也是但願的版本。

clipboard.png

而後咱們再運行測試文件,

➜  tests php test.php                
php: /usr/local/lib/libcurl.so.4: no version information available (required by php) #這個是新問題
<!DOCTYPE html><!--STATUS OK-->
<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <link rel="dns-prefetch" href="//s1.bdstatic.com"/>
    <link rel="dns-prefetch" href="//t1.baidu.com"/>
    <link rel="dns-prefetch" href="//t2.baidu.com"/>
    <link rel="dns-prefetch" href="//t3.baidu.com"/>
    <link rel="dns-prefetch" href="//t10.baidu.com"/>
    <link rel="dns-prefetch" href="//t11.baidu.com"/>
    <link rel="dns-prefetch" href="//t12.baidu.com"/>
    <link rel="dns-prefetch" href="//b1.bdstatic.com"/>
    <title>百度一下,你就知道</title>
    <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/home/css/index.css" rel="stylesheet" type="text/css" />
    <!--[if lte IE 8]><style index="index" >#content{height:480px\9}#m{top:260px\9}</style><![endif]-->
    <!--[if IE 8]><style index="index" >#u1 a.mnav,#u1 a.mnav:visited{font-family:simsun}</style><![endif]-->
    <script>var hashMatch = document.location.href.match(/#+(.*wd=[^&].+)/);if (hashMatch && hashMatch[0] && hashMatch[1]) {document.location.replace("http://"+location.host+"/s?"+hashMatch[1]);}var ns_c = function(){};</script>
    <script>function h(obj){obj.style.behavior='url(#default#homepage)';var a = obj.setHomePage('//www.baidu.com/');}</script>
    <noscript><meta http-equiv="refresh" content="0; url=/baidu.html?from=noscript"/></noscript>
    <script>window._ASYNC_START=new Date().getTime();</script>

發現能夠獲取https的內容了。


解決這個問題:

php: /usr/local/lib/libcurl.so.4: no version information available (required by php) #這個是新問題

解決方式
第一,把/usr/bin裏的curlcurl-config替換爲/usr/local/bin下的對應文件

sudo rm -rf /usr/bin/curl*
sudo ln -s /usr/local/bin/curl /usr/bin/curl
sudo ln -s /usr/local/bin/curl-config /usr/bin/curl-config

第二,因爲我用的是lnmp1.5一鍵安裝包,因此,我從新安裝了下php。這個問題的緣由是php在編譯的時候獲得的libcurl版本是之前系統的版本,如今libcurl升級了,因此對於php來講版本信息就消失了,因此咱們只須要從新安裝一遍php:

cd lnmp1.5
sudo ./upgrade

這裏會提示你輸入要升級哪一個軟件,你選擇PHP。

而後會提示你輸入PHP版本號,你輸入5.6.38。

最後按回車便可。

相關文章
相關標籤/搜索