NodeJS. Child_process.spawn. Handle process' input prompt
Asked Answered
V

2

6

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...

Vanburen answered 2/11, 2015 at 21:49 Comment(2)
Stuck at the very same place. Did you find any solution ? xkcd.com/979Pilcher
@ShashankGoyal No, unfortunately. Still switching to my terminal for prompts...Vanburen
P
1

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
Pollywog answered 2/11, 2015 at 22:54 Comment(4)
Well, maybe I am a little more "newbie" then I thought, but I don't really see what do I need to apply to my code. Direct copy-paste (with my variable names) leads to exceptions in external modules. Pass passwords to git as attributes (if I've got it correctly) is not an option, because not all repositories demands it. External modules is also not my choice, because of I want to make "inner processes" more clear to me, and not to think about it like some kind of magic.Vanburen
And I'm not sure if I want to pipe one stream into another directly. In my case I have two objects: http.Server and ChildProccess. First one has streams http.IncomingMessage (readable) and http.ServerResponse (writable). ChildProccess has stdout, stdin, stderr. I guess I need to keep ChildProcess process alive while redirecting it's requests to http.Server always closing connection, and wait it to be opened again for client response. So I see no way to pipe it directly. (P.S. Sorry if my English is really bad)Vanburen
The purpose of streams is to provide a common mechanism to transfer data from one location to another. They also expose events such as data when data is available to be read. I will try to come up with more of a copy and paste example.Pollywog
Well... ok... and how can it helps me? Yet I see the same picture I saw in my previous case: command line prompting for password. What should I do to "capture" password request and redirect it to other stream as a string? Just as a guess tried append to the end of file process.stdout.on("data",function(){console.log("data")}), then replaced data with end and message. Wrong guess, nothing fired. I'll try to update my question to describe my expectations more precisely.Vanburen
M
0

Don't know if this would help but I found the only way to intercept the prompts from child processes was to set the detached option to true when you spawn a new child process.

Like you I couldn't find any info on prompts from child process in node on the interwebs. One would suspect it should go to stdout and then you would have to write to stdin. If I remember correctly you may find the prompt being sent to stderr.

Its a bit amazing to me that others haven't had this problem. Maybe we just doing it wrong.

Moulder answered 8/4, 2016 at 20:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.