PHPBrew:編譯 PHP 的各種踩雷紀錄

PHPBrew 是由 C9S 大神產出來的神作,一直以來都用它維護伺服器上的 PHP 版本,但時常會有一些小問題要解決。這次剛好要裝到新機器上,就順便記錄一下遇到的一些狀況。


系統環境

新開的 VPS 主機,作業系統為 CentOS 7.5,已經用 yum update 更新到最新環境,有啟用 epel-release repository。


Requirement

先安裝官方 Wiki 指定的基本套件,使用的是以下段落:
https://github.com/phpbrew/phpbrew/wiki/Requirement#fedoracentos-requirements

這頁面的另一個段落(CentOS Requirement)親身實驗確定已失效,repoforge.org 已經掛很久啦!!

yum install make automake gcc gcc-c++ kernel-devel
yum install php php-devel php-pear bzip2-devel yum-utils bison re2c libmcrypt-devel libpqxx-devel libxslt-devel pcre-devel libcurl-devel libgsasl-devel openldap-devel
yum-builddep php
yum install httpd-devel

以及我自己需要裝的相依,注意 readline 是有包含在 +default 的,如果你也是指定 +default ,記得安裝。

yum install readline-devel ImageMagick-devel libmemcached-devel

Installing PHPBrew into System wide Environment

參考資料:https://github.com/phpbrew/phpbrew/wiki/Installing-PHPBrew-into-System-wide-Environment

如果想要讓編譯的 PHP 可以給所有使用者使用,就使用 root 來編譯吧。

sudo -i # 切換成 root 身份
phpbrew init

增加環境變數到 PHPBrew 的 bashrc

vim  ~/.phpbrew/bashrc

增加 PHPBREW_ROOTPHPBREW_HOME 環境變數到開頭。

# /.phpbrew/bashrc
export PHPBREW_ROOT=/opt/phpbrew # php dist files and build files are stored here
export PHPBREW_HOME=/root/.phpbrew # your configuration files.

重新載入

source ~/.phpbrew/bashrc

設定登入自動執行檔

接著設定所有使用者的登入自動執行檔,讓大家可以使用同一個 PHP 版本。

這裡註記一下,官方 Wiki 建議放在 /etc/profile.d/phpbrew 是錯的。系統預設只會載入 *.sh 的腳本,所以應該要命名為 phpbrew.sh

vim /etc/profile.d/phpbrew.sh

增加 PHPBREW_ROOTPHPBREW_HOME 環境變數到開頭。

# /etc/profile.d/phpbrew.sh
export PHPBREW_ROOT=/opt/phpbrew
export PHPBREW_HOME=$HOME/.phpbrew
[[ -e ~/.phpbrew/bashrc ]] && source ~/.phpbrew/bashrc

官方 Wiki 的 Cookbook 把 PHPBREW_HOME 寫錯了,source bashrc 的檔案則是 Cookbook 和 Installing PHPBrew into System wide Environment 都錯,詳情請看下方的錯誤紀錄


Setting up

參考資料:https://github.com/phpbrew/phpbrew#setting-up

更新一下 PHP 的版本列表

phpbrew update

Starting Building Your Own PHP

參考資料:https://github.com/phpbrew/phpbrew#starting-building-your-own-php

來開始編譯 PHP 吧

phpbrew install 7.1.7 +default +pdo +mysql +gd=shared +fpm -- --with-fpm-systemd --with-libdir=lib64

將系統 PHP 切換到我們編譯的 php-7.1.7

phpbrew switch php-7.1.7

然後安裝需要的擴充模組

phpbrew ext install imagick
phpbrew ext install memcached
phpbrew ext install redis
phpbrew ext install gd -- --with-gd=shared --enable-gd-native-ttf --with-jpeg-dir=/usr/lib64 --with-png-dir=/usr/lib64

PHP 設定

接著就可以編輯一些設定了

設定 php.ini

例如想要修改 php.ini 設定 expose_php 為 Off 把版本號資訊隱藏
只要執行以下命令就可以打開當前版本的 php.ini

