I am trying to make a program in Node.js that, after receiving a Unix-like via command POST
, executes it and displays the output in real time in the browser.
This is the code I am using to run the commands:
exec(myCommand, function(err, stdout, stderr){
sys.print('stdout: ' + stdout);
sys.print('stderr: ' + stderr);
if(err !== null) {
console.log('EXECUTION ERROR: ' , err);
}
}
However, the output of stdout
comes in the form of Buffer
, so it's not clear to me how I can make the browser display its content as it increases.
My idea is that if, for example, I execute the command apt-get update
, it will show what it is doing in real time, and not all the output at once when it has finished.
It occurred to me that I could save the contents of the buffer to a string repeatedly, and then have the browser, via JavaScript, check for updates frequently, but that seems like a bit of a hack to me, not to mention that It's not as fast as I would like.
In conclusion, how can I do this as quickly and simply as possible?
In order for the output to be displayed as it is output and not all at once, you must use
spawn
instead of usingexec
. I think it fits more to what you want to achieve. If you want to understand the difference between the two functions you can visit this link .For it to be displayed in real time you should use
socket.io
, it is much more reliable than using GET requests at intervals to get what the command is printing and you can use it as a transport to start executing them.Here I put a demo that sends the commands from any client and the output is reflected in all the others that are connected. I send the command using the same socket but you can modify it and use POST if you want.
Since you don't specify if other frameworks can be used, I used it using only node.js and socket.io.
And this is the file
cmd.html
that is sent to the clientThe method to use is
spawn
instead ofexec
, since the latter waits for the command to finish (and that's what you want to avoid).The stdout (from child_process) is a readable (read) stream and the response (from http) is a writable (write) stream, so what you're missing is a pipe, but in the console it's better known like
|
).The code would be something like:
If you want to do some kind of processing in the middle, you will have to do it using these same streams:
stdout.pipe(colorize).pipe(beautify).pipe(res)
.The two readings I can recommend are (both in English unfortunately): stream-handbook , Some Libraries I use to build web-apps both from Substack. In the second there are many libraries that can be used to modify the stream.