博文記錄
PHP 2020-07-02 16:18:45 178 0

CentOS7/8编译安装PHP7.4.4

说明

近日折腾打包了PHP一套的离线安装包,用于内网离线安装。在这里整理下打包的全部过程以及移植后安装需要注意的东西。

此次打包的环境大致包含:PHP 7.4.4、swoole 4.5.2、phpredis 5.3.0 RC2、rdkafka 4.0.3

文章分为常规动态编译及安装 RPM 依赖包的形式打包 PHP,和静态编译 PHP 的方式在最后记录。

 

我们要做的就是在外网把需要的环境编译或者安装包打包好,再拷贝到内网通过适当的方式使用。

首先在外网准备一个纯净的 centos7 系统,centos-mini(最小化安装)就可以,避免一些依赖被自动安装。否则在准备过程中无法记录缺少哪些依赖,进而在内网报错缺少依赖,一来一回非常麻烦。

 

工作目录

我们编译安装包全部在 /mnt/tools 下进行,如果没有则创建并进入,后面编译每个步骤前都务必先进入这个目录,否则可能会出错。

mkdir /mnt/tools
cd /mnt/tools

安装编译器

主要是包含了编译 php 时所需的 gcc 相关程序

yum install -y gcc gcc-c++ automake autoconf libtool make

 

编译程序

除了编译 php 本身的程序外,还需要编译swoole、phpredis、rdkafka的扩展。

 

PHP

首先我们安装 PHP,PHP 我们采用编译的方式,避免繁杂的rpm依赖包,和升级版本,调整扩展问题。也方便我们后续编译 swoole 和 rdkafka 扩展。

选用最新最新的 PHP 7.4.4

wget http://php.net/get/php-7.4.4.tar.gz/from/this/mirror -O php-7.4.4.tar.gz
tar -xzf php-7.4.4.tar.gz -C ./
cd php-7.4.4

编译的参数

这里整理的大部分常用的扩展都集合进去了,一般够用,如果需要精简,自行裁剪。

PHP 我们编译到了 /usr/local/php/php7.4.4/ 目录,移植时,只需要打包这个目录就可以。

./configure --prefix=/usr/local/php/php7.4.4/ --with-config-file-path=/usr/local/php/php7.4.4/ --with-libdir=lib --enable-fpm --enable-gd --enable-gd-jis-conv --with-fpm-user=www --with-fpm-group=www --enable-mysqlnd --with-pdo-mysql=mysqlnd --enable-opcache --enable-pcntl --enable-mbstring --enable-soap --enable-calendar --enable-bcmath --enable-exif --enable-ftp --enable-intl --enable-sockets --with-openssl --with-zlib --with-curl --with-gettext --with-mhash --with-webp --with-jpeg --with-ldap --with-zip

如果你执行预编译,这里可能会出现很多错误,都是缺少依赖的,这里我们记录一下缺少哪些依赖,然后下载并记录下载,移植到内网时一并打包。

这里提供一个可以下载 RPM 包的网站:https://centos.pkgs.org/7/centos-x86_64/

举例,如果提示缺少 libicu,我们就到这里下载 libicu 的 RPM 包就可以,一般我们下载 x86_64 就可以,如果实在找不到也可以尝试找个其他平台的尝试。

我们在外网环境一般安装依赖时通过 yum 安装 libicu-devel 开发包就可以了。如果这里下载 RPM 包,我们要下载两个一个是程序本身,一个是程序的开发包。通过RPM安装时,不能只安装开发包,会提示缺少程序的依赖。

所以,所需要下载的 libicu 的RPM包如下:

libicu-50.2-3.el7.x86_64.rpm
libicu-devel-50.2-3.el7.x86_64.rpm

 

编译执行

通过以下命令编译执行,过程中可能会遇到错误,目前我在编译时需要的错误只有一个 ldap 扩展的问题,只需要修改 Makefile 就可以成功编译,网上也有很多解决办法,我写在下面了。

make
make install

编译遇到错误:undefined reference to symbol 'ber_memfree

