【问题标题】:node.js: How to detect an empty stdin stream?node.js:如何检测空的标准输入流?
【发布时间】:2012-03-03 03:53:48
【问题描述】:

我有一个 node.js 脚本/服务器,它在启动时从标准输入读取一些输入。但是,有时没有要传入的数据。这很麻烦,因为在这种情况下似乎既没有调用data 也没有调用end 事件。如何检测 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();

【问题讨论】:

  • 你试过 process.stdin.on('error', function(){}) 吗?
  • 或 gfm.stdout.on('error', function() {})
  • 找到解决方案了吗?这似乎是不可能的。
  • 这在 Windows 和 Linux 上都非常适合我。我每次都收到end 事件,即使从/dev/null 重定向stdin 也是如此。会不会是别的东西?在一些相关的说明中,您应该使用流接口将您的stdin 传递到gfm
  • 在我看来,您的 github-flavored-markdown.rb 脚本在从标准输入读取时阻塞,这可以解释这种行为。

标签: node.js stdin detect


【解决方案1】:

来自process.stdinend 事件检测到空的或没有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);

如预期:

$ echo test | node pipe.js
<Buffer 74 65 73 74 0a>
EOF
$ echo -n | node pipe.js
EOF
$ node pipe.js < /dev/null
EOF
$

【讨论】:

  • 正确但有一点需要注意,只运行node pipe.js 将使程序保持空闲状态,因为甚至没有 EOF 字符。更多关于Cameron Tacklind's answer
【解决方案2】:

我相信可能发生的事情是,您根本没有提供标准输入。

Øystein Steimler 的示例显示您将 /dev/null 输入到您的应用中:

node pipe.js /null

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

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

尝试运行这个:

cat < /dev/null

现在尝试运行:

cat

它没有退出,因为它正在等待标准输入。您可以在终端中输入并按回车键发送到程序。在收到您可以使用 ctrl+d

执行的 EOF 之前,它仍然不会退出(并等待更多输入)

【讨论】:

  • 我怎样才能检测到这种情况何时发生?我没有收到任何 readline closeprocess.stdin end 事件。
  • @spiffytech 看我的回答
【解决方案3】:

您可以做的就是让您的应用接受-s 之类的参数,从而使其从标准输入中读取。

LiveScript 的 CLI 工具就是这样做的:

-s, --stdin read stdin

【讨论】:

    【解决方案4】:

    stdin 的运作方式,你想要的不是直接可能的。

    正如其他人指出的那样,如果没有像 &lt; /dev/null 这样的东西来生成 EOFend 事件将永远不会触发。否则程序等待终端发送^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);
    

    【讨论】:

      猜你喜欢
      • 2019-09-25
      • 2017-06-10
      • 1970-01-01
      • 2019-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多