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

Node.js child_process spawn管道报错:Cannot call write after a stream was destroyed

解决Node.js child_process中"Cannot call write after a stream was destroyed"错误

这个错误我之前在处理进程间管道通信时也碰到过,核心问题是流的生命周期没有被正确管理——当multimon-ng的stdin流因为进程退出、崩溃或其他原因被销毁后,你的代码还在尝试从rtl_fm的stdout往里面写数据,自然就会抛出这个错误。另外你的multimon-ng参数还有个小问题,也可能导致进程提前退出触发这个错误。

下面是具体的解决步骤和修正后的代码:

1. 改用pipe()代替手动写入

手动监听data事件并调用write()的方式很容易忽略流的状态变化,而child_process的pipe()方法会自动处理流的销毁、错误和终止逻辑,比手动实现可靠得多。替换掉你原来的ps.stdout.on('data')代码:

// 替换原来的data事件监听
ps.stdout.pipe(grep.stdin);

2. 修正multimon-ng的参数

你的参数里'-f', 'alpha /dev/stdin'是错误的——-f alpha是指定输出格式,/dev/stdin是输入源,需要拆成两个独立的参数,否则multimon-ng会解析出错提前退出:

const grep = spawn('multimon-ng', [
  '-t', 'raw',
  '-a', 'POCSAG512', '-a', 'POCSAG1200', '-a', 'POCSAG2400',
  '-f', 'alpha', // 单独指定输出格式
  '/dev/stdin'  // 单独指定输入源
]);

3. 添加错误监听和进程退出处理

为了排查问题和避免无用进程残留,给两个进程的错误事件、stderr输出和退出事件添加监听:

  • 监听进程启动错误,比如rtl_fm找不到SDR设备、multimon-ng未安装等情况
  • 监听进程的stderr输出,能看到具体的运行错误信息
  • 当其中一个进程退出时,主动终止另一个进程,避免资源浪费

完整修正后的代码

const { spawn } = require('child_process');

// 替换成你实际要监听的频率
const frequency = '152.000'; 

const ps = spawn('rtl_fm', ['-s', '22050', '-f', `${frequency}M`]);
const grep = spawn('multimon-ng', [
  '-t', 'raw',
  '-a', 'POCSAG512', '-a', 'POCSAG1200', '-a', 'POCSAG2400',
  '-f', 'alpha',
  '/dev/stdin'
]);

// 自动管理流管道
ps.stdout.pipe(grep.stdin);

// 处理multimon-ng的解码输出
grep.stdout.on('data', (data) => {
  const decodedMsg = data.toString().trim();
  console.log('解码得到POCSAG消息:', decodedMsg);
  // 在这里添加你处理解码数据的逻辑
});

// rtl_fm相关错误监听
ps.on('error', (err) => {
  console.error('rtl_fm进程启动失败:', err.message);
});

ps.stderr.on('data', (data) => {
  console.error('rtl_fm运行错误:', data.toString());
});

// multimon-ng相关错误监听
grep.on('error', (err) => {
  console.error('multimon-ng进程启动失败:', err.message);
});

grep.stderr.on('data', (data) => {
  console.error('multimon-ng运行错误:', data.toString());
});

// 进程退出联动处理
grep.on('exit', (code, signal) => {
  console.log(`multimon-ng已退出,退出码: ${code}, 终止信号: ${signal}`);
  ps.kill(); // 终止rtl_fm进程
});

ps.on('exit', (code, signal) => {
  console.log(`rtl_fm已退出,退出码: ${code}, 终止信号: ${signal}`);
  grep.kill(); // 终止multimon-ng进程
});

这些改动不仅解决了"Cannot call write after a stream was destroyed"的错误,还让整个进程间通信的逻辑更健壮,方便你排查运行中的各种问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:20:10