phpbrew config

就會用預設的編輯器(如 nano)開啟 php.ini

如果你想要使用 Vim 等其他編輯器開啟
記得指定 EDITOR 環境變數
例如在 ~/.bashrc 中加入

export EDITOR=vim

設定 php-fpm.conf

如果想要設定如 max_children 等針對 FPM 的設定
也是有簡單的指令即可開啟當前版本的 php-fpm.conf

phpbrew fpm config

錯誤紀錄

稍微紀錄一下編譯與安裝時遇到的錯誤。

configure: error: Cannot find OpenSSL’s libraries

如果要讓編譯的 PHP 支援 OpenSSL,在 Fedora/Centos 64-Bit 系統需要加上 --with-libdir=lib64 來編譯。可以參考以下資料:


configure: error: Please reinstall readline - I cannot find readline.h

如果你是使用 +default 選項,就會需要先安裝 readline-devel。參考資料:


PHPBrew 安裝成全域(system-wide),重登入卻沒抓到

文件建議把環境變數放在 /etc/profile.d/phpbrew,這部分寫錯了。
/etc/bashrc 預設只會載入 /etc/profile.d/*.sh,所以應該要命名為 /etc/profile.d/phpbrew.sh


-bash: /opt/phpbrew/bashrc: No such file or directory

Cookbook 和 Installing PHPBrew into System wide Environment 都這樣指定,卻沒有這個檔案,不知道為什麼。我暫時改為 [[ -e ~/.phpbrew/bashrc ]] && source ~/.phpbrew/bashrc。參考以下資料:


module ‘某擴充模組’ already loaded in unknown on line 0

我遇到的是 module 'curl' already loaded in unknown on line 0,通常是因為編譯的時候重複指定了 Variants,例如我原本沒發現 +default 裡面有 curl 就又多寫了一個 +curl。這個解決方法我找不到,只能刪除重新編譯了。


如何移除某一版本 PHP?

這個文件裡面沒有寫,但 phpbrew help 以及 一些 Issue 中有提到。

phpbrew remove [php-version]
phpbrew purge [php-version]

要注意的是,php-version 要填完整名稱,不能像 phpbrew switch 可以只填版本號。例如 phpbrew remove php-7.1.7

phpbrew help 的說明可以看出 removepurge 是有點差異的。

remove    Remove installed php build.
 purge    Remove installed php version and config files.

另外前者會有確認提示:

phpbrew remove php-7.1.7
# Are you sure to delete php-7.1.7? [Y/n]
# php-7.1.7 is removed.  I hope you're not surprised. :)

後者則是直接刪除:

phpbrew purge php-7.1.7
# php version: php-7.1.7 is removed and purged.

PHP Warning: PHP Startup: Invalid library (maybe not a PHP library) ‘curl.so’ in Unknown on line 0

這是因為已經用 +default 把 curl 編譯進去了,如果又再用 phpbrew ext install curl 安裝擴充模組就會造成錯誤。解決方法是停用 curl 外掛:

phpbrew ext disable curl

參考資料:

但我也有執行 phpbrew ext install gd,不知道為什麼沒有報錯就是了⋯⋯


PHP Warning: touch(): Unable to create file /opt/phpbrew/bin/composer because No such file or directory in phar:///usr/local/bin/phpbrew/src/PhpBrew/Downloader/BaseDownloader.php on line 43

執行 phpbrew app get composer 安裝 Composer 的時候,不知道為什麼它不能自己 mkdir,錯誤訊息是 RuntimeException: Target path (/opt/phpbrew/bin/composer) is not writable!

理論上 ~/.phpbrew/bashrc 會幫你自動建好 /opt/phpbrew/bin 目錄,所以可能是你的 ~/.phpbrew/bashrc 沒有設定好。

之後要執行的話就是使用以下指令

php composer command [options] [arguments]

還要多打一個 php 有點麻煩,所以我還是移除改成 Composer 官方的安裝方式了。


終於裝完了

歷經好幾個小時(淚