从node.js运行脚本,捕获stdout,通过Web套接字发送

时间:2014-07-05 15:16:02

标签: javascript node.js

我通过node.js调用Ruby脚本,它通过stdout返回数据,我已经设法让节点将一些数据发送到它的网络套接字但是我缺少行并且不要#39;我真的很了解我在做什么。从研究看起来我似乎正在使用流,但我无法理解大部分文档,因为这些都是非常新的并且在我脑海中:(

当通过bash shell运行时,我的Ruby脚本输出如下到stdout;

{"element":"SENS02","data":{"type":"SEN","descr":"T100"}}
{"element":"SENS01","data":{"type":"SEN","descr":"    "}}
{"element":"LED1","data":{"type":"LED","state":"1"}}
{"element":"LED2","data":{"type":"LED","state":"0"}}

当在控制台上运行时,一切都很好 - 当我通过我的node.js脚本调用它时,我只获得每一行,例如节点将输出;

{"element":"SENS02","data":{"type":"SEN","descr":"T100"}}
{"element":"LED1","data":{"type":"LED","state":"1"}}

我的node.js脚本部分如下;

var cp = require('child_process');
var tail = cp.spawn('test.rb');

// Get updates from ruby script //
tail.stdout.on('data', function(chunk) {
   var pumper = chunk.toString().slice(0,58);
   var closer = JSON.parse(pumper);
   socket.emit('MAP.room1', closer);
});

如果有人可以提供帮助,我偶尔也会遇到以下错误!

  

未定义:0

     

^ SyntaxError:意外的输入结束       在Object.parse(native)

我需要能够输出从我的ruby脚本收到的每一行。任何回答的人请使用我自己的代码,而不是随机的例子,因为它只是在试图理解与什么相关的东西以及它对我来说意味着什么时才会让我感到困惑。我试过看过.pipe,但所有的例子让我感到困惑,我不明白如何使它们适应我自己的脚本。什么是ruby的输出一次是JS Objects 1行,我需要我的web套接字一次发出完全相同的东西。

完成console.log(chunk.toString())以获得可读输出 它已经解除了一些奇怪的东西 - 额外的换行或其他东西。

控制台的输出是;

{"element":"SENS02","data":{"type":"SEN","descr":"T100"}}
{"element":"SENS01","data":{"type":"SEN","descr":"    "}}

{"element":"LED1","data":{"type":"LED","state":"1"}}
{"element":"LED2","data":{"type":"LED","state":"0"}}

我怎样才能绕过这个?这可能导致我的其他意外的输入结束'错误?

如果我var pumper = chunk.slice(0,-1); console.log(pumper.toString()),那么我得到如上所示的输出,没有奇数/额外/胭脂换行符。我仍然没有进一步向前推送,以便将其输出到Web套接字。

我可以从网络套接字中取出它,但它显示我仍然不知何故?!?!

["{\"element\":\"SENS02\",\"data\":{\"type\":\"SEN\",\"descr\":\"T100\"}}\n{\"element\":\"SENS01\",\"data\":{\"type\":\"SEN\",\"descr\":\" \"}}"]} 我需要像在控制台那样将它重新变成单一的扁平线......

因此,按照下面的建议,我现在通过使用此代码获得所需的输出。我仍然在控制台中登录): Unexpected end of input,这似乎来自我从Ruby脚本获得的其他换行符。运行脚本几天没有崩溃,出现所有数据都完整无缺并解析到Web套接字。我仍然需要阅读并完全理解for正在做什么,否则它似乎解决了我的问题。

tail.stdout.on('data', function(chunk) {
var closer = chunk.toString()

var sampArray = closer.split('\n');

 for (var i = 0; i < sampArray.length; i++) {
  try {
   var newObj = JSON.parse(sampArray[i]);
socket.emit('MAP.room1', newObj);
   } catch (err) {
console.log('): ' + err.message);
  }
 }
});

2 个答案:

答案 0 :(得分:0)

尝试spawn你使用ruby脚本,exec正在缓冲输出,这可能就是你所看到的原因。

See

P.S

JSON.parse块包裹try-catch并打印失败时失败的数据

答案 1 :(得分:0)

如果您打算对每个数据块使用JSON.parse(),则需要在换行符\n上预先解析每个块。

JSON.parse无法将换行符分隔的多个对象解析为同一字符串中的2个不同对象

这些单独有效:

"{\"element\":\"SENS02\",\"data\":{\"type\":\"SEN\",\"descr\":\"T100\"}}"
"{\"element\":\"SENS02\",\"data\":{\"type\":\"SEN\",\"descr\":\"T100\"}}\n"
"{\"element\":\"SENS02\",\"data\":{\"type\":\"SEN\",\"descr\":\"T100\"}}\r\n"

这不是:

"{\"element\":\"SENS02\",\"data\":{\"type\":\"SEN\",\"descr\":\"T100\"}}\n{\"element\":\"SENS01\",\"data\":{\"type\":\"SEN\",\"descr\":\"    \"}}"

如果目的是解析整个数据结构,那么您需要将ruby脚本的输出重新组织为类似于下面的内容。

{
    "elements": [
        {
            "name": "SENS02",
            "data": {
                "type": "SEN",
                "descr": "T100"
            }
        },
        {
            "name": "SENS01",
            "data": {
                "type": "SEN",
                "descr": "    "
            }
        },
        {
            "name": "LED1",
            "data": {
                "type": "LED",
                "state": "1"
            }
        },
        {
            "name": "LED2",
            "data": {
                "type": "LED",
                "state": "0"
            }
        }
    ]
}

您可能如何解析输入(粗略示例)

var sample = "{\"element\":\"SENS02\",\"data\":{\"type\":\"SEN\",\"descr\":\"T100\"}}\n{\"element\":\"SENS01\",\"data\":{\"type\":\"SEN\",\"descr\":\"    \"}}\n{\"element\":\"LED1\",\"data\":{\"type\":\"LED\",\"state\":\"1\"}}\n{\"element\":\"LED2\",\"data\":{\"type\":\"LED\",\"state\":\"0\"}}";

var sampArray = sample.split('\n');

for (var i = 0; i < sampArray.length; i++) {
    try {
        var newObj = JSON.parse(sampArray[i]);
        // socket.emit(newObj);
    } catch (err) {
        console.log('): ' + err.message);
    }
}