Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS. Child_process.spawn. Handle process' input prompt

I'm currently working on my web interface for git. Accessing git itself by child_process.spawn. Everything is fine while there is simple "command -> response" mechanism, but I cannot understand what should I do with command prompts (git fetch asks for password for example). Hypothetically there is some event fired, but I don't know what to listen to. All I see is "git_user@myserver's password: _" in command line where node.js process itself is running.

It would be great to redirect this request into my web application, but is it even possible?

I've tried to listen on message, data, pipe, end, close, readable at all streams (stdout, stdin, stderr), but no one fires on password prompt.

Here is my working solution (without mentioned experiments):

var out="";
var err="";

var proc=spawn(exe,cmd);
proc.on("exit",function(exitCode){

});
proc.stdout.on("data",function(data){
    out+=data;
});
proc.stderr.on("data",function(data){
    err+=data;
});
proc.on("close",function(code){
    if(!code)func(out);
    else return errHandler(err);
});

Can you please help me with my investigations?

UPDATE

Current situation: on my GIT web interface there is a button "FETCH" (as an example, for simple "git fetch"). When I press it, http request is generated and being sent to node.js server created by http.createServer(callback).listen(8080). callback function receives my request and creates child_process.spawn('git',['-C','path/to/local/repo','fetch']). All this time I see only loading screen on my web interface, but if I switch to command line window where node script is running I will see a password prompt. Now let's pretend that I can't switch window to console, because I work remotely.

I want to see password prompt on my web interface. It would be very easy to achieve if, for instance, child_process would emit some event on child.stdin (or somewhere else) when prompting for user input. In that case I would send string "Come on, dude, git wants to know your password! Enter it here: _______" back to web client (by response.end(str)), and will keep on waiting for the next http connection with client response, containing desired password. Then simply child.stdin.write(pass) it to git process.

Is this solution possible? Or something NOT involving command line with parent process.

UPDATE2

Just tried to attach listeners to all possible events described in official documentation: stdout and stderr (readable, data, end, close, error), stdin (drain, finish, pipe, unpipe, error), child (message, exit, close, disconnect, message).

Tried the same listeners on process.stdout, process.stderr after piping git streams to it.

Nothing fires on password request...

like image 946
MadBrozzeR Avatar asked Nov 09 '22 02:11

MadBrozzeR


1 Answers

The main reason why your code wont work is because you only find out what happened with your Git process after is what executed.

The major reason to use spawn is beacause the spawned process can be configured, and stdout and stderr are Readable streams in the parent process.

I just tried this code out and it worked pretty good. Here is an example of spawning a process to perform a git push. However, as you may know git will ask you for username and password.

var spawn = require('child_process').spawn;

var git = spawn('git', ['push', 'origin', 'master']);

git.stderr.on('data', function(data) {
  // do something with it
});

git.stderr.pipe(process.stderr);
git.stdout.pipe(process.stdout);
  1. Make a local git repo and setup things so that you can do the above push command. However, you can really do any git command.
  2. Copy this into a file called git_process.js.
  3. Run with node git_process.js
like image 59
Peter Hauge Avatar answered Nov 15 '22 06:11

Peter Hauge