Can Nodejs ui page run shell cmd to remote machine

2019-09-04 22:39发布

问题:

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>

回答1:

Have you looked at the ssh2shell package?



回答2:

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')
});


回答3:

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