将PHP编译为静态二进制文件

15

我需要在一个PHP安装有点问题的系统上运行一个PHP脚本。与其尝试解决这些问题,我想要将我的代码和它自己的PHP二进制文件打包在一起(我可以执行可执行文件)。我想要一个简单的PHP二进制文件,其中已经编译了我需要的所有模块。我的一般过程是:

./configure --enable-static --enable-cli --disable-all

这给我提供了一个没有任何扩展的PHP二进制文件。从这里开始,我可以添加我需要的扩展。例如,要添加curl和json支持

./configure --enable-static --enable-cli --disable-all --with-curl --enable-json

这似乎通常可以正常工作。我的脚本需要libxml支持与AWS进行交互。因此,我将--enable-libxml --enable-simplexml添加到配置命令中。当我将二进制文件复制到远程计算机时,尝试使用XML库时出现错误,看起来像是:

/usr/lib/x86_64-linux-gnu/libxml2.so.2: version `LIBXML2_2.9.0' not found

显然它正在动态链接到libxml2。我认为这意味着虽然PHP扩展是静态编译到PHP中的,但PHP扩展正在使用的库不是。运行ldd可以确认这一点:

$ ldd sapi/cli/php
linux-vdso.so.1 =>  (0x00007fff05cf3000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f3c69f82000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f3c69d68000)
libcurl.so.4 => /lib64/libcurl.so.4 (0x00007f3c69afc000)
librt.so.1 => /lib64/librt.so.1 (0x00007f3c698f4000)
libm.so.6 => /lib64/libm.so.6 (0x00007f3c695ed000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f3c693e8000)
libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f3c691cf000)
libxml2.so.2 => /lib64/libxml2.so.2 (0x00007f3c68e66000)
libz.so.1 => /lib64/libz.so.1 (0x00007f3c68c4f000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3c68890000)
libfreebl3.so => /lib64/libfreebl3.so (0x00007f3c6860f000)
libidn.so.11 => /lib64/libidn.so.11 (0x00007f3c683db000)
libssh2.so.1 => /lib64/libssh2.so.1 (0x00007f3c681b1000)
libssl3.so => /lib64/libssl3.so (0x00007f3c67f72000)
libsmime3.so => /lib64/libsmime3.so (0x00007f3c67d44000)
libnss3.so => /lib64/libnss3.so (0x00007f3c679fc000)
libnssutil3.so => /lib64/libnssutil3.so (0x00007f3c677d0000)
libplds4.so => /lib64/libplds4.so (0x00007f3c675cb000)
libplc4.so => /lib64/libplc4.so (0x00007f3c673c6000)
libnspr4.so => /lib64/libnspr4.so (0x00007f3c67188000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3c66f6a000)
libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007f3c66d20000)
libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007f3c66a40000)
libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007f3c6680a000)
libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007f3c66606000)
liblber-2.4.so.2 => /lib64/liblber-2.4.so.2 (0x00007f3c663f7000)
libldap-2.4.so.2 => /lib64/libldap-2.4.so.2 (0x00007f3c661a4000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3c6a1d7000)
liblzma.so.5 => /lib64/liblzma.so.5 (0x00007f3c65f7f000)
libssl.so.10 => /lib64/libssl.so.10 (0x00007f3c65d12000)
libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007f3c6592b000)
libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007f3c6571c000)
libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007f3c65518000)
libsasl2.so.3 => /lib64/libsasl2.so.3 (0x00007f3c652fa000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f3c650d6000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f3c64e6f000)

正如您所看到的,有许多库与我的php二进制文件动态链接。我猜测它通常是工作的,因为我的目标系统有很多相同的库,但没有libxml库。

所以我的问题是,如何创建一个完全静态的二进制文件,没有共享库的依赖关系。我意识到这将使我的可执行文件变得更大,但这也意味着我可以将我的php可执行文件与代码打包在一起,在任何64位linux机器上都能正常运行。


2
修复 PHP 安装是一个好主意,比起其他方案要好上千倍。 - user557846
共享系统,无法访问。 - Eric Anderson
2
但是它们允许二进制安装吗? - user557846
我知道这是可以做到的。一段时间以前,Magento的某个人就曾经这样做过,以在PHP 4服务器上启用PHP 5。http://www.magentocommerce.com/knowledge-base/entry/installing-magento-on-a-php4-server - txyoji
2个回答

5
我已经找到了一种解决方案,虽然有点凌乱,但我仍将libxml作为共享对象与我的代码包含在一起,并使用LD_LIBRARY_PATH环境变量,使其加载我的共享库对象,而不是安装在系统上的那些对象。
理想情况下,我希望只有一个二进制文件,但这种解决方案可以工作。它还具有稍微使用系统库的优点,如果适用的话(即我的代码包不必包含所有共享库)。但我仍然有兴趣知道是否有办法编译完全静态的php二进制文件。

嗨,Erick,你有没有想到更好的方法来做这件事?我开发了一个完整的基于Web的医院系统,使用php、jquery、HTML、MySQL、JavaScript和HTML编写,医院要求我帮助他们将其编译为一个可执行文件。它在一个RPM Linux服务器上运行,并且不同地理区域的医院的几个分支也连接到它。 - Joseph
1
没有一个二进制文件。我最终使用了一段时间描述的LD_LIBRARY_PATH。后来,该项目迁移到Docker,使我能够更好地控制PHP的版本,而不管环境本身支持什么。 - Eric Anderson

0

Statifier是一个几乎停滞不前的项目,它不支持内存随机化。Ermine太昂贵了。 - Viktor Joras
现在,https://appimage.org 也是一种事物。它不是“静态”二进制文件,而是一个包含所有依赖项的软件包,类似于 Mac OS 应用程序的工作方式。 - txyoji
一个新的项目,用于构建静态二进制文件的 PHP > 7.4 版本 - https://github.com/crazywhalecc/static-php-cli - txyoji

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接