/usr/bin/ld: ext/ldap/.libs/ldap.o: undefined reference to symbol 'ber_memfree'
//usr/lib64/liblber-2.4.so.2: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make: *** [sapi/cli/php] Error 1

解决办法:编辑 MakeFile 文件,找到 EXTRA_LIBS 开头的这一行,在结尾加上-llber。

 

复制配置文件

将所需要的配置文件复制到 PHP 的安装目录,php-fpm 需要后期到内网再复制到 /etc/init.d/php-fpm 方便启用服务。

cp sapi/fpm/init.d.php-fpm /usr/local/php/php7.4.4/php-fpm
cp php.ini-production  /usr/local/php/php7.4.4/php.ini
cp /usr/local/php/php7.4.4/etc/php-fpm.conf.default /usr/local/php/php7.4.4/etc/php-fpm.conf
cp /usr/local/php/php7.4.4/etc/php-fpm.d/www.conf.default /usr/local/php/php7.4.4/etc/php-fpm.d/www.conf

 

编译扩展

扩展包含 phpredis、swoole、rdkafka 的安装

 

[phpredis]

下载源码 phpredis

wget https://github.com/phpredis/phpredis/archive/5.3.0RC2.zip

省略解压过程,自行解压。

 

编译选项

这个基本无依赖,直接编译并安装就行。

/usr/local/php/php7.4.4/bin/phpize
./configure --with-php-config=/usr/local/php/php7.4.4/bin/php-config
make
make install

 

[swoole]

下载源码 phpredis

wget https://github.com/swoole/swoole-src/archive/v4.5.2.tar.gz

省略解压过程,自行解压。

编译选项

swoole 也顺利安装,无依赖问题。

/usr/local/php/php7.4.4/bin/phpize
./configure --with-php-config=/usr/local/php/php7.4.4/bin/php-config
make
make install

 

[rdkafka]

PHP 的 rdkafka 扩展需要依赖系统的 librdkafka 库,稍微多两步,也很简单。

下载 librdafka 记得留存

wget http://mirror.centos.org/centos/7/os/x86_64/Packages/librdkafka-0.11.4-1.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/librdkafka-devel-0.11.4-1.el7.x86_64.rpm

安装 librdkafka

rpm -ivh librdkafka-0.11.4-1.el7.x86_64.rpm 
rpm -ivh librdkafka-devel-0.11.4-1.el7.x86_64.rpm

 

下载 php-rdkafa 的源码

wget https://github.com/arnaud-lb/php-rdkafka/archive/4.0.3.tar.gz --no-check-certificate

编译选项

只要前面系统的库没问题了,这里也顺利完成。

/usr/local/php/php7.4.4/bin/phpize
./configure --with-php-config=/usr/local/php/php7.4.4/bin/php-config --with-rdkafka
make -j 4
make install

 

启用扩展

最后通过修改 php.ini 启用扩展

我们在文件 extension 段加入我们刚刚编译的扩展,,当然加到文件尾也行,只是我强迫症。

extension=swoole
extension=redis
extension=rdkafka

加入完毕后可以通过 php -m 查看扩展是否正常。

/usr/local/php/php7.4.4/bin/php -m

 

打包

打包这里因为我们已经把扩展安装到了php的目录中,所以直接将整个php目录打包就可以。

来到 php 安装目录的上一层,进行打包。

cd /usr/local/php
tar -czf php7.4.4.tar.gz php7.4.4/

 

打包刚刚过程中的下载的 RPM 依赖包

我这里整理了下,PHP7特性的需要如下几个:

libicu-50.2-3.el7.x86_64.rpm
libicu-devel-50.2-3.el7.x86_64.rpm

oniguruma-6.8.2-1.el7.x86_64.rpm
oniguruma-devel-6.8.2-1.el7.x86_64.rpm

libzip-devel-0.11.2-6.el7.psychotic.x86_64.rpm
libzip-devel-0.11.2-6.el7.psychotic.x86_64.rpm

# rdkafka所需
librdkafka-0.11.4-1.el7.x86_64.rpm 
librdkafka-devel-0.11.4-1.el7.x86_64.rpm

