Launch interactive ssh from nodejs - node.js

I have a text blob that contains ip, port, user and passord and would like to write a small utility script where I can:
paste the text in stdin
extract the connection details using regex or any other means
use node to launch ssh interactively using my parsed values
How would I launch the ssh command from node with the arguments, exit node and continue on ssh'ing? The documentation I've found regarding i.e. child_process concerns launching and controlling the process within node, but I simply want to exit back and take over once ssh is started.

The following code will fit your requirements, adjust it to your needs. The program does the following:
reads the port from a file
prompts you for the hostname, reading data from stdin
launches ssh using child_process.fork
Code:
var port = require('fs').readFileSync('port.txt');
const rl = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Enter hostname: ', (answer) => {
require('child_process').spawn('ssh', [answer, port],
{stdio: [process.stdin, process.stdout, process.stderr]});
});
The question is answered except for the following point:
exit node and continue on ssh'ing
I am not aware of this being possible in any programming language, but a better answer can correct me. Instead, you launch a child process and redirect all input/output to it. From your perspective, you only interact with ssh, so the fact that the node process still exists as a parent to ssh is transparent to you.
An equivalent command in perl for example would be system("ssh");

Related

Process Object Stdout and StdIn do not work as expected

I am using vsCode for NodeJS.
My code was simple. So I was expecting stdout should wait for input from console. Once input is given, then it should go to exit.
But once i do > node process
the program goes to exit directly.
file - process.js ->
process.stdout.write('Ask me something : ');
process.stdin.on('data', function(answer){
console.log(answer.toString());
});
console.log('exit')
process.exit();
Output:
c:\node-projects\demo-nodejs>node process
Ask me something : exit
c:\node-projects\demo-nodejs>
How can I use process object to get standard input/output/print/exit the code instead of using other readline object?
There are a few question/answers such as this one already on this site that probably answer what you are asking. Your code is not working because the line with process.stdin.on is not a synchronous callback method call, it is an event handler that waits for the 'data' event.
If I understand what you are trying to do, I think it is easiest to import the 'readline' module. It is built-in to the nodejs executable, but not loaded to your code execution environment unless you require it.
That would make your code look like this:
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Ask me something : ', function(answer){
console.log(answer.toString());
console.log('exit')
process.exit();
});
Note that the rl.question method call executes right away and calls the function(answer) function when the user is done with text input. It can take some understanding and getting used to the asynchronous program control flow in NodeJS, you might have to rethink some of the rest of your program structure.
The offical documentation for the readline NodeJS module and function is here.

node.js - How to spawn a child process without blocking stdin of parent process?

I'm making an interactive CLI in node (and blessed.js) that spawns child processes every couple of seconds to run some Python scripts. These scripts modify a set of JSON files that the CLI pulls from.
The problem is that the CLI must be able to accept input from the user at all times, and when these child processes are spawned, the stdin of the CLI/parent process appears to be blocked and it looks like the Python scripts are executing in the foreground. Here's the code I'm using to run the Python scripts:
const { spawn } = require("child_process");
function execPythonScript(args) {
return spawn("python3", args, { stdio: "ignore" });
}
execPythonScript(["path_to_script.py"]);
I've also tried running the script as a background process, i.e. execPythonScript(["path_to_script.py", "&"]), but to no avail. Any ideas?
Thanks in advance!
UPDATE:
I'm starting to suspect this is an issue with blessed and not child-process, since I've exhausted all relevant methods (and their arguments) for spawning non-blocking background processes, and the problem still persists.
Each blessed instance uses process.stdin for input by default, but I figured it's possible that the stdin stream gets used up by the child processes, even though I'm spawning them with stdio set to "ignore". So I tried using ttys and instantiating blessed.screen to read from the active terminal (/dev/tty) instead of /dev/stdin:
const ttys = require("ttys");
screen = blessed.screen({
input: ttys.stdin, // Instead of process.stdin
smartCSR: true
});
But it's still blocking...
You also need to detach the process:
spawn("python3", args, { stdio: "ignore", detached: true })
This is a useful primer.

Electron Readline

I'm trying to build an app using electron, it's designed to get a GUI later but for now i'm just trying to do this:
function test(){
console.log("In Test")
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', function(line){
console.log(line);
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', test);
On launching npm start, I see the "In Test" log, but when I type something in my shell, it's not returned to me as I need it to be by the Readline module.
Am I missing something ?
In Electron the console becomes the Chromium console which is not like the terminal you're used to. Readline is not going to work as far as I know. The blink console in Chromium does not support reading input this way. It operates more like a debug REPL where you can type JS code, inspect variables, etc. It's not for user input. I don't think you're going to be able to get input supplied from that console into stdin, which is where the readline module is waiting to see data.
Update
I assumed OP was using the dev tools console expecting it to work like a shell. He was using it properly. The actual issue is a bug with node's readline module on Windows. Node devs are actively working to fix it. It's a regression bug that was fixed once before but appeared again in recent versions of node.

Close another process from node on Windows

How can I kill a process from node on Windows?
I'm making a updater. It needs close a windows executable (.exe) to download the updates. (The update process is download and overwrite). I read that this is possible with process.kill(pid[, signal])
But, How can I get the PID of the process if I know the name of the process?
According to the documentation, you simply access the property.
process.kill(process.pid, 'SIGKILL');
This is a theoretical, untested, psuedo function that may help explain what I have in mind
exec('tasklist', (err, out, code) => { //tasklist is windows, but run command to get proccesses
const id = processIdFromTaskList(processName, out); //get process id from name and parse from output of executed command
process.kill(id, "SIGKILL"); //rekt
});
Use node-windows to get pid of process you want to kill so that you can call process.kill. The library also provides an api to kill task.

node.js STDIN works with process.stdin, not when piped

I'm using require("child_process").spawn and calling an executable, which at the beginning is pausing for a password to be input; if I use it like below:
var spawn = require("child_process").spawn;
var exe = spawn("NameOfExe.exe", [/*arguments*/], {stdio: [process.stdin, process.stdout, process.stderr]});
It works perfectly (Yes, I know I can do inherit, shush :p ). I can type inside my console and it'll accept it with no issues.
However, if I do it like this:
var spawn = require("child_process").spawn;
var exe = spawn("NameOfExe.exe", [/*arguments*/], {stdio: ["pipe", process.stdout, process.stderr]});
exe.stdin.write("Password\n");
then the executable doesn't even receive the stdin; it immediately goes to Execution Failed.
I'm completely at a loss for this. Any suggestions?
EDIT:
I think I may be onto something!
So I'm 99.99% certain that the executable is using C# and Console.ReadKey to get the password. However, according to Microsoft, an exception gets thrown whenever the In property is redirected somewhere else.
So this explains it, but is there a way around this using Node, or am I at the mercy of the people who made this executable?
The ReadKey method reads from the keyboard even if the standard input is redirected to a file with the SetIn method.
You figured it out. It uses native bindings to the hardware controller/HAL, and not the shell, to handle stdio.

Resources