Looking to run a shell command from nodejs ui webpage form. Form has one entry field for a "ssh {machinename} /path/to/script.sh" command. The page will be nodejs single page application. New to nodejs.
Can this be done? I have searched but just found pages with php or python examples. Also looked at argv and shelljs but no one mentions what I am trying to do. Machine-A has single-page-application and its public key already inserted into Machine-B where the executed shell script resides. Running the command on cli works. I want users to run their own commands on the spa page. *Nix environment only.
So far I have the following...
package.json:
{
"name": "TP",
"version": "0.0.1",
"description": "Testing Project",
"private": true,
"dependencies": {
"express": "3.x",
"hbs": "*"
}
}
form:
<form action="" method="post" enctype="multipart/form-data" style="margin:0; width:720px;">
<fieldset>
<!-- ENTER COMMAND -->
<label for="test">Enter Test:</label>
<input style="display: inline; width: 500px;" type="text" id="test_input" name="value" placeholder="Enter test command with correct params" />
<!-- RUN COMMAND -->
<input type="button" onclick="runTest()" value="Run Test!" style="float: right;" />
<!-- CLEAR COMMAND -->
<input type="button" name="testform" value="Clear Test" onclick="this.form.reset();" style="float: right;" />
<br />
</fieldset>
</form>
Have you looked at the ssh2shell package?
I found the ssh2 npm to be more along the lines of what I need and have available to me to complete the task. And you'll see the simplicity also which I like. Now to have the entire process to be handled by a front end button and pipe the stdout to mongodb.
npm install ssh2
Background:
Had to use escape characters for bash command
Users private key path, host and username
User with sudo rights
Users public key in destination vm
Code:
var Client = require('ssh2').Client;
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('STDOUT: ' + data);
}).stderr.on('data', function(data) {
console.log('STDERR: ' + data);
});
stream.end('cd /home/cruzcontrol/bin/ \n sh flash_demo_test.sh \n exit \n');
});
}).connect({
host: '10.5.74.123',
username: 'cruzcontrol',
privateKey: require('fs').readFileSync('/home/cruzcontrol/.ssh/id_rsa')
});
This is probably redundent now but I thought I would add it in case someone else found it helpful.
Serving the page and receiving the form post data can be done using nodejs express. There are lots of basic site examples like simple-website-in-node that you can use to get up and going.
Example:
Server code example provided by the link above. SSH2shell example given in the app.post function.
This example is not tested.
Following the tutorial above would be recommended for setup.
.
var express = require('express')
, logger = require('morgan')
, app = express()
, bodyParser = require('body-parser')
, fs = require('fs')
, Mustache = requires('mustache')
, formPage = fs.readFileSync('./templates/myForm.xhtml');
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use( bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.use(logger('dev'))
app.use(express.static(__dirname + '/static'))
//main page route
app.get('/', function (req, res, next) {
try {
var html = Mustache.parse(formPage, { title: 'My Form' })
res.send(html)
} catch (e) {
next(e)
}
})
//POST route
app.post('/', function (req, res) {
//SSH2shell implementation
var host = {
server: {
host: '10.5.74.123',
port: 22,
userName: 'cruzcontrol',
privateKey: fs.readFileSync('/home/cruzcontrol/.ssh/id_rsa') },
//Here you form command is set as the only command
commands: [ req.body.value ]
};
var SSH2Shell = require ('ssh2shell')
, SSH = new SSH2Shell(host)
, callback = function( sessionText ){
//code here to return the sessionText and command in the form page.
var html = Mustache.parse(formPage, { title: 'My Form',
value: req.body.value,
result: sessionText});
res.send(html);
}
SSH.connect(callback);
})
app.listen(process.env.PORT || 3000, function () {
console.log('Listening on http://localhost:' + (process.env.PORT || 3000))
})
As long as node express was serving your page SSH2shell could receive your command (value) from the form submission, run it and display the result and the command in a returned form page. The example uses the templating engine Mustache so the myForm.xhtml would need the page form html and a couple of tags to output the command and response.
SSH2shell has no code that checks that a password is set or any of the other connection parameters so if you don't need it to authenticate then you don't have to use it.
SSh2shell wraps SSH2.shell.
The minimum required to get SSH2shell working is:
- The host.server options.
- The host.commands array of commands to run.
- Either use the
host.onEnd
orSSH2shell.on('end')
event handler or a callback function to process the full session text closing the connection.
That's it.
Multiple commands could be handled by using a text box and either use a delimiter to split the commands or treating each line as a command then pushing them onto a command array. host.commands
property can be set with the commands array variable. Response (sessionText) handling would be basically the same except where req.body.value
would be the text box content.
For more details about SSH2shell for SSH shell command processing see the SSH2shell readme