Javascript 尝试在node.js中执行shell脚本的同步行为
我对node.js很陌生,我将它用作服务器来接收http。从浏览器获取请求,进行一些处理并将结果返回到浏览器 处理过程实际上是使用phantom.js/casper.js抓取一个网站,由于在node.js中使用casper.js的复杂性,我使用shell脚本将其作为子进程执行 当我运行下面的代码并从浏览器发出请求时,响应似乎出现在shell脚本运行之前。我尝试使用异步库以串联方式运行步骤,以便run.sh在添加到响应之前运行并返回一个值,但它似乎不是这样工作的。有人能看出我的愚蠢错误吗 提前谢谢Javascript 尝试在node.js中执行shell脚本的同步行为,javascript,node.js,shell,Javascript,Node.js,Shell,我对node.js很陌生,我将它用作服务器来接收http。从浏览器获取请求,进行一些处理并将结果返回到浏览器 处理过程实际上是使用phantom.js/casper.js抓取一个网站,由于在node.js中使用casper.js的复杂性,我使用shell脚本将其作为子进程执行 当我运行下面的代码并从浏览器发出请求时,响应似乎出现在shell脚本运行之前。我尝试使用异步库以串联方式运行步骤,以便run.sh在添加到响应之前运行并返回一个值,但它似乎不是这样工作的。有人能看出我的愚蠢错误吗 提前谢谢
var express = require('express');
var app = express();
var sys = require('sys');
var exec = require('child_process').exec;
var async = require('async');
var auth = express.basicAuth('test', 'pass');
var server = app.listen(3000, function() {
console.log('Listening on port %d', server.address().port);
});
var result;
//app.use(auth);
app.get('/free/:u/:p', auth, function(req, res) {
async.series([
function(callback){
var puts = function (error, stdout, stderr) {
result = stdout;
}
exec("./run.sh " + req.params.u + " " + req.params.p, puts);
callback(null);
},
function(callback){
res.writeHead(200,{'Content-Type':'application/json'});
res.send(result)
callback(null);
}
]);
});
app.get('/', function(req, res) {
res.send('Hello!');
});
您没有异步调用callbacknull。你需要把它放进去
此外,您不应该使用全局结果变量—它甚至在请求之间是全局的,可能会将数据泄漏到不同的客户端—arghh!。对于这个微不足道的链,几乎没有理由使用async.js
app.get('/free/:u/:p', auth, function(req, res) {
exec("./run.sh " + req.params.u + " " + req.params.p, function (error, stdout, stderr) {
res.writeHead(200,{'Content-Type':'application/json'});
res.send(stdout);
});
});
请注意不转义shell参数所带来的安全问题。基本上,您遇到的问题是,调用exec时就像调用同步函数一样,而实际上它是异步的 因此,你实际上应该:
exec("./run.sh " + req.params.u + " " + req.params.p, puts, function(){
callback(null);
});
或者简单地这样做,因为无论如何,您不必关心异步系列中的函数传递的函数参数
exec("./run.sh " + req.params.u + " " + req.params.p, puts, callback)
原因是您运行shell命令,然后立即调用回调,该回调运行响应的下一个函数 要修复它,您可以像这样更改puts函数puts并删除callbacknull:
虽然这种方法有效,但最好使用async.瀑布而不是async.series。它允许您将每个函数的结果传递给下一个函数。因此,您不需要全局结果变量。感谢您的帮助advncd,这也很有效,但我想我使用的是不必要的async Ryperfect,与此相比,我的代码真的很差!现在我有一个不同的问题,它只有在注释掉res.writeHead部分时才会运行。它似乎在写头前运行send。这是我得到的错误:错误:发送邮件后无法设置邮件头。还有-你提到的安全问题是什么-我有点迷路了..嗯,不应该。代码中还有其他发送吗?我所说的脆弱性是一个基本问题。浏览/免费//rm+-r+\。或者更好:不要!除上述“/”路线代码外,不读取代码中的其他发送。。我理解为什么现在这是一个巨大的安全问题!有道理。不过,我并没有真正理解逃跑的解决方案。我是否需要使用某种正则表达式来排除可能意外执行的任何内容?不,您需要将字符串参数用引号括起来,并使用正则表达式来转义任何字符串分隔符。或者您只需使用spawn而不是exec,exec会接受一系列参数并适当地转义它们。好的,谢谢。因此,从我读到的内容来看,spawn发回一个数据流,而不是在使用exec时将其限制在缓冲区大小。我找不到关于shell参数自动转义的任何资料。此外,我还必须捕获流,这将使我回到最初的异步问题。。。啊。你有没有可能改用spawn为我重写上面的内容?
var express = require('express');
var app = express();
var sys = require('sys');
var exec = require('child_process').exec;
var async = require('async');
var auth = express.basicAuth('test', 'pass');
var server = app.listen(3000, function() {
console.log('Listening on port %d', server.address().port);
});
var result;
//app.use(auth);
app.get('/free/:u/:p', auth, function(req, res) {
async.series([
function(callback){
var puts = function (error, stdout, stderr) {
result = stdout;
callback(null); //added here
}
exec("./run.sh " + req.params.u + " " + req.params.p, puts);
//callback(null); //commented
},
function(callback){
res.writeHead(200,{'Content-Type':'application/json'});
res.send(result)
callback(null);
}
]);
});
app.get('/', function(req, res) {
res.send('Hello!');
});