記一次生產(chǎn)升級事件(php)

背景

咸魚君所在公司的安全部門, 掃描出項目的生產(chǎn)服務(wù)安全漏洞,并且很負(fù)責(zé)任的提供了兩份掃描文檔,

一份針對nginx(1.1.6),
一份針對php(7.1.3),

并限期一周內(nèi)改善完!

咸魚君粗略一掃,全都是服務(wù)軟件的漏洞,

于是乎, 兩個選擇擺在眼前:

1.根據(jù)文檔,按圖索驥, 一個補丁一個補丁的“勞模打補丁”;
2.直接升級軟件到最新版, 當(dāng)然, 得確保服務(wù)的代碼必須要適配!

于是咸魚君“認(rèn)真”考慮了一下(實在是懶,補丁太多,當(dāng)然,也是覺得升級了對應(yīng)用代碼影響不大), 決定升級服務(wù)軟件來解決漏洞!

下面,詳細(xì)介紹咸魚君的升級過程~

評估升級風(fēng)險!

有相似需求的朋友一定要認(rèn)真評估“直接升級服務(wù)軟件版本”方案是否適合自己的業(yè)務(wù), 因為服務(wù)軟件的版本每次升級都會有些變化, 比如php就會舍棄一些函數(shù), 萬一項目代碼用到了, 結(jié)果你直接升級了php
, 最后導(dǎo)致生產(chǎn)的服務(wù)代碼跑不起來,那就悲劇了!!

評估升級風(fēng)險的方式,咸魚君采用的是本地升級服務(wù)軟件,測試項目代碼是否正常~

有條件的也可以搞臺克隆生產(chǎn)環(huán)境的服務(wù)器, 而后測試升級操作~

備份備份備份!

先找到php 的安裝目錄
whereis php
查看當(dāng)前版本(7.1.3)
/usr/local/php/bin/php -v 
查看當(dāng)前configure編譯參數(shù).這個要保存下,編譯新php時要用!
php -i | grep configure 

這里列出來的數(shù)據(jù)格式不對,需要處理一下,建議小伙伴保存在txt中,然后將單引號“ ’ ”替換為空值即可

 ./configure  
--prefix=/usr/local/php
 --with-config-file-
path=/usr/local/php/etc 
--enable-fpm 
--with-mcrypt 
--enable-mbstring 
--enable-pdo 
--with-curl 
--disable-debug 
--disable-rpath 
--enable-inline-optimization 
--with-bz2 
--with-zlib 
--enable-sockets 
--enable-sysvsem 
--enable-sysvshm 
--enable-pcntl 
--enable-mbregex 
--with-mhash 
--enable-zip 
--with-pcre-regex 
--with-mysqli 
--with-gd 
--with-jpeg-dir 
--with-freetype-dir 
--enable-calendar 
--with-openssl 
--with-png-dir 
--with-zlib-dir 
--enable-gd-native-ttf 
--with-xsl 
--with-gettext 
--with-pdo-mysql
備份舊版的php文件夾
sudo cp -r /usr/local/php  /usr/local/php_7.1_bac 

php升級

