NodeJS. Child_process.spawn. 处理进程输入提示

6
我目前正在为git编写Web界面,通过子进程spawn访问git。在简单的“命令->响应”机制下一切都很好,但是我无法理解如何处理命令提示(例如git fetch要求密码)。假设有一些事件被触发,但我不知道该听什么。我看到的只是在Node.js进程本身运行的命令行中出现“git_user@myserver's password: _”。

将此请求重定向到我的Web应用程序将非常好,但这是否可能呢?
我已经尝试在所有流(stdout、stdin、stderr)上监听message、data、pipe、end、close、readable,但没有一个在密码提示上触发。
这是我的工作解决方案(没有提到实验):
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);
});

能帮我调查一下吗?

更新

目前的情况是:在我的GIT网页界面上有一个“FETCH”按钮(例如,用于简单的“git fetch”)。当我按下它时,会生成HTTP请求并发送到由http.createServer(callback).listen(8080)创建的node.js服务器。 callback函数接收我的请求并创建child_process.spawn('git',['-C','path/to/local/repo','fetch'])。这段时间内,我只看到我的网页界面上有加载页面,但是如果我切换到运行node脚本的命令行窗口,我会看到密码提示符。现在假设我无法切换到控制台窗口,因为我是远程工作。

我想在我的网页界面上看到密码提示符。如果child_process会在要求用户输入时在child.stdin(或其他位置)发出某些事件,那将非常容易实现。在这种情况下,我将字符串“来吧,小伙子,git想知道你的密码!在这里输入:_______”发送回Web客户端(通过response.end(str)),并将继续等待包含所需密码的客户端响应的下一个http连接。然后只需将其child.stdin.write(pass)写入git进程即可。

这个解决方案可行吗?或者有没有不涉及父进程的命令行的解决方法。

更新2

刚刚尝试了在所有可能的事件(stdout和stderr(可读,数据,结束,关闭,错误),stdin(drain,完成,pipe,unpipe,错误),child(消息,退出,关闭,断开连接,消息))上添加侦听器。将git流导入后,尝试在process.stdout,process.stderr上使用相同的侦听器。

密码请求上没有触发任何操作...


卡在同一个地方了。你找到任何解决办法了吗?https://xkcd.com/979/ - Shashank Goyal
@ShashankGoyal 不好意思,还没有。我仍然需要切换到终端来进行提示... - MadBrozzeR
2个回答

1
你的代码无法正常工作的主要原因是因为只有在Git过程执行后才能找出发生了什么。
使用spawn的主要原因是,生成的进程可以进行配置,并且父进程中的stdout和stderr是可读的流。
我刚试过这段代码,它运行得非常好。这里是一个生成进程来执行git推送的示例。然而,正如您所知道的,git会要求您输入用户名和密码。
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. 创建一个本地的git仓库,并设置好相关内容,以便执行上述的push命令。但实际上,您可以执行任何git命令。
  2. 将此内容复制到名为git_process.js的文件中。
  3. 使用node git_process.js运行。

也许我比想象中更像一个新手,但我真的不知道需要在我的代码中应用什么。直接复制粘贴(带有我的变量名)会导致外部模块异常。将密码作为属性传递给 git(如果我理解正确)不是一个选项,因为并非所有存储库都要求这样做。外部模块也不是我的选择,因为我想让“内部过程”对我更加清晰明了,而不是将其视为某种魔法。 - MadBrozzeR
我不确定是否想要直接将一个流导入另一个流。在我的情况下,我有两个对象:http.ServerChildProccess。第一个具有流http.IncomingMessage(可读)和http.ServerResponse(可写)。ChildProccess具有stdoutstdinstderr。我猜我需要保持ChildProcess进程处于活动状态,同时将其请求重定向到http.Server,总是关闭连接,并等待它再次打开以供客户端响应。所以我看不到直接导入的方法。(P.S.如果我的英语真的很糟糕,对不起) - MadBrozzeR
流的目的是提供一个通用机制,将数据从一个位置传输到另一个位置。它们还公开事件,例如当可读取数据时的数据。我将尝试提供更多复制和粘贴的示例。 - Peter Hauge
好的...好吧...那这对我有什么帮助呢?我看到了和之前一样的情况:命令行提示输入密码。我该怎么做才能“捕获”密码请求并将其重定向到其他流中作为字符串?只是猜测尝试在文件末尾添加 process.stdout.on("data",function(){console.log("data")}),然后用 endmessage 替换 data。猜错了,没有触发任何事件。我会尝试更新我的问题,更准确地描述我的期望。 - MadBrozzeR

0

不知道这是否有所帮助,但我发现拦截子进程提示的唯一方法是在生成新的子进程时将detached选项设置为true。

和你一样,我在互联网上找不到有关node中子进程提示的任何信息。人们会怀疑它应该传递到stdout,然后您需要写入stdin。如果我记得正确,您可能会发现提示被发送到stderr。

对我来说,令人惊奇的是其他人没有遇到过这个问题。也许我们做错了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接