运行 来自 Nodejs 的 shell 脚本

Running a shell script from Nodejs

我有一个 shell 脚本 start.sh,它的工作是在后台生成多个 java 进程,然后像这样正常退出:

java -jar jar1.jar &
java -jar jar2.jar &
...
exit 0

打印出一堆输出:

Starting jar1
Starting jar2
...

现在我希望 nodejs 调用 start.sh 跟踪输出,这样我就可以在 starter.sh 完成后对其进行操作

问题是 Nodejs 认为 starter.sh 只有在所有已启动的 java 进程都已死时才完成。 这很奇怪,因为从 shell 开始,starter.sh 立即退出并且与 java 进程不再有任何关系

如何使 starter.sh 在从节点调用时表现相同?

这是我用来生成的代码 starter.sh:

  const process = spawn('starter.sh', []);

  process.stdout.on('data', (data) => {
    console.log(`stdout: ${data}`);
    // prints 'Starting jarx' like expected
  });

  process.stderr.on('data', (data) => {
    console.log(`stderr: ${data}`);
  });

  process.on('close', (code) => {
    console.log(`child process exited with code ${code}`);
    // Not called unless all the spawned java processes are dead :(
  });

我感觉我的问题与子进程与父节点共享 stdio 有关。事实上,如果 java 进程没有 stdout 可写,它们会写到哪里。因此节点必须等待它们完成才能考虑 starter.sh done

我已经决定给子进程它自己的 stdio 并将 starter.sh 输出写入文件:

  const out = fs.openSync('/tmp/command.out', 'w');
  const err = fs.openSync('/tmp/command.err', 'w');

  const process = spawn(command, args, {detached: true, stdio: ['ignore', out , err]});
  process.unref();

  process.on('close', (code) => {
    console.log(`child process exited with code ${code}`);
    console.log(fs.readFileSync('/tmp/command.out', 'utf8');
    console.log(fs.readFileSync('/tmp/command.err', 'utf8'));
  });

这样 close 回调会在 starter.sh 完成后立即调用,我仍然可以访问它的输出。