还有一些基础的,就是说可能一些系统系统环境包含的。

libcurl-7.29.0-57.el7.x86_64.rpm
libcurl-devel-7.29.0-57.el7.x86_64.rpm
libjpeg-turbo-1.2.90-8.el7.x86_64.rpm
libjpeg-turbo-devel-1.2.90-8.el7.x86_64.rpm
libpng-1.5.13-7.el7_2.x86_64.rpm
libpng-devel-1.5.13-7.el7_2.x86_64.rpm
libwebp-0.3.0-7.el7.x86_64.rpm
libwebp-devel-0.3.0-7.el7.x86_64.rpm
libxml2-2.9.1-6.el7.4.x86_64.rpm
libxml2-devel-2.9.1-6.el7.4.x86_64.rpm
libzip-0.10.1-8.el7.x86_64.rpm
libzip-devel-0.10.1-8.el7.x86_64.rpm
openldap-2.4.44-21.el7_6.x86_64.rpm
openldap-devel-2.4.44-21.el7_6.x86_64.rpm
openssl-1.0.2k-19.el7.x86_64.rpm
openssl-devel-1.0.2k-19.el7.x86_64.rpm
sqlite-3.7.17-8.el7_7.1.x86_64.rpm
sqlite-devel-3.7.17-8.el7_7.1.x86_64.rpm

把以上的全部打包移植到内网,如果你是通过 zip 压缩,可能你还额外需要附带一个 unzip 的包。

unzip-6.0-20.el7.x86_64.rpm

 

移植运行

如果你成功的把以上的所有包移植到内网了,那么可以进行以下的还原相关操作,将打包好的环境还原到系统中并调整得以使用。

 

还原程序

首先你找一个适当的目录存放你的移植包,将其解压获取刚才打包的 php 以及 RPM 依赖包。并将我们之前打包的 php7.4.4.tar.gz 进行解压,得到 php7.4.4 的目录。

移动到对应的目录,如果不存在,则需要创建。

mkdir /usr/local/php
mv -rf php7.4.4 /usr/local/php/

配置文件是:/usr/local/php/php7.4.4/php.ini

将 PHP 软连接到系统环境变量目录中

ln -s /usr/local/php/php7.4.4/bin/php /usr/local/bin/php

将 php-fpm 复制到系统服务目录,可以将其以服务方式运行。

cp /usr/local/php/php7.4.4/php-fpm /etc/init.d/php-fpm

并赋予执行权限

chmod +x /etc/init.d/php-fpm

顺便可以运行或者加入开机自启,根据需要。

# 启动
service start php-fpm

# 停止
service stop php-fpm

# 重启
service restart php-fpm

# 加入开机自启
systemctl enable php-fpm

 

解决依赖问题

通过尝试运行 php -v 查看 php 所报的错误,而逐个选择安装那些依赖,直到没有错误为止,能正常输出 php 版本号就可以正常工作了。

如,报 php: error while loading shared libraries: libwebp.so.4: cannot open shared object file: No such file or directory

我们需要装 libwebp 的 RPM 包,安装方式如下:

rpm -ivh libwebp-0.3.0-7.el7.x86_64.rpm
rpm -ivh libwebp-devel-0.3.0-7.el7.x86_64.rpm

安装完毕后,再通过 php -v 查看错误,如此往复操作即可。

这里再顺便说一下,尽可能的少装 RPM,更不要一口气把所有 RPM 包都装了,其一是避免系统本身就有的包产生冲突,其二是,这样更能方便理解程序所需的包,需之装之,不装多余的包进去。

 

以上的完整离线包,我都打包好了,有需要的可以直接下载,不用自己再折腾一遍。

php 的版本及模块如下:

> php -v
PHP 7.4.4 (cli) (built: Apr 12 2020 21:52:52) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

> php -m
[PHP Modules]
bcmath
calendar
Core
ctype
curl
date
dom
exif
fileinfo
filter
ftp
gd
gettext
hash
iconv
intl
json
ldap
libxml
mbstring
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
rdkafka
redis
Reflection
session
SimpleXML
soap
sockets
SPL
sqlite3
standard
swoole
tokenizer
xml
xmlreader
xmlwriter
zip
zlib

