Get password for node-cli and pass it on to next command in nodejs - node.js

Im trying to build a command line interface using nodejs. I have used enquirer package to prompt users for questions. I have a scenario where i need to write to /etc/hosts file. I tried running the following command using execa package
const {stdout} = await execa.command('echo "192.241.xx.xx venus.example.com venus" >> /etc/hosts', { cwd: '/etc/'})
But it does not seems to work and tried with sudo command as well
const {stdout} = await execa.command("sudo vim hosts", { cwd: '/etc/'});
How to execute it in nodejs. Basically i wanted to prompt the user for password and then need to write it to /etc/hosts file.
FYKI: im using execa for executing shell commands.
Tried the hostile.js and it didn't work either.
Here is the full code
async function executeCommand() {
try {
const {stdout} = await execa.command("echo '192.34.0.03 subdomain.domain.com' | sudo tee -a /etc/hosts", { cwd: '/etc/'});
console.log(stdout);
} catch (error) {
console.log(error);
process.exit(1);
}
}

There is a Node package for this purpose, called password-prompt:
let prompt = require('password-prompt');
let password = prompt('password: ');
And now that you have the password, you can run something like this:
let command = `echo "${password}" | sudo -S -k vim /etc/hosts`;

This solution worked for me
const { promisify } = require('util');
const exec = promisify(require('child_process').exec)
const nameOutput = await exec("echo '127.0.0.1 test.com' | sudo tee -a /etc/hosts")
This would prompt password to enter.

Related

How to allow Node.js child_process.execSync to run `scp -P 4422 root#myserver.com:/data/backups/...` without getting Permission Denied

I am running a simply Node.js process to backup my data everyday by using child_process.execSync to run:
scp -P 4422 root#myserver.com:/data/backups/dbs.zip /data/backups/dbs.zip
Notice if I run the above command directly, it will work. But when I do it in Node, the log I got is:
[2020-03-04 05:00:00] error downloading backup...Command failed:
Permission denied, please try again.
root#myserver.com: Permission denied (publickey,password).
Do I have to create a key file for Node.js' child_process to use when it fires scp? If so, how come if I run scp -i id_rsa.pem -P 4422 root#myserver.com:/data/backups/dbs.zip /data/backups/dbs.zip in Node.js it just stuck (like it even stops running any async actions such as appendFile. It also created a lot of processes called (node) and these processes cannot be killed.
const path = require('path');
const {
backupPath,
downloadPath
} = require('../../conf');
const keyPath = path.join(
__dirname,
'../../key/id_rsa.pem'
);
const downloadProcess = log => {
const { execSync } = require('child_process');
log('downloading backup...');
try {
const date = new Date();
const backupName = `db_${date.format('yyyy-MM-dd')}.tar.gz`;
const command = `scp -i ${keyPath} -P 4422 root#myserver.com:${backupPath}/${backupName} ${downloadPath}/${backupName}`;
log(`running command: ${command}`);
const stdout = execSync(command);
log(`downloaded backup ${backupName} at ${downloadPath}${'\n'}stdout:${'\n'}${stdout}`);
} catch (e) {
log(`error downloading backup...${e.message}`);
}
}
module.exports = downloadProcess;

Open terminal and launch commands

In my electron/reactjs app, i'm trying to open a terminal and launch somes commands.
My code looks like this :
const terminal = 'x-terminal-emulator';
const { spawn } = require('child_process');
spawn(terminal);
My terminal opens but i don't know how to launch commands in this terminal like 'cd /my/custom/path && ls'
Can someone help me please ? :)
Node.js child_process.spawn command have an option to specify the shell you want to use.
So I would use the opposite logic and launch directly the command within a particular shell (for exemple bash):
const { spawn } = require('child_process');
const terminal = '/bin/bash';
let cmd = 'echo $SHELL';
spawn(cmd, { shell: terminal })
.stdout.on('data', (data) => {
console.log(`stdout: ${data}`); //-> stdout: /bin/bash
});

Adding samba user programically with node.js

I've wrote function in node,js as follows:
const addUserToSamba = (userLogin, password) => {
const echoPassword = spawnSync('echo', ['ne',`${password}\n${password}\n`]);
const addUserCredentialsToSamba = spawnSync('smbpasswd', ['-a', '-s', userLogin], {
input: echoPassword.stdout,
});
console.log('Added user credentials to Samba configuration');
console.log(addUserCredentialsToSamba.stderr.toString());
console.log(addUserCredentialsToSamba.stdout.toString());
}
I want to achieve something like this in bash:
echo -ne "$PASS\n$PASS\n" | smbpasswd -a -s $LOGIN
When I'm running addUserToSamba(userLogin, password); function with given userlLogin and user password then I even get message Added user ${userLogin} as a stdout of the addUserCredentialsToSamba outcome.
But the credentials don't work.
Have I correctly rewritten this bash function to the node.js one?
If no, how can I fix it?
You can simply skip the echo part and output the credentials directly to the smbpasswd process:
const addUserCredentialsToSamba = spawnSync('smbpasswd', ['-a', '-s', userLogin], {
input: `${password}\n${password}\n`,
});

Is it possible to check if a system is on LAN vs WiFi via nodejs?

Are there any packages for node that can determine if a PC is on a LAN vs Wifi connection?
I have gone through the node docs and it doesn't appear there is a native node module. (https://nodejs.org/api/os.html)
Could not find anything in NPM that could determine this either.
Remember you can run any bash command you want using exec.
So you can do something along the lines of
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function main() {
const { stdout, stderr } = await exec('tail -n+3 /proc/net/wireless | grep -q .');
if (stdout) { // wirelesss }
}
main()
Adapted: determine if connection is wired or wireless?

how do I make node child_process exec continuously

How to exec continuously? e.g. ls after cd?
I tried
exec = require('child_process').exec;
exec('cd ~/',
function(){
exec('ls'),
function(err, stdout, stderr){
console.log(stdout); // this logs current dir but not ~/'s
}
}
)
exec('cd ~/').exec('ls', function(err, stdout, stderr){
console.log(stdout);
})//this also fails because first exec returns a ChildProcess Object but not itself.
It is not possible to do this because exec and spawn creates a new process. But there is a way to simulate this. You can start a process with exec and execute multiple commands in the same time:
In the command line if you want to execute 3 commands on the same line you would write:
cmd1 & cmd2 & cmd3
So, all 3 commands run in the same process and have access to the context modified by the previous executed commands.
Let's take your example, you want to execute cd ../ and after that to execute dir and to view the previous directory list.
In cmd you shoud write:
cd../ & dir
From node js you can start a process with exec and to tell it to start another node instance that will evaluate an inline script:
var exec = require('child_process').exec;
var script = "var exec = require('child_process').exec;exec('dir',function(e,d,er){console.log(d);});";
script = '"'+script+'"';//enclose the inline script with "" because it contains spaces
var cmd2 = 'node -e '+script;
var cd = exec('cd ../ &'+cmd2,function(err,stdout,strerr)
{
console.log(stdout);//this would work
})
If you just want to change the current directory you should check the documentation about it http://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
You can use nodejs promisify and async/await:
const { promisify } = require('util');
const exec = promisify(require('child_process').exec);
export default async function () {
const cpu = await exec('top -bn1');
const disk = await exec('df -h');
const memory = await exec('free -m');
const payload = {
cpu,
disk,
memory,
};
return payload
}
If you want to use cd first, better use process.chdir('~/'). Then single exec() will do the job.
You can call exec with cwd param like so:
exec('ls -a', {
cwd: '/Users/user'
}, (err, stdout) => {
if (err) {
console.log(err);
} else {
console.log(stdout);
}
})
But beware, cwd doesn't understand '~'. You can use process.env.HOME instead.

Resources