博客是用 WordPress 搭建的,最新版的 WordPress 有个功能是健康度检查,报告有一个问题为 PHP 版本过低。实话说并不算低,最新是 7.4 而我用的是 7.2。但看着总是不顺眼,于是安装了 PHP 7.4,准备迁移。
安装好之后,没有动搏客,而是用另一个虚拟站点做测试,加载页面直接显示“Mcrypt PHP extension required.”
这个 mcrypt 库对于很多 PHP 用户是个爱憎交加的玩意儿,从 7.1 以后官方就不再支持了,但会有不少老的开发库依赖它。其实目前的 PHP 7.2 能够正常运行也是做了额外的努力才安装上的。作为一个懒懒的程序员,本能上极其抗拒再大动干戈来一遍,思忖可以和当前的 PHP 7.2 共享。
于是把 /etc/php/7.2/cli/conf.d/20-mcrypt.ini
往 7.4
的相应路径下复制了一份,fpm
下的也同样处理。service php7.4-fpm restart
后刷新页面,错误仍在。
只好执行 php7.4 -v
查看,发现报一个警告如下:
PHP Warning: PHP Startup: Unable to load dynamic library ‘mcrypt.so’ (tried: /usr/lib/php/20190902/mcrypt.so (/usr/lib/php/20190902/mcrypt.so: cannot open shared object file: No such file or directory), /usr/lib/php/20190902/mcrypt.so.so (/usr/lib/php/20190902/mcrypt.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
作为一个聪明的程序员,这也难不住咱。到 /usr/lib/php
下查看,另有一个目录名为 20170718
,其中就有 mcrypt.so
文件,显然是 7.2 所用的,复制一份到 20190902
目录好了。
不料还不成,又报以下错:
PHP Warning: PHP Startup: mcrypt: Unable to initialize module
Module compiled with module API=20170718
PHP compiled with module API=20190902
These options need to match
in Unknown on line 0
看来文件里自带了硬编码的版本兼容信息,用 stings mcrypt.so | grep 2017
得到如下结果:
API20170718,NTS
/usr/include/php/20170718/Zend
/usr/include/php/20170718/main
/usr/include/php/20170718/main/streams
/usr/include/php/20170718/ext/standard
/usr/include/php/20170718/Zend
/usr/include/php/20170718/main
/usr/include/php/20170718/main/streams
推测第一行就是关键所在。作为一个坏坏的程序员,俺直觉把这个字符串改了就可以。
最简单的办法是,scp
把文件拉回本地,用一个十六进制编辑器改掉后再推到远程。但作为一个时不时挑战自我的程序员,就地在主机上解决掉问题才有成就感。用哪一套组合拳呢?
首先当然要知道那个 API 字串的便宜,直觉又一次灵验,看了看 strings
命令的帮助,发现加上 -td
的参数(d
意为十进制,o
和 x
也可以,对应八进制和十六进制)即可,偏移值为 30041
。
其次是要想办法把新串覆盖进去。这种指定位置覆盖内容的活儿,dd
命令显然是首选:
printf 'API20190902' | dd of=mcrypt.so seek=30041 bs=1 count=11 conv=notrunc
执行完毕后使用 dhex
工具进行了文件的比较确认,修补成功。但用 php -v
验证,API 不兼容的错误信息依旧,应该是在其他地方还有需要处理的细节,本次实践暂告失败,但似乎也并非全无收获。