编译安装PHP

本文以centos stream 9和php8.1为例,描述编译思路

Unix 系统下的安装 核心配置选项列表

安装编译需要的工具和依赖

如何确定需要的依赖,看一下你要用的php扩展,需要那些系统组件和组件对应的系统库

可以查看扩展库归类 ,找到安装/配置说明可以查看详细说明,举例说明 GD库 配置参数详细说明

使用dnf或yum install xxx安装

#编译器相关工具
deltarpm gcc gcc-c++ make cmake autoconf bison re2c 
#基础库
glibc glibc-devel glib2 glib2-devel
#网络和数据库相关
curl curl-devel libcurl libcurl-devel sqlite-devel sqlite-devel libsqlite3x-devel
#文本字符数据格式
oniguruma oniguruma-devel libxml2 libxml2-devel libxslt libxslt-devel libtidy-devel libtidy libicu-devel 
#图片格式 字体
gd-devel
freetype freetype-devel libjpeg libjpeg-devel libjpeg-turbo libjpeg-turbo-devel libpng libpng-devel libtiff-dev libgif-dev libwebp-devel
#文件解压缩
 zlib zlib-devel libzip-devel  bzip2 bzip2-devel
#数学和加密
openssl openssl-devel libmcrypt libmcrypt-devel mhash mhash-devel mcrypt libargon2 libsodium

手动编译安装

有些库没有系统二进制包,不能直接使用命令安装需要下载来,或者版本太低达不到php的要求,需要手动编译安装

libiconv libargon2 libsodium

依赖说明

deltarpm 一种rpm包,优化了体积

bison 是一种通用目的的分析器生成器

re2c 一个将正则表达式转化成基于C语言标识的预处理器

oniguruma 正则表达式库,使用–enable-mbstring需要安装

freetype 可移植的字体引擎,它提供统一的接口来访问多种字体格式文件 –with-freetype

libicu  Unicode 支持、软件国际化编码 –enable-intl 开启intl扩展

libxml2 xml操作库 –enable-xml 开启

libxslt 是一种样式转换标记语言,可以将XML资料档转换为另外的XML或其它格式 –with-xsl

libtidy 处理html的一种扩展 –with-tidy 很少用

libiconv 字符编码转换库 启用–with-iconv

查看编译选项

./configure --help

创建用户和组

id -g www >/dev/null 2>&1
[ $? -ne 0 ] && groupadd www
id -u www >/dev/null 2>&1
[ $? -ne 0 ] && useradd -g www -M -s /sbin/nologin www

常用的编译参数选项,来自oneinstack脚本,php8.1.sh安装源码

./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc \
    --with-config-file-scan-dir=/usr/local/php/etc/php.d \
    --with-fpm-user=www --with-fpm-group=www --enable-fpm --disable-fileinfo \
    --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd \
    --with-iconv --with-freetype --with-jpeg --with-zlib \
    --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-exif \
    --enable-sysvsem --with-curl --enable-mbregex \
    --enable-mbstring --with-password-argon2 --with-sodium=/usr/local --enable-gd --with-openssl \
    --with-mhash --enable-pcntl --enable-sockets --enable-ftp --enable-intl --with-xsl \
    --with-gettext --with-zip=/usr/local --enable-soap --disable-debug
#防止libiconv导致的报错
make ZEND_EXTRA_LIBS="-L/usr/local/libiconv/lib/ -liconv"
make install

如上启用了fpm,mysqli,mysqland,iconv,gd,xml,bcmath,shmop,exif,sysvsem,curl,mbstring,Password hashing,mhash,openssl,pcntl,sockets,ftp,intl,xsl,gettext,zip,soap

根据项目实际需求来启用需要的参数,比如,项目用cli框架swoole或者workman之类的可以不启用fpm

PHP debug 笔记

简单方式

修改php错误级别,var_dump(),print_r(),die(),exit() 人工断点。

Pecl扩展方式

yasd

出现了coredump

[24-Jul-2022 08:55:01] WARNING: [pool yangliuan] child 14755 said into stdout: “[yasd] Connect IDE failed (Connection refused), please check that the IDE is in a listening state”

child 14756 exited on signal 11 (SIGSEGV – core dumped) after 991.060461 seconds from start

zend xdebug

框架debug工具包

Laravel Telescope

laravel-debugbar

maximebf/php-debugbar

gdb 调试 coredump

什么是coredump

相关文章

coredump调试记录 – PHP篇

使用GDB调试PHP core dump

Generate PHP core dumps on segfaults in PHP-FPM

一个低概率的PHP Core dump

coredump配置、产生、分析以及分析示例 

什么是Core Dump?

Webman/Workman使用笔记

数据库迁移文件Phinx

如何刷新所有回滚

不能直接刷新所有回滚,创建完第一个迁移之后,使用断点命令打上断点,方便后边刷新所有回滚,这样只会滚两次就可以了。

phinx breakpoint -e development -t 20120103083322(第一个迁移的时间版本)

数据模拟的库

改用 https://fakerphp.github.io/#installation,原先的过时了。

setInterval轮询问题记录

一个electron项目,在使用setInterval轮询时,出现了网络崩溃的系统错误。 在setInterval中执行console.log显示setInterval还会执行,但是axios不会重新发起ajax请求。其中getControlStatus轮询后端接口获取数据

