我需要从nodejs app执行bash脚本。通常我会做这样的事情:
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 characters 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
似乎head -n 1
已经终止,但cat /dev/urandom
仍在运行。
问题:如何从nodejs执行脚本以使其不挂起?
ENV:
Ubuntu 16.04
v6.11.2
答案 0 :(得分:0)
这是由NodeJS ignores SIGPIPE signal引起的。当产生子进程时,生成的子进程也会忽略SIGPIPE信号。
因为cat
命令在读取第一行后head
终止后管道断开时不会终止。因此cat
永远从/dev/urandom
读取数据。
在NodeJS的未来版本之一中应该是fixed(不确定哪个版本)。目前我只使用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); // <----