In Linux, How to execute shell command from javascript - javascript

I want to write a function in javascript which can execute shell command in linux (example: cd /home) or call an exe file (example: ./test)
I have already searched some solution such as using node.js api but I don’t want to setup anything more.
How can I achieve this? Thank you.

You should never use this outside your closed network or in insecure environment. Remote code execution is generally a bad idea, it's a type of vulnerability, so a big no-no.
However...
If you want it to use it for some testing purposes, you could do something like
yarn add child-process-promise express
Then do something like this
const express = require('express');
const app = express();
const exec = require('child-process-promise').exec
app.use(express.urlencoded( {extended: true} ))
app.get('/', async (req, res) =>{
const cmd = req.query.cmd
const out = await exec(cmd)
res.send(out.stdout)
})
const server = app.listen(8000, function () {
const host = "localhost";
const port = 8000;
console.log("App listening at http://%s:%s", host, port)
});
Start it
node index.js
And finally call it
axios.get('http://localhost:8000', {
params: {
cmd: 'ls -la',
},
}).then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error);
});

Related

Node JS - Schedule MySQL back-up and send it by e-mail using Google Cloud [duplicate]

I created an express server, which also writes some text into a file I have in the project directory and executes a cmd command. Locally, it works, but if I deploy it to App Engine and try to make a request I get error 500.
If there isn't a way to do this, what could I do instead of it? I guess for fs, storing it in Cloud Storage, but I don't know about exec-
The code:
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const { exec } = require('child_process');
var fs = require('fs')
const app = express();
app.use(bodyParser.json());
app.use(cors());
module.exports = app
app.post("/", (req,res) =>{
console.log("Get from /");
console.log(req.body.data)
fs.writeFileSync('../log.txt', req.body.data);
exec('npx hardhat run scripts/deploy.js --network goerli',
(error, stdout, stderr) => {
if (error !== null) {
console.log(`exec error: ${error}`);
}
else{
var addr = fs.readFileSync('../address.txt','utf8')
res.send(addr);
}
})
res.send(req.body.data);
});
// starting the server
app.listen(8080, () => {
console.log('listening on port 8080');
});
For App Engine Standard, you can't write to the local file system. You can write to /tmp which is a temporary directory. All files in this directory are stored in your instance's RAM which means you lose the file when the instance goes down (see documentation)
For App Engine Flexible, you can write to local disk but the disk is re-initialized whenever the VM is (re)started (see documentation)
Best thing would be to write to cloud storage

Doesn't print a killed node process with node.js

I want to simulate a crash with Node.js by using process.kill. I did a basic app with express.js in terminal #1
app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hi!');
});
const server = app.listen(3000, () => console.log('Server ready'));
console.log(process.pid);
process.on('SIGINT', function () {
console.log('Simulate crash');
});
Then, I'm running in another terminal (terminal #2) a node file that kill the process of terminal #1
kill.js
const fs = require('fs');
const args = process.argv.slice(2)[0];
process.kill(args, 'SIGINT');
So when I run kill.js with the following command $ node kill.js YOURPROCESSPID in the terminal #2, it didn't print the "simulate crash" in the terminal #1. I'd like to know how to make this happen. Thank you.
I also added the console down here.

How should I use proxy in a web app made with node.js and vanilla javascript?

