2017-08-23 122 views
0

我需要从nodejs应用程序执行bash脚本。通常我会做这样的事情:如何从nodejs正确执行shell脚本

var childProcess = require('child_process'); 
childProcess.execFile('./test.sh', function (error, stdout, stderr) { 
    console.log(error, stdout, stderr); 
}) 

但我最近遇到了一个bash脚本,永远不会终止,当它像这样执行。这是再现这一问题的小例子:

#!/bin/bash 
LC_CTYPE=C cat /dev/urandom | tr -dc "a-zA-Z0-9" | fold -w 8 | head -n 1 
  • LC_CTYPE=C - 强制tr解释一切为ASCII字符
  • tr -dc "a-zA-Z0-9" < /dev/urandom - 读伪随机字节,丢弃一切,除了a-zA-Z0-9
  • fold -w 8 - 换行输出成8行字符
  • head -n 1 - 读取第一行(8个字符)

当从终端中执行正常工作,并将其立即终止:

# ./test.sh 
0J5hsGeh 

当使用执行以上的NodeJS脚本它只是挂起:

# node test.js 

screenshot from htop command

看来是head -n 1已经终止,但cat /dev/urandom仍在运行。

问题:如何从nodejs执行脚本,使其不挂起?

ENV:

  • OS:Ubuntu 16.04
  • 版本的NodeJS:v6.11.2
+0

尝试添加'exit'命令你的bash脚本 –

+0

结束在你的家当设置-x或通过bash的-x运行它,我们将不得不发生了什么 –

+0

家伙更清晰的画面,感谢建议。但是,他们没有帮助。脚本末尾的'exit'不会执行任何操作,在这种情况下甚至不会执行,因为前一行永远不会终止。'-x'也没有帮助,因为脚本从不完成,所以'-x'生成的输出不会被打印。无论如何,我不是试图调试bash脚本。我试图找出为什么通过nodejs执行它有所作为。 – Prvaak

回答

0

这是一个事实,即ignores SIGPIPE signal的NodeJS造成的。当产生子过程时,SIGPIPE信号也被产生的子过程忽略。

因为cat命令在读取第一行后终止head后管道损坏时不终止。所以cat永远从/dev/urandom读取数据。

它应该是fixed在未来版本的NodeJS(不知道哪个虽然)之一。现在我只使用that issue的解决方法。

var childProcess = require('child_process'); 
process.on('SIGPIPE', noop); // <---- 
childProcess.execFile('./test.sh', function (error, stdout, stderr) { 
    console.log(error, stdout, stderr); 
}) 
process.removeListener('SIGPIPE', noop); // <----