[Zend Modules]

 

下载地址

待更新

 

静态编译

静态编译可以将你所需的 PHP 编译好提供给其他人使用,不用担心对方依赖不足无法运行。其次在内网环境下也非常适用。

编译参数

我们这里以最简化加上我所需要的几个基础库作为编译参数,如果你有所不同,更改其即可。

./configure LDFLAGS=-static --prefix=/usr/local/php/php7.4/ --with-config-file-path=/usr/local/php/php7.4/  --enable-sockets  --enable-json --with-openssl --disable-all --enable-static=yes --enable-shared=no --enable-inline-optimization

 

修改Makefile

BUILD_CLI = $(LIBTOOL) --mode=link $(CC) -export-dynamic $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS_PROGRAM) $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_CLI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $(SAPI_CLI_PATH)
BUILD_CGI = $(LIBTOOL) --mode=link $(CC) -export-dynamic $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS_PROGRAM) $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_CGI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $(SAPI_CGI_PATH)

替换为

BUILD_CLI = $(LIBTOOL) --mode=link $(CC) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS_PROGRAM) $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_CLI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -all-static -o $(SAPI_CLI_PATH)
BUILD_CGI = $(LIBTOOL) --mode=link $(CC) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS_PROGRAM) $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_CGI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -all-static -o $(SAPI_CGI_PATH)

即,在 BUILD_CLIBUILD_CGI 对应的行中移除 -export-dynamic,在 -o $(SAPI_CGI_PATH)-o $(SAPI_CLI_PATH) 之前,添加 -all-static

 

编译

make LDFLAGS=-ldl
make install

如果在编译中出现错误:

/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcrypto.a(threads_pthread.o): in function `CRYPTO_THREAD_init_local':
(.text+0x125): undefined reference to `pthread_key_create'
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcrypto.a(threads_pthread.o): in function `CRYPTO_THREAD_set_local':
(.text+0x157): undefined reference to `pthread_setspecific'
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcrypto.a(threads_pthread.o): in function `CRYPTO_THREAD_cleanup_local':
(.text+0x177): undefined reference to `pthread_key_delete'
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcrypto.a(threads_pthread.o): in function `openssl_init_fork_handlers':
(.text+0x1d3): undefined reference to `pthread_once'
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcrypto.a(threads_pthread.o): in function `CRYPTO_THREAD_get_local':
(.text+0x143): undefined reference to `pthread_getspecific'
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcrypto.a(dso_dlfcn.o): in function `dlfcn_pathbyaddr':
(.text+0x451): undefined reference to `dladdr'
collect2: error: ld returned 1 exit status
make: *** [Makefile:253: sapi/cli/php] Error 1

在EXTRA_LIBS 行尾加入:-ldl,当然我还加入了 -lpthread ,因为它还报了pthread 的错误。

EXTRA_LIBS = -lcrypt -lresolv -lcrypt -lrt -lm -lssl -lcrypto -lcrypt -lcrypt -lpthread -ldl

(至于里面为什么有重复的 -lcrypt 我也不清楚)

 

 

静态编译 swoole

将 swoole 下载解压并移动到 php-src/ext/swoole 目录中,再执行强制清理脚本就行了:

 ./buildconf --force

附上的我的编译参数

./configure LDFLAGS=-static --prefix=/usr/local/php/php7.4/ --with-config-file-path=/usr/local/php/php7.4/  --enable-sockets  --enable-json --with-openssl --disable-all --enable-static=yes --enable-shared=no --enable-inline-optimization --disable-phpdbg --disable-fpm --disable-cgi --enable-swoole

官方介绍

https://wiki.swoole.com/wiki/page/760.html

 

参考:

http://blog.gaoyuan.xyz/2014/04/09/statically-compile-php/

https://www.cnblogs.com/rooney/archive/2012/07/05/2577705.html

發表評論
StudioEIM - 冒险者讲习所
0:00