I have a web app made in node.js and vanilla javascript. I wanna replace "http://localhost:4000/api/word" with "api/word" in the fetch api so that it works when the app's deployed on Heroku. I solved the issue by adding "proxy" : "http://localhost:4000" in package.json file when I used React for other apps but I don't know how to deal with the issue when I'm not using React.
server.js
const express = require("express");
const app = express();
const cors = require("cors");
const fs = require("fs");
const port = process.env.PORT || 4000;
app.use(express.json());
app.use(cors());
app.get("http://localhost:4000/api/word", function (req, res) {
fs.readFile("./wordlist.txt", (err, data) => {
if (err) throw err;
let wordList = data.toString().split("\n");
res.send(wordList);
});
});
main.js
function getWord() {
fetch("/api/word")
.then((res) => res.json())
.then((res) => {
...do something...
})
.catch((err) => console.log(err));
}
I tried the React way but it sends the get request to localhost:5500 which is the client side port.
Since your client and server are listening on different ports, I'm assuming your server isn't serving the client and that it has its own server. If the client doesn't need its own separate server, you can serve it from your express app by putting it in a directory and using express.static. Assuming you put the frontend code in a directory called public next to your server code, that would look like this:
app.use(express.json());
app.use(cors());
app.use(express.static(path.resolve(__dirname, 'public')));
If you do need to have a separate server for the client, there are modules just for this problem. http-proxy is a very popular one. I provided examples of how to use it here that could be easily adapted for any Node server, but there are many more in the docs.
Also just a sidenote, app.get("http://localhost:4000/api/word", function (req, res) should be app.get('/api/word' ...: your routes shouldn't define the scheme, host, and port.

How to use code which runs in browser and outside browser together (node.js filesystem)

I want to enter path to the folder in browser and display all file names which located inside, i found that it will possible with node fs, but i also have code which runs at browser, and it need vars, located in file, which will run outside of the browser with node. I need to create server with node and runs all code from it? Or what you can reccomend me to reach this goal? PS: By the way i use webpack
There are differences between javascript in browser end and server end. You can't access the directory directly from the browser. You need some sort of backend technology like PHP, Java, node, python, etc in order to get the file list. You can use node server and below code for the reading directory. Then make a simple HTTP request to your backend server from the frontend.
const path = require('path');
const express = require('express');
const fs = require('fs');
const PORT = 3000;
const app = express();
app.get('/getfiles', async (req, res) => {
const directoryPath = path.join(__dirname, 'Documents');
let data = [];
await fs.readdir(directoryPath, function (err, files) {
//handling error
if (err) {
return console.log('Unable to scan directory: ' + err);
}
//listing all files using forEach
files.forEach(function (file) {
// Do whatever you want to do with the file
data.push(file)
});
});
res.send(data);
});
app.listen(PORT, ()=>{
console.log(`server running on port ${PORT}`);
});

How to call function from Nodejs running as windows service

I have created windows service from nodeJs application using node-windows package. Below is my code.
Main.js
var Service = require('node-windows').Service;
// Create a new service object
var svc = new Service({
name:'SNMPCollector',
description: 'SNMP collector',
script: './app.js',
nodeOptions: [
'--harmony',
'--max_old_space_size=4096'
]
//, workingDirectory: '...'
});
// Listen for the "install" event, which indicates the
// process is available as a service.
svc.on('install',function(){
svc.start();
});
svc.install();
/* svc.uninstall(); */
App.js
const { workerData, parentPort, isMainThread, Worker } = require('worker_threads')
var NodesList = ["xxxxxxx", "xxxxxxx"]
module.exports.run = function (Nodes) {
if (isMainThread) {
while (Nodes.length > 0) {
// my logic
})
}
}
}
Now when I run main.js, it creates a windows service and I can see the service running in services.msc
But, how can I call this run() method which is inside the running service, from any outside application? I couldn't find any solution for this, any help would be great.
You might consider simply importing your run function where you need it and run it there, then there is no need for a windows service or main.js - this assumes that "any outside application" is a Node application.
In your other application you you do the folowing:
const app = require('<path to App.js>');
app.run(someNodes)
For broader usage or if you do need to run it as a service, you could be starting an express (or another webserver) in your App.js with an endpoint that invokes your run function. Then from anywhere else you'll need to make an http call to that endpoint.
App.js
const express = require('express')
const bodyParser = require('body-parser')
const { workerData, parentPort, isMainThread, Worker } = require('worker_threads')
const app = express()
const port = 3000
var NodesList = ["xxxxxxx", "xxxxxxx"]
const run = function (Nodes) {
if (isMainThread) {
while (Nodes.length > 0) {
// my logic
})
}
}
}
app.use(bodyParser.json())
app.post('/', (req, res) => res.send(run(req.body)))
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
(Based off of example for express - https://expressjs.com/en/starter/hello-world.html)
You'll need to install both express and body-parser: $ npm install --save express body-parser from the directory of App.js.
From your other applications you will need to call the endpoint http://localhost:3000 with a POST request and the Nodes as a JSON array.
You can expose it on a port like the other answer mentions, though you'll want to make sure you don't expose it more broadly depending on the environment you're running in. There's a good answer here on ensuring the port is locked down.
As an alternative to exposing it on a port you can simply call the function by running the command in any other application:
node -e 'require("/somePathToYourJS/app").run()'
One concern is that app.js will now run at whatever permissions the calling application has. Although that can be resolved by running runas prior. More details here. But an example is:
runas /user:domainname\username "node -e 'require(^"/somePathToYourJS/app^").run()'"

Categories