I have a node js server, which triggers a shell script that I have. The code is as follows (simple Hello World example):
var http = require("http");
function onRequest(request, response) {
console.log("Request received.");
response.writeHead(200, {"Content-Type": "text/plain"});
var spawn = require('child_process').spawn;
//executes my shell script - main.sh when a request is posted to the server
var deploySh = spawn('sh', [ 'main.sh' ]);
//This lines enables the script to output to the terminal
deploySh.stdout.pipe(process.stdout);
//Simple response to user whenever localhost:8888 is accessed
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
The code works perfectly - A server is started and whenever the page is loaded (request) in the browser, the shell script runs on the server and outputs its results on the terminal.
Now, I want to display that result back to the client browser instead of just "Hello World". How to do that? Please note that the script takes 4 - 5 seconds to execute and generate a result.
I have a node js server, which triggers a shell script that I have. The code is as follows (simple Hello World example):
var http = require("http");
function onRequest(request, response) {
console.log("Request received.");
response.writeHead(200, {"Content-Type": "text/plain"});
var spawn = require('child_process').spawn;
//executes my shell script - main.sh when a request is posted to the server
var deploySh = spawn('sh', [ 'main.sh' ]);
//This lines enables the script to output to the terminal
deploySh.stdout.pipe(process.stdout);
//Simple response to user whenever localhost:8888 is accessed
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
The code works perfectly - A server is started and whenever the page is loaded (request) in the browser, the shell script runs on the server and outputs its results on the terminal.
Now, I want to display that result back to the client browser instead of just "Hello World". How to do that? Please note that the script takes 4 - 5 seconds to execute and generate a result.
Share Improve this question asked Mar 3, 2014 at 12:08 user3374766user3374766 452 silver badges5 bronze badges 1- github./mettamage/browserbash – gauravds Commented Apr 20, 2019 at 17:26
2 Answers
Reset to default 8You have two options:
Option 1:
Convert your function to use the child_process.exec
method instead of child_process.spawn
method. This will buffer all data sent to stdout
in memory and allow you to send as one chunk across the line to the browser:
var http = require("http"),
exec = require("child_process").exec;
function onRequest(request, response) {
console.log("Request received.");
response.writeHead(200, {"Content-Type": "text/plain"});
//executes my shell script - main.sh when a request is posted to the server
exec('sh main.sh', function (err, stdout, stderr) {
if (err) handleError();
//Print stdout/stderr to console
console.log(stdout);
console.log(stderr);
//Simple response to user whenever localhost:8888 is accessed
response.write(stdout);
response.end();
});
}
http.createServer(onRequest).listen(8888, function () {
console.log("Server has started.");
});
Option 2:
If you want to keep the child_process.spawn
method, you will need to introduce real time networking into your stack that pushes data events to the browser upon receiving events from the child process. Take a look at socket.io or (remended) SockJS for setting up real time munication between your server and client.
Side Note:
I wanted to point out a flaw in your code above that will end up hurting you in the long run in your future endeavors with node.
function onRequest(request, response) {
console.log("Request received.");
response.writeHead(200, {"Content-Type": "text/plain"});
var spawn = require('child_process').spawn;
In the last line above, you are requiring the child_process
module on each request. Not only does this add unnecessary overhead to each request, you will end up running into module caching issues if you are not careful. It is remended that all calls to require happen at the top of the module scope and no where else. The only time its "acceptable" to make require calls in the middle of your logic is when building truly synchronous CLI tools — but even then its best to keep all requires organized at the top of your module scope for readability.
var http = require('http'),
process = require('child_process');
var server = http.createServer(function (req,res){
res.writeHead(200,{'content-type':'text/html'});
process.exec('ls',function (err,stdout,stderr) {
if(err){
console.log("\n"+stderr);
res.end(stderr);
} else {
console.log(stdout);
res.end("<b>ls displayes files in your directory</b></br>"+stdout+"</br>");
}
});
}).listen(3000);