我试图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。
我做错了什么?我如何阅读输出?我不得不异步地做这件事吗?
答案 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