接下來我們?nèi)?https://www.php.net/downloads.php找到合適的穩(wěn)定的php版本來下載, 記得一定要詳細(xì)看change log,來決定要不要升級! 否則生產(chǎn)的服務(wù)代碼因為版本問題掛了,那就悲劇了!! 咸魚君考察后,選擇了 php7.4.4穩(wěn)定版,粗略一看,應(yīng)該沒問題(事實上后面發(fā)現(xiàn)了個小問題!險些悲劇!)
下載
//切換會用戶目錄(下載文件時先切換自己的目錄,這是個好習(xí)慣!)
cd ~ 
wget https://www.php.net/distributions/php-7.4.4.tar.gz 
解壓
tar -zxvf php-7.4.4.tar.gz
配置編譯參數(shù) (注意, 這里有很多問題, 為了流程的連貫性, 建議先往下看,讀完全文, 最后再執(zhí)行, 咸魚君實力踩坑!)
cd php-7.4.4
//這里的***代表之前保存的編譯參數(shù)
//但是php7.4.4和之前的有些許不同,所以需要大家先轉(zhuǎn)換!!!!
//務(wù)必先不要執(zhí)行,看完全文再執(zhí)行,免得踩坑~
./configure  --prefix=*** 
編譯
sudo make
安裝
sudo make install
恢復(fù)配置
cd /usr/local/php_7.1_bac/
sudo cp etc/php.ini  /usr/local/php/etc/php.ini
sudo cp etc/php-fpm.conf /usr/local/php/etc/php-fpm.conf
sudo cp etc/php-fpm.d/www.conf /usr/local/php/etc/php-fpm.d/
切換新版php
//平滑重啟
kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`

//當(dāng)然,有時候急于等待結(jié)果的話,可以殺死再重啟(不建議)
//咸魚君為了快速驗證,所以采用殺死再重啟的方式,小伙伴們視實際情況而定
cd /usr/local/php/sbin/
sudo killall php-fpm
sudo ./php-fpm
最后,確認(rèn)服務(wù)正常,去訪問下生產(chǎn)的服務(wù),是不是正常,如果發(fā)現(xiàn)不對,立刻執(zhí)行以下命令恢復(fù)舊php
cd /usr/local
sudo killall php-fpm
sudo rm -r php
sudo cp -r php_7.1_bac/  php
sudo /php/sbin/php-fpm

如果真像上面羅列的升級過程一樣簡單就好了,事實上,咸魚君升級php7.4.4的過程中碰到了很多的,并且有些問題是網(wǎng)上找不到明確解答的!, 接下來聽咸魚君細(xì)細(xì)道來~

php編譯期間缺包問題

No package '*******' found

碰到這問題很好解決,缺啥裝啥即可!
這里咸魚君碰到了如下的包缺失問題, 要是你碰到的和我不一樣,沒關(guān)系, 網(wǎng)上這類的問題解決貼一大把,主要因系統(tǒng)環(huán)境而異!

No package 'libjpeg' found
sudo yum install libjpeg libjpeg-devel
No package 'libxml-2.0' found
sudo yum -y install libxml2
sudo yum -y install libxml2-devel
No package 'sqlite3' found
sudo yum install sqlite-devel
No package 'oniguruma' found
sudo yum install oniguruma oniguruma-devel
No package 'libpng' found
sudo yum install libpng-devel

以上包都很好解決,下面這個包有點“意思”,

No package 'libzip' found

Please reinstall the libzip distributio 或 configure: error: system libzip must be upgraded to version >= 0.11
這個包比較特別, 不知道是不是php7.4.4的適配問題, 咸魚君發(fā)現(xiàn) yum install 安裝的版本比較低,并且下載的1.2.1這個包安裝上還是識別不了,只有1.2.0可以用!!!
yum remove libzip libzip-devel     //卸載yum安裝的低版本
wget https://nih.at/libzip/libzip-1.2.0.tar.gz
tar -xvf libzip-1.2.0.tar.gz
cd libzip-1.2.0
./configure
make
////這句一定要執(zhí)行,不然編譯安裝php還是報錯找不到!!
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig/"   
sudo ldconfig
sudo make install

php執(zhí)行時加載“.so”擴展失敗問題

咸魚君安裝完各種包,興沖沖的執(zhí)行

cd /usr/local/php/sbin/
sudo killall php-fpm
sudo ./php-fpm

時,發(fā)現(xiàn),報錯

PHP Warning: PHP Startup: Unable to load dynamic library “******.so”

好吧, 折騰唄!
根本原因就是, 原來編譯安裝的擴展, 比如“redis”這類的,只適用于當(dāng)時的php, 所以我們要想繼續(xù)使用, 則必須得用新的php重新編譯這些擴展,重新安裝!

這里注意的時,有些擴展在php的安裝包里就有,所以不用額外去下載~

Unable to load dynamic library “ bcmath.so”
cd php-7.4.4/ext/bcmath 
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
sudo make
sudo make install
Unable to load dynamic library “redis.so”
wget https://pecl.php.net/get/redis-5.2.1.tgz
tar -axvf redis-5.2.1.tgz
cd redis-5.2.1
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
sudo make
sudo make install

咸魚君就碰到這兩個, 安裝完后

cd /usr/local/php/sbin/
sudo killall php-fpm
sudo ./php-fpm

好吧,再次報錯, 原來是新的擴展打上后, 擴展路徑和以前不一樣了,所以需要修改php.ini, 注意, 安裝擴展時,有返回一個安裝路徑, extension_dir這填充這個路徑即可

sudo vim /usr/local/php/etc/php.ini

修改

extension_dir = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20190902/"

最后

cd /usr/local/php/sbin/
sudo killall php-fpm
sudo ./php-fpm

好的,好像沒問題了!!(劇透, 接下來有兩個大坑!!!)

檢查服務(wù)正常階段

看似nginx和php都升級成功了,也不曾有報錯了!
接下來我們來到最后階段, 訪問下項目, 看下是不是正常運行!!

大坑一: 驗證碼不顯示!

咸魚君項目采用的是Laravel5.6 + captcha做的驗證碼展示, 結(jié)果升級后發(fā)現(xiàn),驗證碼顯示不出來, 圖片請求全是500錯誤, 打開Laravel Debug模式,看到報錯

Symfony\Component\Debug\Exception\FatalThrowableError: Call to undefined function Intervention\Image\Gd\imagettfbbox()

一看, php的gd擴展有問題啊!!!
趕緊去ssh生產(chǎn),查看gd擴展是不是正常安裝的

php -m | grep gd

發(fā)現(xiàn), gd擴展是有的!
這就奇怪了, 隨后網(wǎng)上搜索下, 發(fā)現(xiàn)了各種“大佬”帖子的“解決方案”
大致方案如下

  1. php重新編譯gd擴展
  2. 獨立下載gd擴展編譯安裝
    ………………
    好吧, 咸魚君嘗試了, 并沒什么用!
    這里就不發(fā)出這類的“解決方案”了,免得小伙伴們和我一樣走“歪路”!

下面是重點了, 解決方案如下

問題原因

其實這個問題的確和 gd 擴展有關(guān)系, 主要是和gd擴展的子擴展freetype有關(guān)系!
你需要先判斷生產(chǎn)環(huán)境是不是安裝了freetype

//查看freetype安裝目錄
find / -name freetype  

要是安裝了, 則編寫一個小php腳本來判斷有沒有正確加載
gdtest.php

<?php

if(extension_loaded(gd)){
echo "can use gd<br>";
foreach(gd_info() as $cate=>$value)
echo "$cate: $value<br>";
}else
echo "can not use gd";
?>

執(zhí)行

php test.php

結(jié)果:

can use gd
GD Version: bundled (2.0.34 compatible)
FreeType Support:                            #這里冒號后面沒有值,說明gd不支持freetype
T1Lib Support:
GIF Read Support: 1
GIF Create Support: 1
JPEG Support: 1
PNG Support: 1
WBMP Support: 1
XPM Support:
XBM Support: 1
JIS-mapped Japanese Font Support:

若“FreeType Support: ”后為空不為“1”則說明,gd庫沒有freetype支持!

問題似乎陷入了循環(huán),明明安裝了freetype, 但是gd擴展卻顯示不支持??!!!! 搜遍互聯(lián)網(wǎng),咸魚君得到的全都是“重裝freetype”,“重裝gd擴展”,甚至“重裝php”的“解決方案”!

最后,咸魚君無疑中看到一篇帖子,關(guān)于介紹php7.4.4的configure編譯配置參數(shù)的變化的! 如下

--with-gd                   改為 --enable-gd
--with-freetype-dir     改為 --with-freetype
--with-jpeg-dir           改為 --with-jpeg
--with-webp-dir         改為 --with-webp
--with-xpm-dir           改為 --with-xpm
--with-libxml-dir         改為  --with-libxml 
--enable-zip              改為 --with-zip
--enable-zlib-dir        改為 --with-zlib

大家看到

--with-freetype-dir     改為 --with-freetype

有沒有眼前一亮?!! 是的,真相如此簡單, 還記得我們之前

php -i | grep configure

查出的那一堆配置參數(shù)么, 我們只需要按圖索驥, 把對應(yīng)的舊版參數(shù)替換成新版參數(shù), 然后重新

./configure  --prefix=***
make 
sudo make install

即可!!!

真是坑爹!

另外,咸魚君羅列的可能不全, 大家可以自行查看新版的參數(shù)

 //**代表你需要的擴展參數(shù)的關(guān)鍵字,來查看對應(yīng)的配置方式
./configure -h  | grep **   

最后編譯配置php7.4.4的命令為

./configure  
--prefix=/usr/local/php 
--with-config-file-path=/usr/local/php/etc 
--with-php-config=/usr/local/php/bin/php-configure 
--enable-fpm 
--enable-bcmath 
--with-mcrypt 
--enable-mbstring 
--enable-pdo 
--with-curl 
--disable-debug 
--disable-rpath 
--enable-inline-optimization 
--with-bz2 
--with-zlib 
--enable-sockets 
--enable-sysvsem 
--enable-sysvshm 
--enable-pcntl 
--enable-mbregex 
--with-mhash 
--with-zip 
--with-pcre-regex 
--with-mysqli 
--enable-gd 
--with-jpeg 
--with-freetype 
--enable-calendar 
--with-openssl 
--with-png 
--with-zlib 
--with-gd-native-ttf 
--with-xsl 
--with-gettext 
--with-pdo-mysql

大坑二: php7.4.4數(shù)組嚴(yán)格驗證

滿心關(guān)系的解決完驗證碼問題, 登入了項目web后臺,卻突然發(fā)現(xiàn)報錯

Trying to access array offset on value of type null

當(dāng)時, 嚇得咸魚君一身冷汗, 迅速ssh上生產(chǎn), 先恢復(fù)了舊php!

之后,排查得到報錯原因

原來php7.4.4移除了很多notice報錯,也就是可能老版的php只是warning,notice級別的報錯,在新版里全部以error拋出!
Trying to access array offset on value of type null

就是其中的一種, php7.4.4不允許對值為null的數(shù)組不進(jìn)行判空操作直接使用!

舉個例子

$arr = //api返回;
$name = $arr['name'];

這樣的操作就會拋出異常,所以我們需要先判斷

if(isset($arr['name'])){
    $name = $arr['name'];
}

可以看出,php也在進(jìn)行一些類型的嚴(yán)格規(guī)范了!

修改了這個問題, php就不拋錯了, 咸魚君再次上線了新版php~~

至此, 順利從php7.1.3升級至7.4.4!!

希望咸魚君的升級筆記能夠幫到需要的小伙伴~

升級需評估 ,否則要背鍋~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末压真,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖悯姊,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悲柱,死亡現(xiàn)場離奇詭異,居然都是意外死亡精居,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門潜必,熙熙樓的掌柜王于貴愁眉苦臉地迎上來靴姿,“玉大人,你說我怎么就攤上這事刮便】詹拢” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵恨旱,是天一觀的道長辈毯。 經(jīng)常有香客問我,道長搜贤,這世上最難降的妖魔是什么谆沃? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮仪芒,結(jié)果婚禮上唁影,老公的妹妹穿的比我還像新娘。我一直安慰自己掂名,他們只是感情好据沈,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著饺蔑,像睡著了一般锌介。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天孔祸,我揣著相機與錄音隆敢,去河邊找鬼。 笑死崔慧,一個胖子當(dāng)著我的面吹牛拂蝎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惶室,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼温自,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拇涤?” 一聲冷哼從身側(cè)響起捣作,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤誉结,失蹤者是張志新(化名)和其女友劉穎鹅士,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惩坑,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡掉盅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了以舒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趾痘。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蔓钟,靈堂內(nèi)的尸體忽然破棺而出永票,到底是詐尸還是另有隱情,我是刑警寧澤滥沫,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布侣集,位于F島的核電站,受9級特大地震影響兰绣,放射性物質(zhì)發(fā)生泄漏世分。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一缀辩、第九天 我趴在偏房一處隱蔽的房頂上張望臭埋。 院中可真熱鬧,春花似錦臀玄、人聲如沸瓢阴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荣恐。三九已至,卻和暖如春睬涧,著一層夾襖步出監(jiān)牢的瞬間募胃,已是汗流浹背旗唁。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留痹束,地道東北人检疫。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像祷嘶,于是被迫代替她去往敵國和親屎媳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350