node.js:如何检测空的stdin流?

时间:2012-02-10 17:12:37

标签: node.js stdin detect

我有一个node.js脚本/服务器,它在启动时读取stdin的一些输入。但是,有时候没有数据要传入。这很麻烦,因为在这种情况下似乎都没有调用dataend事件。如何在node.js代码中检测到这种情况?

我想避免在输入结尾添加特殊的“结束”字符,以免给客户带来不便。相关代码如下:

  var newHTML = '';
  var gfm = spawn(__dirname + '/node_modules/docter/bin/github-flavored-markdown.rb');
  process.stdin.on('data', function(chunk){
    gfm.stdin.write(chunk);
  });
  process.stdin.on('end', function(){
    gfm.stdin.end();
  });
  gfm.stdout.on('data', function(data) {
    newHTML += data;
  });
  gfm.on('exit',function(ecode){
    socket.emit('newContent', newHTML);
  });
  process.stdin.resume();

4 个答案:

答案 0 :(得分:5)

来自end的{​​{1}}事件检测到空的或没有STDIN流。

这个简单的脚本process.stdin证明了:

stdin.js

不同的情景:

process.stdin.on( 'data', function(data) { console.log( data ) } );
process.stdin.on( 'end', function() { console.log( 'EOF' ) } );

此脚本$ echo test | node stdin.js <Buffer 74 65 73 74 0a> EOF $ echo -n | node stdin.js EOF $ node stdin.js < /dev/null EOF $ 表明使用管道生成的子进程非常有效:

pipe.js

正如所料:

var spawn = require('child_process').spawn;
var cat = spawn( '/bin/cat' );
cat.stdout.on( 'data', function(data) { console.log( data ) } );
cat.stdout.on( 'end', function() { console.log( 'EOF' ) } );

process.stdin.pipe(cat.stdin);

答案 1 :(得分:5)

我相信可能发生的事情是,你根本没有给出斯坦丁。

ØysteinSteimler的示例显示您将 / dev / null 提供给您的应用:

  

node pipe.js&lt;的/ dev / null的

但是,当你根本没有将stdin流式传输到应用程序时,永远不会解决。只运行node pipe.js不会退出,因为它仍在等待 stdin

您可以使用其他unix程序自行测试,例如cat

尝试运行:

cat < /dev/null

现在尝试运行:

cat

它不会退出,因为它正在等待stdin。您可以输入终端并按Enter键发送到程序。它仍然不会退出(并等待更多输入),直到它收到 EOF ,您可以使用 ctrl + d

答案 2 :(得分:2)

你可以做的就是让你的应用程序接受-s这样的参数,使其从标准输入读取。

这就是LiveScript的CLI工具:

-s, --stdin read stdin

答案 3 :(得分:1)

stdin的工作方式无法直接实现。

正如其他人指出的那样,如果没有end之类的东西来生成 EOF < /dev/null事件将永远不会触发。否则,程序将等待终端发送^D

对您可能有用的另一种方法是,如果stdin上没有任何活动,则设置一个超时时间,该超时时间将在短时间内到期。这不理想,但是可以工作:

function handleData(chunk) {
  //clearTimeout(timeout);
  gfm.stdin.write(chunk);
}
function handleEnd() {
  //clearTimeout(timeout);
  gfm.stdin.end();
}
function handleTimeout() {
  process.stdin.removeListener('data', handleData);
  process.stdin.removeListener('end', handleEnd);

  // Do whatever special handling is needed here.
  gfm.stdin.end();
}

const timeoutMilliseconds = 100;

process.stdin.on('data', handleData);
process.stdin.on('end', handleEnd);
const timeout = setTimeout(handleTimeout, timeoutMilliseconds);

// You could skip the rest of this code if you just add `clearTimeout(timeout)`
// to the body of `handleData` and `handleEnd` but that would call `clearTimeout` excessively.
function stopTimeout() {
  process.stdin.removeListener('data', stopTimeout)
  process.stdin.removeListener('end', stopTimeout);
  clearTimeout(timeout);
}

process.stdin.on('data', stopTimeout);
process.stdin.on('end', stopTimeout);