说明
近日折腾打包了 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_CLI
和 BUILD_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
Comments