SSH2 library, how to execute unix commands from NODE - javascript

I am trying to understand about the SSH2 for nodeJS https://github.com/mscdex/ssh2, but I can't find more documentation, does anybody has more related to the client events?
I am trying to connect from my Node project to a Unix server and execute commands from node using this library SSH2 such as mkdir, ls or some other unix commands but I can't find any documentation of how to do it.
I am able to establish connection, but now I need to execute unix commands
var Client = require('ssh2').Client;
//
var conn = new Client();
conn.on('ready', function() {
console.log('Client :: ready');
conn.sftp(function(err, sftp) {
if (err) throw err;
console.log('Client :: SSH open');
output.add("ls");
conn.end();
});
}).connect({
host: 'hostname',
port: 22,
username: 'user',
password: 'password'
});
Or if this is not achievable with SSH2 can somebody recommend another Node Library were I can connect to an unix server? I have a Node application that creates a HTML file but after the creation I need to name it in base of the last file name that I have in a unix server, create the directory in unix and the upload it using sftp-upload plugin. Trying to achieve this with node instead of doing manually.

You can do this with node-exec or ssh2-exec which uses ssh2. ssh2 is low level so for exec you can use other libs like ssh2-exec and ssh2-connect.
There are plenty of examples in README.md.
Example (from ssh2-exec README):
connect = require('ssh2-connect');
exec = require('ssh2-exec');
connect({host: localhost}, function(err, ssh){
child = exec({cmd: 'ls -la', ssh: ssh}, function(err, stdout, stderr){
console.log(stdout);
});
child.stdout.on('data', function(data){
console.log(stdout);
});
child.on('exit', function(code){
console.log('Exit', code);
});
})

Related

Unable to make request to my mariadb database using node server