renderer.js:1 Uncaught (in promise) SystemError [ERR_SYSTEM_ERROR]: A system error occurred: undefined returned undefined (undefined)
    at Object.networkInterfaces (os.js:203)
    at t.default (renderer.js:12)
    at a.<anonymous> (renderer.js:26)
    at r (renderer.js:26)
    at Generator._invoke (renderer.js:26)
    at Generator.forEach.e.<computed> [as next] (renderer.js:26)
    at i (renderer.js:1)
    at renderer.js:1
    at new Promise (<anonymous>)
    at new t (renderer.js:12)
addCodeToName @ internal/errors.js:306
SystemError @ internal/errors.js:165
NodeError @ internal/errors.js:250
checkError @ os.js:64
hidden @ internal/errors.js:294
networkInterfaces @ os.js:203
t.default @ renderer.js:12
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26
setInterval (async)
resetControlStatusRequest @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
handleControlOrder @ renderer.js:26
(anonymous) @ renderer.js:26
r @ renderer.js:26
(anonymous) @ renderer.js:26
forEach.e.<computed> @ renderer.js:26
i @ renderer.js:1
(anonymous) @ renderer.js:1
Promise.then (async)
i @ renderer.js:1
(anonymous) @ renderer.js:1
t @ renderer.js:12
(anonymous) @ renderer.js:1
getControlStatus @ renderer.js:26
(anonymous) @ renderer.js:26

setInterval存在的问题

对自己调用的代码是否报错会无视掉。即自己调用的代码即使错误,也会继续执行下去,这就是导致上述问题获取接口失效原因。

setInterval无视网络延迟
我们在向服务器轮询数据的时候,如果发生网络卡顿的情况,客户端收到请求响应的时间大于interval循环的时间。而setInterval会无视任何情况下继续定时执行,这就会导致了用户的客户端里充斥着客户端的请求

参考文章

项目经历之——轮询后端接口(setInterval、websocket)

MDN文档:确保执行时间短于定时器时间间隔

PHP安装PECL扩展

查看模块是否安装

phpinfo(); 页面调用函数
php -m 查看已安装模块
php –ini 查看php.ini的位置
php –ri gd 查看模块信息

GD

查看是否支持webp

php --ri gd | grep WebP

Imagick

举例,查看imagick是否安装webp支持

 php --ri imagick | grep WEBP

安装imagick支持webp php处理

模块安装

php安装 pear 文档

wget http://pear.php.net/go-pear.phar
#指定php目录安装pear
sudo /usr/local/php/bin/php go-pear.phar

安装之后可以使用pear 和pecl命令安装扩展

方式一 使用pear相关命令

PEAR命令 安装扩展文档

pear install extension_name
pear upgrade extension_name
pear install --onlyreqdeps html_page2

参数
-onlyreqdeps (install required dependencies (依赖) only) 安装需要依赖
–alldeps (install all dependencies (依赖) ) 安装全部依赖

方式二

pecl命令文档

方式三

phpize源码编译安装 (共享/动态 扩展) 以redis为例

上https://pecl.php.net/下载好扩展的源码包 redis-6.2.7.tar.gz

tar -zxvf redis-6.2.7.tar.gz
cd redis-6.2.7
/usr/local/php/bin/phpize 
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install 
#写入配置
 echo 'extension=redis.so' > /usr/local/php/etc/php.d/redis.ini

扩展静态编译到php中

参考文章

PHP PECL 使用

PHP XML操作FAQ

加载h5标签报错

Tag xxx invalid in Entity

$html_dom = new DOMDocument();
//关闭h5标签可能的报错
libxml_use_internal_errors(true);
$html_dom->loadHTML($html5);

DOMDocument 保存 xml时中文出现乱码

$html_dom = new DOMDocument();
$html_dom->loadHTML('<?xml encoding="UTF-8">'.$html);

PHP的DOM内部是utf8机制的,在loadHTML时,是通过检查字符中meta的charset来设置编码的,如果没有charset,就当iso8859进行处理了,而这种情况下进行saveXML时,输出来的却是utf8,所以就看到乱码了.

对不包含<meta>标签和<body>标签的富文本字符串处理特别有用

Go开发生态 常用笔记

环境搭建

gvm 开发环境推荐使用版本管理脚本

你有同时使用多版本 Go 语言的需求吗,那就快使用多版本管理利器 GVM 吧!

环境准备:如何安装和配置一个基本的 Go 开发环境?

 工作区和GOPATH

软件生态

Go中文文档

开发工具

awesome-go

go的一些常用包

参考文章

为什么很多公司都转型go语言开发?Go语言能做什么

Go 语言的整洁架构之道 —— 一个使用 gRPC 的 Go 项目整洁架构例子

Laravel使用ftp上传

接手一个laravel项目,使用ftp上传报错如下

`ftp_rawlist(): php_connect_nonb() failed: Operation now in progress (115)`

原因配置文件中选项没有写全

'driver' => 'ftp',
'host' => '*******',
'port' => 21,
'username' => '*******',
'password' => '*******',
'passive' => false, //此选项需要加
'ignorePassiveAddress' => true, //此选项需要加

参考文章

How to fix `ftp_rawlist(): php_connect_nonb() failed: Operation now in progress (115)`

原理解析

有时间补充

报错如下

500 Illegal PORT command.
配置项改为true
'passive' => true,