You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP exec()传递大Base64字符串触发unable to fork问题求助

解决PHP exec传递大Base64到Node脚本时的"unable to fork"问题

问题原因

不是内存限制,是命令行参数总长度超出系统上限。不同操作系统对单个进程的命令行参数总长度有严格限制(比如Linux默认约128KB,Windows更小),大体积图片的Base64编码字符串很容易突破这个限制,导致exec无法fork新进程。

解决方法

方法1:通过标准输入(STDIN)传递数据

这是最可靠的方式,完全避开命令行参数长度限制:

PHP代码修改

<?php
$path = './exampleDir/example.png';
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = base64_encode(file_get_contents($path));
$base64 = "data:image/".$type.";base64,".$data;

$cfPage = "index";
$iwidth = "400";
$iheight = "425";
$iaspect = $iwidth/$iheight;

// 构造命令,用escapeshellarg处理参数避免注入和解析错误
$cmd = sprintf(
    'node ./scripts/test.js %s %s %s',
    escapeshellarg($cfPage),
    escapeshellarg(uniqid()),
    escapeshellarg($iaspect)
);

// 用proc_open创建管道,传递STDIN数据
$descriptorspec = [
    0 => ['pipe', 'r'], // PHP写入,Node读取的标准输入
    1 => ['pipe', 'w'], // Node写入,PHP读取的标准输出
    2 => ['pipe', 'w']  // 标准错误输出
];

$process = proc_open($cmd, $descriptorspec, $pipes);

if (is_resource($process)) {
    // 将Base64写入STDIN
    fwrite($pipes[0], $base64);
    fclose($pipes[0]);

    // 可选:读取Node脚本的输出和错误信息
    $output = stream_get_contents($pipes[1]);
    $errors = stream_get_contents($pipes[2]);
    fclose($pipes[1]);
    fclose($pipes[2]);

    // 等待进程结束并回收资源
    proc_close($process);
}
?>

Node脚本修改(test.js)

// 从命令行获取常规参数
const cfPage = process.argv[2];
const uniqId = process.argv[3];
const aspect = process.argv[4];

// 从STDIN读取Base64数据
const fs = require('fs');
const base64Data = fs.readFileSync(process.stdin.fd, 'utf8').trim();

// 后续业务逻辑示例
console.log('接收的Base64长度:', base64Data.length);

方法2:通过临时文件传递数据

如果STDIN方式不兼容现有逻辑,可将Base64写入临时文件,让Node脚本读取:

PHP代码修改

<?php
$path = './exampleDir/example.png';
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = base64_encode(file_get_contents($path));
$base64 = "data:image/".$type.";base64,".$data;

$cfPage = "index";
$iwidth = "400";
$iheight = "425";
$iaspect = $iwidth/$iheight;

// 创建临时文件存储Base64
$tmpFile = tempnam(sys_get_temp_dir(), 'img_base64_');
file_put_contents($tmpFile, $base64);

// 传递临时文件名作为参数
$cmd = sprintf(
    'node ./scripts/test.js %s %s %s %s',
    escapeshellarg($cfPage),
    escapeshellarg(uniqid()),
    escapeshellarg($iaspect),
    escapeshellarg($tmpFile)
);

exec($cmd, $output, $exitCode);

// 处理完成后删除临时文件
unlink($tmpFile);
?>

Node脚本修改(test.js)

const cfPage = process.argv[2];
const uniqId = process.argv[3];
const aspect = process.argv[4];
const tmpFilePath = process.argv[5];

// 读取临时文件中的Base64数据
const fs = require('fs');
const base64Data = fs.readFileSync(tmpFilePath, 'utf8').trim();

// 后续业务逻辑示例
console.log('接收的Base64长度:', base64Data.length);

注意事项

  • 所有命令行参数必须用escapeshellarg()包裹,避免命令注入攻击和特殊字符导致的解析错误。
  • 临时文件方式要确保文件权限正确,且处理完成后立即删除,避免磁盘冗余占用。

内容的提问来源于stack exchange,提问作者이재동

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 16:06:28