I'm currently learning how to setup a node server and I'm making an API that performs some requests on my MariaDB database hosted on my VPS.
The problem is that when I make a POST request which makes a SQL request to the database, the connection times out and the server shuts down.
I have tried to add new users to MariaDB with all privileges, I tried use sequelize too.
But none of those solutions work, it still times out every time I make a query to my database.
I can connect to phpmyadmin and make some request on it, so I think that my database is running fine.
Here is my code:
router.post('/login', async function(req,res) {
let conn;
try {
// establish a connection to MariaDB
conn = await pool.getConnection();
// create a new query
var query = "select * from people";
// execute the query and set the result to a new variable
var rows = await conn.query(query);
// return the results
res.send(rows);
} catch (err) {
throw err;
} finally {
if (conn) return conn.release();
}
})
The way I connect to my database in my database.js file
const pool = mariadb.createPool({
host: process.env.DATABASE_HOST,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABSE_NAME,
});
// Connect and check for errors
module.exports={
getConnection: function(){
return new Promise(function(resolve,reject){
pool.getConnection().then(function(connection){
resolve(connection);
}).catch(function(error){
reject(error);
});
});
}
}
module.exports = pool;
And my error:
Node.js v17.0.1
[nodemon] app crashed - waiting for file changes before starting...
[nodemon] restarting due to changes...
[nodemon] starting `node server.js`
Server started
/Users/alexlbr/WebstormProjects/AlloEirb/server/node_modules/mariadb/lib/misc/errors.js:61
return new SqlError(msg, sql, fatal, info, sqlState, errno, additionalStack, addHeader);
^
SqlError: retrieve connection from pool timeout after 10001ms
at Object.module.exports.createError (/Users/alexlbr/WebstormProjects/AlloEirb/server/node_modules/mariadb/lib/misc/errors.js:61:10)
at timeoutTask (/Users/alexlbr/WebstormProjects/AlloEirb/server/node_modules/mariadb/lib/pool-base.js:319:16)
at Timeout.rejectAndResetTimeout [as _onTimeout] (/Users/alexlbr/WebstormProjects/AlloEirb/server/node_modules/mariadb/lib/pool-base.js:342:5)
at listOnTimeout (node:internal/timers:559:11)
at processTimers (node:internal/timers:500:7) {
text: 'retrieve connection from pool timeout after 10001ms',```
Three possibilities come to mind:
There is a typo in database name:
database: process.env.DATABSE_NAME
database: process.env.DATABASE_NAME
Your environment variables are not being properly set. Are you using dotenv to load these from an .env file?
https://www.npmjs.com/package/dotenv
If not, how are you setting the process.env values at runtime?
If the environment values are indeed set:
verify that these environment values are correct
verify which interface your MariaDB server is listening on:
It's possible the server is using a bind-address configuration and only listening on 127.0.0.1 (which is the default on Debian/Ubuntu)
You want to make sure the server is listening on: 0.0.0.0 (all interfaces, not only localhost)

Trying to SSH using protractor

I'm running protractor on my windows VM and need to execute some commands on a linux VM. I'm trying to use SSH to do the same. I've tried using 'simple-ssh', 'remote-exec' and 'ssh-exec. The problem with all of them is the same, the protractor test completes without any error but the SSH connection is not established. Strangely it doesn't throw any error as well, I've tried giving wrong IP, but still, no error is thrown. I've tried SSH over python with same machine, it works flawlessly.
here is a piece of code from documentation that I directly tried to use.
var ssh = new SSH({
host: 'xx.xx.xxx.xx',
user: 'xxxxx',
pass: 'xxxxx'
});
ssh.exec('ls -lh', {
out: function(stdout) {
console.log(stdout);
}
}).start();
Figured it out.
I used ssh2 package to establish an interactive SSH session. Then I synchronized it with jasmine using done() in jasmine 2.
Used Maciej Ciach's solution for solving sync problem.
Here's an 'It' block that runs flawlessly
it("trying ssh connection", function (done) {
var conn = new Client();
conn.on('ready', function () {
console.log('Client :: ready');
conn.shell(function (err, stream) {
if (err) throw err;
stream.on('close', function () {
console.log('Stream :: close');
conn.end();
}).on('data', function (data) {
console.log('OUTPUT: ' + data);
});
stream.end('ls \nexit\n');
done();
});
}).connect({
host: 'xx.xx.xxx.xx',
port: 22,
username: 'x',
privateKey: require('fs').readFileSync('file_path')
});
})
Obviously, you need to add your public ssh key to the list of trusted keys on your server first.
You can read about it here.
If you are on windows then execute those commands in Powershell.

Node.js child_process exec, stdin not being passed through to ssh

I have the following Node.js code to ssh into a server and it works great forwarding stdout, but whenever I type anything it is not forwarding to the server. How do I forward my local stdin to the ssh connections stdin?
var command = 'ssh -tt -i ' + keyPath + ' -o StrictHostKeyChecking=no ubuntu#' + hostIp;
var ssh = child_proc.exec(command, {
env: process.env
});
ssh.stdout.on('data', function (data) {
console.log(data.toString());
});
ssh.stderr.on('data', function (data) {
console.error(data.toString());
});
ssh.on('exit', function (code) {
process.exit(code);
});
There's two ways to go about this if you want to pipe the process.stdin to the child process:
Child processes have a stdin property that represents the stdin of the child process. So all you should need to do is add process.stdin.pipe(ssh.stdin)
You can specify a custom stdio when spawning the process to tell it what to use for the child process's stdin:
child_proc.exec(command, { env: process.env, stdio: [process.stdin, 'pipe', 'pipe'] })
Also, on a semi-related note, if you want to avoid spawning child processes and have more programmatic control over and/or have more lightweight ssh/sftp connections, there is the ssh2 module.

Helenus isn't able to connect

I am developing an application in nodejs with cassandra driver using helenus. the version of helenus is 0.6.10.
This is app.js.
var helenus = require('helenus');
var pool = new helenus.ConnectionPool({
hosts: ['localhost:9160'],
keyspace: 'test_dev',
user: '',
password: ''
});
pool.connect(function(err, keyspace) {
if (err) throw err;
console.log('Listening on port 3000....');
});
pool.on('error', function(err) {
if (err) throw err;
});
When we call pool.connect then it is throwing following error in the callback.
error name : "HelenusNoAvailableNodesException"
error message: "Could Not Connect To Any Nodes"
When i have gone through the troubleshooting the problem. I have found that onDescribe method in Connection.prototype.use method is being throwing an error which is "NotFoundException".
What i am doing wrong? Any help.
First check your Cassandra version. If you are running Cassandra 1.2 or greater, you should really be using the Datastax NodeJS Driver. There really isn't any reason to be using Thrift in 1.2 or greater as the performance and features of CQL greatly outweigh Thrift. Also, while the Thrift server is still available for use, no development effort is given to it.
If you are absolutely sure you need to be using Thrift then first ensure the keyspace exists. Helenus requires a keyspace to connect to, so if the keyspace is not present it will not be able to connect to any nodes. If the keyspace exists then run:
nodetool statusthrift
if it says anything other than running then run nodetool enablethrift and try again.
If thrift is running then I would check the interface configured in your cassandra.yaml. The rpc_address should match the interface you are connecting to from the client. If you unsure of the interface then just set it to 0.0.0.0. The rpc_port should be 9160. After changing any settings in the cassandra.yaml you will need to restart the cassandra service on each of the nodes in the cluster.

ssh persistent sessions with node.js

I am working with node.js, and I am trying to embed a console in the web browser to work in a remote server. The web application do the connection so the user does not need to do the ssh username#host but only type commands.
I have tried the node.js' ssh2 module and other modules which use ssh2. But I'm experiencing always the same problem. Every time I execute a command programmatically using exec(), the ssh session is restarted. I'll explain it better with an example.
> ls
returns the content of home directory, one of the directories in the home directory is mydir
> cd mydir
> ls
returns the content of my home directory again, because after a command is executed the ssh session is closed/restarted.
Any node.js library which can do the job? or even a library of other technology different to javascript?
Edit: Other example for clarifying, using the node.js' module ssh-exec
The server has to execute some commands in other machine using ssh. A function in the server contains the following code
var c = exec.connection('username#host.com'); // It takes the ssh key from the default location
exec('cd mydir', c).pipe(process.stdout);
exec('ls -lh', c).pipe(process.stdout);
As you can see I am not ending the connection after the first exec but the output I obtain is the content of the home directory not the content of mydir directory, because the ssh session is reset after each exec.
The maintainer of node.js' ssh2 module provided the solution.
To use the method shell() instead of the method exec().
The method shell() creates an interactive session with the server we are connecting.
The method shell() provides a stream as a parameter of its callback (like the method exec()).
Like when using exec(), stream.on('data', function(data, extended) {...}); can be used to get the output of the commands. However, in this case, to provide commands (input) to the machine you connected with, you need to use stream.write(yourcommand+'\n');
PS. Feel free to edit to improve the accuracy of the answer.
I have to guess a bit, but you do something like child = exec('ssh username#host ls')?
You can do something like
child = exec('ssh username#host');
upfront and in the "loop" of your browser
child.stdin.write('ls\n');
When finished, just close stdin:
child.stdin.end()
which also finishes the child process.
I know this link is old but I figured this may help someone if they're looking for a solution. The
To use the method shell() instead of the method exec().
Works. Here's another solution. Use absolute file paths i.e.
conn.exec("mkdir -p /home/user/Direc/{one,two,three}/", function(err, stream) {
if (err) throw err;
stream.on('data', function(data) {
console.log('STDOUT: ' + data);
}).stderr.on('data', function(data) {
console.log('STDERR: ' + data);
});
});
conn.exec("ls -la /home/user/", function(err, stream) {
if (err) throw err;
stream.on('close', function(code, signal) {
console.log('Stream :: close :: code: ' + code + ', signal: ' + signal);
conn.end();
}).on('data', function(data) {
console.log('STDOUT: ' + data);
}).stderr.on('data', function(data) {
console.log('STDERR: ' + data);
});
});

Categories

Resources