How to access terminal in Nodejs - javascript

I want to build a nodejs application which will do some automatic work for me . But I want to know if I can execute terminal commands in nodejs . Is there any module which will be helpful to access command line interface ? Suppose I want to run this command code . or ifconfig or cd. So how can I do this from nodejs application ?
I know I can run nodejs from my terminal But I want to access terminal and do whatever I want .like installing other softwares from terminal Like executing 'apt install package-name'

So what you want is a portable method of running system specific functionality. Thankfully, nodejs has a module to do this called the child_process module. For more specific information you can glance at the linked documentation, but a basic example goes like this:
const { spawn } = require('child_process');
// Here we make the call making sure to list the command first and the arguments as the next parameter in a list
const diff = spawn('diff', ["texta.txt", "textb.txt"])
// We can also log the output of this function with
diff.stdout.on('data', (data) => {
console.log(data.toString());
});
// or we can log the exit code with
diff.on('exit', (code) => {
console.log(`Child exited with code ${code}`);
});

Related

Use puppeteer with imgui-js

In case the lenght of the question might be scary, the summary of the question is how to interact with a front end app from a node server. Puppeteer usage should come along with that request solved I believe. Question is large because I explained all my failed attempts to achieve backend code (puppeteer) work in the browser. Apart from building and running the repo that although its easy right following the instructions might take a some time, I believe the question should be feasable for a javascript/node regular programmer. There it goes, thanks for reading.
I cloned, built and ran imgui-js repository succesfully.
I want to use it along with puppeteer for a small app. All the npm commands inside and stuff tried are inside the mentioned imgui-js project.
I tried:
1.- Run the node example from the project: With npm run-script start-example-node.
This runs the example/index.js script, but nothing is drawn as we are not in the browser and the window is undefined. Can be checked debugging in the main.ts:
if (typeof(window) !== "undefined") {
window.requestAnimationFrame(done ? _done : _loop);
}
So I do not understand the purpose of this example in the repo.
Edit: Seems it can be to have the client-server comunication done, but I do not now how to do this.
2.- Puppeteer browserify:
I followed the browserify hello world.
Just a summary of the steps:
npm install -g browserify
npm i puppeteer
Go to the build folder to generate de bundle.js for my const puppeteer = require('puppeteer'); script, so cd example, cd build, browserify myScript.js -o bundle.js
Add <script src="./build/bundle.js"></script> to the example/index.html.
I obtain this error:
Uncaught TypeError: System.register is not a function
at Object.96.puppeteer (bundle.js:19470:8)
at o (bundle.js:1:265)
at r (bundle.js:1:431)
at bundle.js:1:460
I also tried browserifying main.js along with my script: browserify main.js myScript.js -o bundle.js. Same error.
3.- Try to setup puppeter with the rollup module bundler: following this resource among others. So doing:
npm install --save-dev rollup tape-modern puppeteer
npm install --save-dev rollup-plugin-node-resolve
npm install --save-dev rollup-plugin-commonjs
npm install --save-dev sirv tape-browser-color
And tried to add that the the imgui-js rollup.config.js configuration file.
Think its not working because all the server setup at the npm start and so on is not performed with rollup.
4.- Puppeteer-web: Following the steps of this resource I tried to run puppeteer in the browser.
npm i puppeteer-web
Code in the client and the server:
Client:
<script src="https://unpkg.com/puppeteer-web"></script>
<script>
const browser = await puppeteer.connect({
browserWSEndpoint: `ws://0.0.0.0:8080`, // <-- connect to a server running somewhere
ignoreHTTPSErrors: true
});
const pagesCount = (await browser.pages()).length;
const browserWSEndpoint = await browser.wsEndpoint();
console.log({ browserWSEndpoint, pagesCount });
</script>
Server (server.js script):
const httpProxy = require("http-proxy");
const host = "0.0.0.0";
const port = 8080;
async function createServer(WSEndPoint, host, port) {
await httpProxy
.createServer({
target: WSEndPoint, // where we are connecting
ws: true,
localAddress: host // where to bind the proxy
})
.listen(port); // which port the proxy should listen to
return `ws://${host}:${port}`; // ie: ws://123.123.123.123:8080
}
const puppeteer = require("puppeteer");
puppeteer.launch().then(async browser=>{
const pagesCount = (await browser.pages()).length; // just to make sure we have the same stuff on both place
const browserWSEndpoint = await browser.wsEndpoint();
const customWSEndpoint = await createServer(browserWSEndpoint, host, port); // create the server here
console.log({ browserWSEndpoint, customWSEndpoint, pagesCount });
})
Run server script: node server.js. Server seems properly created. Terminal log:
browserWSEndpoint: 'ws://127.0.0.1:57640/devtools/browser/58dda865- b26e-4696-a057-25158dbc4093',
customWSEndpoint: 'ws://0.0.0.0:8080',
pagesCount: 1
npm start (from new terminal to assure the created server does not terminate)
I obtain the error in the client:
WebSocket connection to 'ws://0.0.0.0:8080/' failed:
(anonymous) # puppeteer-web:13354
I just want to use puppeteer with this front end library together in my app, fetching data with puppeteer to display it the UI and provide the user input back to puppeteer.
My ideal solution would be number 1, where I would be able to use any npm package apart from puppeteer and communicate from the backend(node server) to the client (imgui user interface) back and forth.
Thanks for any help.
EDIT:
I more less achieved it with the node server solution server which is my desired scenario, with expressjs and nodemon, running a different server in the application and communicationg with the app. Now I would find more valuable any help on:
1.- The browserifying solution and or insight about why my attempts with this approach failed.
2.- The solution that keeps everything in the one same server, that would be the server that in the repo serves the html to the browser with "start-example-html": "http-server -c-1 -o example/index.html". Dont know if that is possible. Its because I would not lose the life loading etc if I serve both things with my expressjs server added by myself.
Kind of what Create React App does with Proxying API Requests
3.- As suggested in the comments, guidance or solution to make the server code render a window through node with the imgui output (npm start-example-node) of course would be a valid answer to the question.
Seems not quite correct to change the question conditions during the bounty with a bit of a broad new scenario, but now that conditions has changed so I try to make the most of the investment and the research already done in the topic, also due to my lack of expertise in the wev-dev module bundling configuration area, so bounty may be granted for the most valuable advice in any of the two topics mentioned above. Thanks for your understanding.

