linux环境下curl上传文件设置postfiled导致php-fpm子进程崩溃

1. 问题描述

1). 出现问题过程

1.我在使用curl请求接口时,突然出现了请求某几个接口时发起请求的一端报502的情况,但是502出现以后再次进入其它页面也是很正常的,在查看nginx日志以后显示:

2024/10/21 09:36:00 [error] 21876#21876: *3150 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: , server: localhost, request: "GET /index.php/Admin/index/index/clientid/58174.html HTTP/1.1", upstream: "fastcgi://unix:/home/im_user/im_server/im_webserver/php/var/php.sock:", host: "ip:8000", referrer: "http://ip:8000/index.php/Home/login/index/clientid/58174.html"

2.接着我去查询了php-fpm的错误日志,内容是php-fpm的子进程退出了,又重新启动了,导致在报502以后其它页面还是正常的:

[21-Oct-2024 09:36:56] WARNING: [pool www] child 25252 exited with code 127 after 228293.010424 seconds from start
[21-Oct-2024 09:36:56] NOTICE: [pool www] child 30319 started

日志中可以看进程退出又重启的过程。

2). 代码排查定位

1.在看日志不确定以后我去查看了curl的相关代码

function test($url,$post_data = array(), $timeout = 5, $method = CURL_POST,$header=[])
{

    $methos_m = ['GET', 'POST', 'PUT', 'DELETE'];
    $method=$methos_m[$method];
    $method = strtoupper($method);
    if (!in_array($method, $methos_m)) {
        return false;
    }
    switch ($method) {
        case "PUT":
            $header[] = "X-HTTP-Method-Override: PUT";
            break;
        case "DELETE":
            $header[] = "X-HTTP-Method-Override: DELETE";
            break;
        default:
    }


    $data = $post_data ;
    $ch = curl_init();

    // https请求 不验证证书和hosts
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

    curl_setopt ($ch, CURLOPT_URL, $url);

    if ($header){
        curl_setopt ($ch, CURLOPT_HTTPHEADER, $header);
    }


    if ($method=='POST'){
        curl_setopt ($ch, CURLOPT_POST, 1);
    }



    if($data){
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }

    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_HEADER, false);

    $file_contents = curl_exec($ch);
    $res = curl_error($ch);
    $code = curl_errno($ch);

    curl_close($ch);

    return $file_contents;
}

2.在日志加断点以后发现问题出现于

if($data){
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}

在$data为数组传值时设置CURLOPT_POSTFIELDS会导致php-fpm子进程崩溃,这个我并不能理解其中的原理

3). 尝试修改出现的后续问题

1.http_build_query处理
在确定参数问题以后我通过http_build_query进行参数的处理

    if (is_array($data))
    {
        $data=http_build_query($data);
    }

这样处理了以后常规参数不再报导致php-fpm退出
2.处理以后文件传输问题
因为需求上有一些服务器之间的文件传输通过curl进行,类似于

$a['file']=new \CURLFile(__DIR__.'/test.php');
$res =test("http://127.0.0.1:8000/test.php",$a);

这样的传输方式通过http_build_query会导致最终只能传输文件路径,
但是不通过http_build_query会导致php-fpm子进程崩溃

<2024-10-21 10:38>补充:在尝试php版本替换为php7.4以后不会出现传入数组导致子进程崩溃的问题

4). 当前系统

NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

5). php版本

php版本:8.3.9

2. 当前疑惑

是否有能处理curl_setopt($ch, CURLOPT_POSTFIELDS, $data);传入数组时导致php-fpm子进程退出,
或者兼容处理curl传输文件处理的方式

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
最佳答案

经过反复调试,在寻找了一台干净的centos机器上对php8.3.9使用了同样的参数进行重新编译,过程中缺少的依赖直接使用yum进行升级,再次调试的时候这个问题没有再出现,应该是运维在编译时的环境影响了curl的功能

3个月前 评论
讨论数量: 11

看你问题描述,nginx错误日志的时间09:36:00,fpm的日志进程退出的时间09:36:56,从时间上看,两者没什么关联关系,下图为fpm exited code chatgpt解释。

file

4个月前 评论
nnsl (楼主) 4个月前

上传的文件应该是过大了,超过默认进程处理能力,连接被重置了, 修改下PHP.INI 内POST 文件大小试一下

4个月前 评论
nnsl (楼主) 4个月前
raybon (作者) 3个月前
nnsl (楼主) 3个月前
raybon (作者) 3个月前

你这个问题确实比较奇特,我查了下官方文档,本地尝试也是比较正常,没什么问题的,php8和7都可以正常的请求,不会出现进程直接挂掉的情况,建议是直接使用cli下执行,用trace进行跟踪调试,看下有没有什么有用的信息

4个月前 评论
轻语过往 (作者) 4个月前
轻语过往 (作者) 4个月前

经过反复调试,在寻找了一台干净的centos机器上对php8.3.9使用了同样的参数进行重新编译,过程中缺少的依赖直接使用yum进行升级,再次调试的时候这个问题没有再出现,应该是运维在编译时的环境影响了curl的功能

3个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!