简体   繁体   English

如何从Node.js正确执行Shell脚本

[英]How to properly execute shell script from nodejs

I need to execute a bash script from nodejs app. 我需要从nodejs应用程序执行bash脚本。 Usually I would do something like this: 通常我会做这样的事情:

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

But I recently ran into a bash script that never terminated when it was executed like that. 但是我最近遇到了一个bash脚本,当它那样执行时,它从未终止。 This is a minimal example that reproduces the issue: 这是重现此问题的最小示例:

#!/bin/bash
LC_CTYPE=C cat /dev/urandom | tr -dc "a-zA-Z0-9" | fold -w 8 | head -n 1
  • LC_CTYPE=C - force the tr to interpret everything as ascii characters LC_CTYPE=C强制tr将所有内容解释为ASCII字符
  • tr -dc "a-zA-Z0-9" < /dev/urandom - read pseudorandom bytes, discard everything except a-zA-Z0-9 tr -dc "a-zA-Z0-9" < /dev/urandom读取伪随机字节,丢弃除a-zA-Z0-9以外a-zA-Z0-9所有内容
  • fold -w 8 - wrap output into lines 8 characters long fold -w 8将输出包装成8个字符长的行
  • head -n 1 - read the first line (8 characters) head -n 1读取第一行(8个字符)

When executed from terminal it works fine and it terminates immediately: 从终端执行时,它可以正常工作并立即终止:

# ./test.sh 
0J5hsGeh

When executed using the above nodejs script it just hangs: 使用上面的nodejs脚本执行时,它会挂起:

# node test.js

htop命令的屏幕截图

It seems that the head -n 1 already terminated but the cat /dev/urandom is still running. head -n 1似乎已经终止,但cat /dev/urandom仍在运行。

Question: How to execute the script from nodejs so that it does not hang? 问题: 如何从nodejs执行脚本,以使其不会挂起?

Env: 信封:

  • OS: Ubuntu 16.04 操作系统: Ubuntu 16.04
  • Nodejs version: v6.11.2 Node.js版本: v6.11.2

This is caused by the fact that NodeJS ignores SIGPIPE signal . 这是因为NodeJS 忽略了SIGPIPE信号 When a subprocess is spawned the SIGPIPE signal is ignored by the spawned subprocess as well. 生成子流程时,生成的子流程也会忽略SIGPIPE信号。

Because of that the cat command does not terminate when the pipe is broken after the head terminated after reading the first line. 因此,在读取第一行后终止head之后,当管道断开时, cat命令不会终止。 So the cat reads data from /dev/urandom forever. 因此, cat会永远从/dev/urandom读取数据。

It should be fixed in one of the future versions of NodeJS (not sure which though). 应该在NodeJS的未来版本之一中修复它(尽管不确定是哪一个)。 For now I just use the workaround from 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); // <----

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM