npm ssh2 library getting pid of the process - node.js

I am trying to find out the pid of the ssh2 connection and its process. I connect a remote computer and start a process. I am using npm ssh2 library.
Here is my code;
This is in an HTTP query and I need to learn pid of the process because in another HTTP query I need to shut down this process by using pid .
try {
conn.on('ready', () => {
console.log('Client :: ready');
conn.shell((error, stream ) => {
if (error) throw error;
stream.on('close', () => {
console.log('Stream :: close');
conn.end();
}).on('data', (data) => {
console.log('OUTPUT: ' + data);
res.write('OUTPUT: ' + data)
setTimeout(() => {
res.end()
}, 7000);
});
stream.write('cd .. \n');
stream.write('source /opt/ros/melodic/setup.bash \n');
stream.write('cd home/catkin_ws \n');
stream.write('source devel/setup.bash \n');
stream.end('roslaunch package sample.launch \n');
});
}).on('error', (error) => {
res.write(error.message);
res.end()
console.log(error)
}).connect({
host: ip_address,
port: 22,
username: 'root',
password: 'password',
});
} catch (error) {
console.log(error)
res.status(405).send(error)
}
I've tried so much but I couldn't find. Thank you so much for your help.

Related

Entering password programmatically in ssh2 nodejs

I'm using ssh2 nodejs client (https://github.com/mscdex/ssh2)
I'm trying to do the following:
SSH into box.
Login to docker.
It will re-prompt for password. Enter that password.
I'm failing on 3rd step.
This is my code
var Client = require('ssh2').Client;
var conn = new Client();
conn.on('ready', function() {
console.log('Client :: ready');
conn.exec('sudo docker ps', {pty: true}, function(err, stream) {
if (err) throw err;
stream.on('close', function(code, signal) {
conn.end();
// data comes here
}).on('data', function(data) {
console.log('STDOUT: ' + data);
}).stderr.on('data', function(data) {
console.log('STDERR: ' + data);
});
// stream.end(user.password+'\n');
^^ If i do this, it will work but I won't be able to do anything else afterwards
});
}).connect({
host: 'demo.landingpage.com',
username: 'demo',
password: 'testuser!'
});
How do I enter the password programmatically? (I'm already using {pty: true} while doing conn.exec
Please enlighten!
Assuming your stream is a duplex stream, you have the possibility to write into the stream without ending it by writing
.on('data', (data) => {
stream.write(user.password+'\n');
}
or you can use an cb function
function write(data, cb) {
if (!stream.write(data)) {
stream.once('drain', cb);
} else {
process.nextTick(cb);
}
}
and
.on('data', (data) => {
write(user.password+ '\n', () => {
console.log('done');
}
});

make node.js not exit after ssh2 connection error

I have the following code in my node.js app to test the SSH connection to a server using ssh2 :
var Connection = require('ssh2');
var conn = new Connection();
conn.on('ready', function() {
console.log('Connection :: ready');
conn.exec('uptime', function(err, stream) {
if (err) throw err;
stream.on('exit', function(code, signal) {
console.log('Stream :: exit :: code: ' + code + ', signal: ' + signal);
}).on('close', function() {
console.log('Stream :: close');
conn.end();
}).on('data', function(data) {
console.log('STDOUT: ' + data);
}).stderr.on('data', function(data) {
console.log('STDERR: ' + data);
});
});
}).connect({
host: serverIp,
port: serverPort,
username: serverUsername,
privateKey: require('fs').readFileSync('./id_rsa')
});
It works fine, but if it returns an error, if I get a connection timeout for example, the node.js app crashes...
I would like to do the following :
if an error is returned, simply redirect to /servers page without crashing the app.
I tried to change the "if (err) throw err;" line with "if (err) res.redirect('/servers');" but it doesn't work...
Can someone help me with this noobie question ? I'm new to node.js :)
thanks a lot.
Listen to the error event:
conn.on('error', function(e) { /* do whatever */ });
Right now, your process crashes b/c that connection error is unhandled.

Sequential execution of requests

How can I call functions one-by-one after completing? I have code like that, which must be executed continuously.
For example, I have:
var Connection = require('ssh2');
var c = new Connection();
c.on('connect', function() {
console.log('Connection :: connect');
});
c.on('ready', function() {
console.log('Connection :: ready');
c.exec('uptime', function(err, stream) {
if (err) throw err;
stream.on('data', function(data, extended) {
console.log((extended === 'stderr' ? 'STDERR: ' : 'STDOUT: ')
+ data);
});
stream.on('end', function() {
console.log('Stream :: EOF');
});
stream.on('close', function() {
console.log('Stream :: close');
});
stream.on('exit', function(code, signal) {
console.log('Stream :: exit :: code: ' + code + ', signal: ' + signal);
c.end();
});
});
});
c.on('error', function(err) {
console.log('Connection :: error :: ' + err);
});
c.on('end', function() {
console.log('Connection :: end');
});
c.on('close', function(had_error) {
console.log('Connection :: close');
});
c.connect({
host: '192.168.100.100',
port: 22,
username: 'frylock',
privateKey: require('fs').readFileSync('/here/is/my/key')
});
In what way can I call several functions one-by-one? When the connection to the ssh2 server is established, and the first request is executed, I have to parse the output of this request and send another request with data from the previous request.
I have functions which can do all this; the only problem is how to make another request after the first one is completed.
You can use nested callbacks. In the 'end' handler of each request, create a new connection and setup its end handler. Nest until needed. Similar to:
c.on('end', function() {
// after c is done, create newC
var newC = new Connection();
newC.on('end', function() {
// more if needed.
});
});
Another approach is to use some library for promises, like Q, which clears up the syntax a lot.
You can also take a look at this question: Understanding promises in node.js
From the sounds of it, you might want to look into a control flow node module such as async. Also you shouldn't need to tear down the connection just to execute another command on the same server.

How to SSH into a server from a node.js application?

var exec = require('child_process').exec;
exec('ssh my_ip',function(err,stdout,stderr){
console.log(err,stdout,stderr);
});
This just freezes - I guess, because ssh my_ip asks for password, is interactive, etc. How to do it correctly?
There's a node.js module written to perform tasks in SSH using node called ssh2 by mscdex. It can be found here. An example for what you're wanting (from the readme) would be:
var Connection = require('ssh2');
var c = new Connection();
c.on('connect', function() {
console.log('Connection :: connect');
});
c.on('ready', function() {
console.log('Connection :: ready');
c.exec('uptime', function(err, stream) {
if (err) throw err;
stream.on('data', function(data, extended) {
console.log((extended === 'stderr' ? 'STDERR: ' : 'STDOUT: ')
+ data);
});
stream.on('end', function() {
console.log('Stream :: EOF');
});
stream.on('close', function() {
console.log('Stream :: close');
});
stream.on('exit', function(code, signal) {
console.log('Stream :: exit :: code: ' + code + ', signal: ' + signal);
c.end();
});
});
});
c.on('error', function(err) {
console.log('Connection :: error :: ' + err);
});
c.on('end', function() {
console.log('Connection :: end');
});
c.on('close', function(had_error) {
console.log('Connection :: close');
});
c.connect({
host: '192.168.100.100',
port: 22,
username: 'frylock',
privateKey: require('fs').readFileSync('/here/is/my/key')
});
The other library on this page has a lower level API.
So I've wrote a lightweight wrapper for it. node-ssh which is also available on GitHub under the MIT license.
Here's an example on how to use it.
var driver, ssh;
driver = require('node-ssh');
ssh = new driver();
ssh.connect({
host: 'localhost',
username: 'steel',
privateKey: '/home/steel/.ssh/id_rsa'
})
.then(function() {
// Source, Target
ssh.putFile('/home/steel/.ssh/id_rsa', '/home/steel/.ssh/id_rsa_bkp').then(function() {
console.log("File Uploaded to the Remote Server");
}, function(error) {
console.log("Error here");
console.log(error);
});
// Command
ssh.exec('hh_client', ['--check'], { cwd: '/var/www/html' }).then(function(result) {
console.log('STDOUT: ' + result.stdout);
console.log('STDERR: ' + result.stderr);
});
});
The best way is to use promisify and async/await. Example:
const { promisify } = require('util');
const exec = promisify(require('child_process').exec);
export default async function (req, res) {
const { username, host, password } = req.query;
const { command } = req.body;
let output = {
stdout: '',
stderr: '',
};
try {
output = await exec(`sshpass -p ${password} ssh -o StrictHostKeyChecking=no ${username}#${host} ${command}`);
} catch (error) {
output.stderr = error.stderr;
}
return res.status(200).send({ data: output, message: 'Output from the command' });
}
Check my code:
// redirect to https:
app.use((req, res, next) => {
if(req.connection.encrypted === true) // or (req.protocol === 'https') for express
return next();
console.log('redirect to https => ' + req.url);
res.redirect("https://" + req.headers.host + req.url);
});
pure js/node way to ssh into hosts. Special thanks to
ttfreeman. assumes ssh keys are on host. No need for request object.
const { promisify } = require('util');
const exec = promisify(require('child_process').exec);
require('dotenv').config()
//SSH into host and run CMD
const ssh = async (command, host) => {
let output ={};
try {
output['stdin'] = await exec(`ssh -o -v ${host} ${command}`)
} catch (error) {
output['stderr'] = error.stderr
}
return output
}
exports.ssh = ssh

How to kill a tail process that's execute using nodejs ssh2?

How to kill tail process that i execute in this query ?
var c = new Ssh2();
c.on('connect', function() {
console.log('Connection :: connect');
});
c.on('ready', function() {
console.log('Connection :: ready');
c.exec('tail -f test.txt', function(err, stream) {
if (err) throw err;
stream.on('data', function(data, extended) {
console.log((extended === 'stderr' ? 'STDERR: ' : '')
+ data);
});
stream.on('exit', function(code, signal) {
c.end();
});
});
});
c.on('error', function(err) {
console.log('Connection :: error :: ' + err);
});
c.on('end', function() {
console.log('Connection :: end');
});
c.on('close', function(had_error) {
console.log('Connection :: close');
});
c.connect({
host: '127.0.0.1',
port: 22,
username: 'test',
password: 'test'
});
Or is there any suggestion to execute tail -f using nodejs?
The easiest way to do this is to use a form like this for your command line: 'tail -f test.txt & read; kill $!'.
Then when you want to kill the process, simply stream.write('\n');

Resources