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

Node.js spawn创建lzip子进程无法获取stdout输出问题排查

问题原因

你当前代码的核心问题是没有等待lzip子进程完成全部处理流程,仅等待了stdin的写入和关闭操作,就直接读取了tarContent的内容。此时lzip可能还在处理输入数据、还没开始向stdout输出解压后的内容,所以data事件还未触发,buffer自然是空的。

修复方案

快速修复原有代码

你只需要新增对lzip子进程生命周期的监听,等进程正常退出后再处理结果即可,同时建议增加错误监听排查问题:

import { requestBinary } from 'by-request';
import { spawn } from 'child_process';
import { min } from '@tubular/math';

export async function tarLzToZip(url: string): Promise<void> {
  const lzData = await requestBinary(url, { headers: { 'User-Agent': 'curl/7.64.1' } });
  const lzipProc = spawn('lzip', ['-d'], { stdio: ['pipe', 'pipe', process.stderr] });
  let tarContent = Buffer.alloc(0);

  // 监听stdout数据
  lzipProc.stdout.on('data', data => {
    tarContent = Buffer.concat([tarContent, data], tarContent.length + data.length);
  });

  // 新增错误监听,方便排查问题
  lzipProc.on('error', err => {
    throw new Error(`lzip进程启动失败: ${err.message}`);
  });
  lzipProc.stderr.on('data', data => {
    console.error('lzip错误输出:', data.toString());
  });

  // 写入输入数据
  for (let offset = 0; offset < lzData.length; offset += 4096) {
    await new Promise<void>((resolve, reject) => {
      lzipProc.stdin.write(lzData.slice(offset, min(offset + 4096, lzData.length)), err => {
        if (err)
          reject(err);
        else
          resolve();
      });
    });
  }

  await new Promise<void>((resolve, reject) => {
    lzipProc.stdin.end((err: any) => {
      if (err)
        reject(err);
      else
        resolve();
    });
  });

  // 新增:等待lzip进程退出后再返回结果
  await new Promise<void>((resolve, reject) => {
    lzipProc.on('close', code => {
      if (code === 0) {
        resolve();
      } else {
        reject(new Error(`lzip进程异常退出,错误码: ${code}`));
      }
    });
  });

  console.log('data length:', tarContent.length);
}

更优方案

你最终采用的流pipe方案是更推荐的实现方式:不需要手动拼接buffer、不需要手动处理分块写入,Node.js的流机制会自动处理背压、数据传输和生命周期管理,性能和稳定性都更高,也更符合Node.js的异步IO设计理念。

需要注意的事项:

  • 确保运行环境已经安装了lzip工具,否则spawn会抛出找不到命令的错误
  • 处理大文件时,手动拼接buffer会占用大量内存,用流边处理边写入目标文件/输出可以大幅降低内存占用
  • 不要忽略子进程的错误监听,避免异常情况无法排查

内容的提问来源于stack exchange,提问作者kshetline

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 08:18:02