user2939415
user2939415

Reputation: 894

Sending a Terminate (Ctrl+C) Command in Node.js SSH2

I am using Node.js SSH2 module(https://github.com/mscdex/ssh2). myScript.py executes continuously. How can I stop it while keeping the SSH connection alive?

var Connection = require('ssh2');
var c = new Connection();
c.on('ready', function() {
  c.exec('python myScript.py', function(err, stream) {
    if (err) throw err;
    stream.on('data', function(data, extended) {
      //this callback gets called multiple times as the script writes to stdout
      console.log((extended === 'stderr' ? 'STDERR: ' : 'STDOUT: ') + data);
      allData+=data;
    });
  });
});
c.connect({
  host: xxx.xxx.x.xx,
  port: 22,
  username: 'user',
  password: 'pass'
});

Upvotes: 2

Views: 2840

Answers (2)

Dominic
Dominic

Reputation: 905

We got the same problem in our research group and our solution is to fetch the process ID of the remote process when first executing the command and then kill it when needed.

It seems python processes are continuing to live detached in the background if you only use the kill [pid] command, therefore we used the pkill -g [pid] command in our solution below. This might be different or the same in other cases. But I guess it's good to know that you shoud try both cases if one doesn't work for you.

This is our (simplified) solution. Of course it does not make sense to kill every exec command after 5 seconds... but you will get the idea (and a safe pid/conn scope for reuse):

var Connection = require('ssh2');
var c = new Connection();

function killProcess(conn, pid) {
    setTimeout(function() {
        console.log('Killing PID ' + pid);
        conn.exec('pkill -g ' + pid, function(){});
    }, 5000);
}

c.on('ready', function() {
    // echo $$; gives you the PID, we prepend it with the string
    // "EXEC PID: " to later on know for sure which line we grab as PID
    c.exec('echo "EXEC PID: $$";python myScript.py', function(err, stream) {
        if(err) throw err;
        stream.on('data', function(buffer) {
            var line = '' + buffer; // unbeautiful ;)
            console.log(line);
            if(line.substr(0, 10) === 'EXEC PID: ') {
                killProcess(c, line.substr(10));
            }
        }).on('end', function() {
            console.log('exec killed');
        });
    });
});
c.connect({
  host: xxx.xxx.x.xx,
  port: 22,
  username: 'user',
  password: 'pass'
});

Upvotes: 4

mscdex
mscdex

Reputation: 106746

The problem is that not all SSH servers support the packet sent by signal(), this includes OpenSSH as of this writing.

Fortunately for SIGINT, you can usually get the expected behavior by instead writing '\x03' to the stream.

Upvotes: 2

Related Questions