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

Node.js调用spawn/exec执行Bash命令遇ENOENT错误问题

问题背景

在Debian 10(GNU bash 5.0.3)系统中,以下Bash命令在终端直接粘贴可正常执行:

documents=("/data/sice.pdf" "/das00/12ser.pdf");bash ./clean-pdfs.sh "${documents[*]}"

但使用Node.js的exec或spawn调用该命令时均失败:

  • 使用exec时出现括号相关报错
  • 改用spawn后,出现无明确指向的ENOENT错误

相关Node.js代码:

const { exec } = require('child_process');
command = `documents=(${pdfPaths});` + 'bash ./clean-pdfs.sh "${documents[*]}"'
console.log(command);

const subProcess = require('child_process')
const lsChildProcess = subProcess.spawn(command)

lsChildProcess.stdout.on('data', (data) => {
  console.log(data);
})

lsChildProcess.on('error', function(err) {
 console.log(err);
});

运行后得到的错误信息:

{ Error: spawn documents=("/data/Traa.pdf" "/dater.pdf");bash ./clean-pdfs.sh "${documents[*]}" ENOENT
    at Process.ChildProcess._handle.onexit (internal/child_process.js:240:19)
    at onErrorNT (internal/child_process.js:415:16)
    at process._tickCallback (internal/process/next_tick.js:63:19)
  errno: 'ENOENT',
  code: 'ENOENT',
  syscall:
   'spawn documents=("/daice.pdf" "/daer.pdf");bash ./clean-pdfs.sh "${documents[*]}"',
  path:
   'documents=("/dace.pdf" "/daer.pdf");bash ./clean-pdfs.sh "${documents[*]}"',
  spawnargs: [] }
错误原因

spawn方法的工作逻辑是直接调用系统中的可执行文件,而非像终端那样通过shell解析命令字符串。你传入的整个命令串并不是系统中存在的可执行程序,因此触发ENOENT(找不到指定文件/程序)错误。

解决方案

方案1:正确使用spawn调用shell命令

将bash作为可执行程序传入,通过-c参数让bash执行你的完整命令串:

const { spawn } = require('child_process');
// 假设pdfPaths是已处理好的带引号的路径字符串,或直接传入数组转义后的格式
const pdfPaths = '"/data/Traa.pdf" "/dater.pdf"';
const lsChildProcess = spawn('bash', [
  '-c',
  `documents=(${pdfPaths}); bash ./clean-pdfs.sh "${documents[*]}"`
]);

// 处理标准输出
lsChildProcess.stdout.on('data', (data) => {
  console.log(data.toString());
});

// 处理错误输出
lsChildProcess.stderr.on('data', (data) => {
  console.error(data.toString());
});

lsChildProcess.on('error', (err) => {
  console.error(err);
});

方案2:修正exec的写法

exec默认会通过shell解析命令,之前的报错是因为路径字符串的转义问题。需要确保路径数组被正确转成bash可识别的格式:

const { exec } = require('child_process');
const pdfPathsArray = ["/data/Traa.pdf", "/dater.pdf"];
// 转义路径中的引号,确保bash能正确解析
const formattedPaths = pdfPathsArray
  .map(path => `"${path.replace(/"/g, '\\"')}"`)
  .join(' ');
const command = `documents=(${formattedPaths}); bash ./clean-pdfs.sh "${documents[*]}"`;

exec(command, (error, stdout, stderr) => {
  if (error) {
    console.error(`执行错误: ${error.message}`);
    return;
  }
  console.log(`输出: ${stdout}`);
  if (stderr) {
    console.error(`错误输出: ${stderr}`);
  }
});

方案3:简化调用(推荐)

无需在shell中定义数组,直接将路径作为参数传给clean-pdfs.sh,Node.js的数组展开语法可直接传递多个参数:

const { spawn } = require('child_process');
const pdfPaths = ["/data/Traa.pdf", "/dater.pdf"];
// 直接将路径作为脚本参数传入
const lsChildProcess = spawn('bash', ['./clean-pdfs.sh', ...pdfPaths]);

lsChildProcess.stdout.on('data', (data) => console.log(data.toString()));
lsChildProcess.stderr.on('data', (data) => console.error(data.toString()));
lsChildProcess.on('error', (err) => console.error(err));

此时在clean-pdfs.sh中可通过$@获取所有传入的路径参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:30:54