How to execute terminal commands in a js file (discord.js)

My discord bot currently has a local recording feature that creates a file every time someone speaks. When the bot disconnects from the voice call (from !stoprecording), I need to manually run node merge.js in my terminal to merge all those files into 1 main PCM file. From there, I need to run another FFMPEG terminal command to convert the merged PCM file into an MP3. That's fine on it's own, but is was curious if there was any way I could automate that? Is there a way to execute terminal commands in the actual code itself. So that every time !stoprecording is ran, it would merge the file and convert to mp3 using FFMPEG?
You can use Node.JS native stuff to exec shell command when handling discord.js bot command
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function ls() {
const { stdout, stderr } = await exec('ls');
console.log('stdout:', stdout);
console.log('stderr:', stderr);
}
// ls function is called in command exec function
ls();

How do you set up Node to open n shells and execute n commands synchronously?

I'm writing a test suite that requires a proxy to be booted up, and then a curl POST request needs to be made to the proxy once it is live.
This is simple to do manually via two different tabs in the terminal eg:
In one terminal window: sh ./proxy/bin/yourProxy
In another terminal window: curl -X POST http://localhost:8080/proxy
This works, but I want to have this automated.
The issue I'm running into is that when I run the first shell command, a shell opens, but another shell never opens - and I need two different shells - one for each command.
I've tried using the concurrently npm module and using sleep to make the commands synchronous - no luck
I'm exploring using node. I've tried node's spawn, exec, and execSync. Here's an example using spawn:
const { spawn } = require("child_process");
const childOne = spawn("/bin/sh", [ "-c", "curl http://www.google.com" ])
const childTwo = spawn("/bin/sh", [ "-c", "curl http://www.yahoo.com" ])
childOne.stdout.on("data", (data) => {
console.log(`childOne stdout:\n${data}`);
});
childTwo.stdout.on("data", (data) => {
console.log(`childTwo stdout:\n${data}`);
});
This produces the result of curling childOne - but child2 shows a "redirect".
Terminal output:
child2 stdout:
redirect
child stdout:
expected output from curling google.com
How do you set up Node to open n shells and execute n commands synchronously?
First you won't want need to do things such as running other processes, making network requests etc. synchronously, since they may block your main process and get your program stuck.
Second, there are no problems with the functions you've found: spawn() and exec() can run processes asynchronously, and execSync() does the same thing synchronously. The reason why curl http://www.yahoo.com prints redirect is that it IS a redirect. Try running it in your own shell, and you'll be able to find exactly the same output:
$ curl http://www.yahoo.com
redirect

How to kill a npm child process

I've a package.json on which I define a debug script. This script launches a node app.
The whole npm script is being launched by a test, and this last one must kill the debug script once the test ends.
So when I spawn npm run debug and I kill it, the node process isn't killed.
I've tried to either kill the whole process with child_process.kill and spawning a kill bash command with no luck since the pid doesn't belong to the node launched using npm run debug.
How to kill that node process for which I don't own its pid?
You don't have to necessarily own the PID to be able to kill it (as long as the user running the scripts has permission to do it).
You could spawn commands and do it like you would in command-line (of which there are a number of ways). There are also packages like find-process which you can use to find the process that way as well.
An even easier way is to write some file that has the pid in it when debug starts up (if you can). Then you can just read that file back in to get the PID.
// in debug
import { writeFile } from 'fs';
writeFile('debug.pid', process.pid, 'utf8', err => err && console.log('Error writing pid file'));
// in app where it'll kill
import { readFile } from 'fs';
let debugPid;
readFile('debug.pid', 'utf8', (err, data) => err ? console.log('Error reading pid file') : debugPid = data);
Regardless of approach, once you have the PID, use process.kill() to kill it:
process.kill(pid);

Use Node.js to interface with bash

I have apache and Node.js running on Ubuntu
Is there a way to programatically check if the apache service is running with Node? If it's not running, allow Node.js to start/restart the service, also could the same code be used to run other processes like MySQL?
I'd also like to find a way to make Node execute "ps -u user" and capture the output in a js string or object
I've had a look at Node.js child processes but I can't figure it out
Thanks in advance
You can use the "exec" method of "child_process" module to execute a command from your node app and have its output passed as a parameter to a callback function.
var exec = require("child_process").exec;
exec("ps -u user", function (error, stdout, stderr) {
var myResult = stdout;
//doSomething
});
You could also use shelljs - https://www.npmjs.com/package/shelljs, which has many functions goes directly to shell and is cross-platform. ps command is not one of them, so use exec similar as with child_process.
require('shelljs/global');
exec('ps -aux | grep apache')
With exec you could start/restart service too, however you will need to run node process as root, what's not best option. Or create usergroup specifically for apache.
To run 'ps -u user' use the same. It will return you object with all info you need about processes.
exec('ps -u user');
And than continue with output as you need.
with spawn you can run shell scripts. So if you had a shell script written to check if a processes is running...something like this you should us spawn to run it. something like...
var child = spawn('sh', [__dirname+'/some-status-shell-script.sh'], {env: process.env});
Likewise you can use spawn to access your mysql db...similiar to this

Categories

Resources