在meteor中读取shell命令的输出

时间:2014-05-20 08:21:37

标签: javascript shell meteor stdout

我试图ping远程服务器以检查它是否在线。流程是这样的:

1)用户插入目标主机名

2)Meteor执行命令' nmap -p 22主机名'

3)Meteor读取并解析输出,以检查目标的状态。

我已经能够异步执行一个命令,例如mkdir,它允许我稍后验证它是否有效。

不幸的是,我似乎无法等待回复。我的代码在/server/poller.coffee里面是:

Meteor.methods

 check_if_open: (target_server) ->

     result = ''

     exec = Npm.require('child_process').exec

     result = exec 'nmap -p ' + target_server.port + ' ' + target_server.host

     return result

这应该同步执行exec,不应该吗?使用Futures,ShellJS,AsyncWrap的任何其他方法都失败了,一旦安装了节点包,流星就拒绝启动。我似乎只能通过meteor add(mrt)安装。

位于/client/views/home/home.coffee的我的客户端代码是:

Template.home.events 

    'submit form': (e) ->

        e.preventDefault()
        console.log "Calling the connect button"

        server_target =
           host: $(e.target).find("[name=hostname]").val()
           port: $(e.target).find("[name=port]").val()
           password: $(e.target).find("[name=password]").val()


        result = ''

        result = Meteor.call('check_if_open', server_target)

        console.log "You pressed the connect button" 

        console.log ' ' + result

结果始终为null。结果应该是子进程对象,并且具有stdout属性,但此属性为null。

我做错了什么?我如何阅读输出?我不得不异步地做这件事吗?

1 个答案:

答案 0 :(得分:2)

您需要使用某种异步包装,child_process.exec是严格异步的。以下是使用期货的方法:

# In top-level code:
# I didn't need to install anything with npm,
# this just worked.
Future = Npm.require("fibers/future")

# in the method:
fut = new Future()
# Warning: if you do this, you're probably vulnerable to "shell injection"
# e.g. the user might set target_server.host to something like "blah.com; rm -rf /"
exec "nmap -p #{target_server.port} #{target_server.host}", (err, stdout, stderr) ->
  fut.return [err, stdout, stderr]
[err, stdout, stderr] = fut.wait()
if err?
  throw new Meteor.Error(...)
# do stuff with stdout and stderr
# note that these are Buffer objects, you might need to manually
# convert them to strings if you want to send them to the client

在客户端上调用方法时,必须使用异步回调。客户端没有光纤。

console.log "You pressed the connect button"
Meteor.call "check_if_open", server_target, (err, result) ->
  if err?
    # handle the error
  else
    console.log result