【问题标题】:NodeJS. Child_process.spawn. Handle process' input prompt节点JS。 Child_process.spawn。处理进程的输入提示
【发布时间】:2016-02-02 22:14:15
【问题描述】:

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

将此请求重定向到我的 Web 应用程序会很棒,但它甚至可能吗?

我尝试在所有流(stdout、stdin、stderr)上收听messagedatapipeendclosereadable,但没有人触发密码提示。

这是我的工作解决方案(未提及实验):

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 Web 界面上有一个按钮“FETCH”(例如,简单的“git fetch”)。当我按下它时,会生成 http 请求并发送到由http.createServer(callback).listen(8080) 创建的 node.js 服务器。 callback 函数接收我的请求并创建 child_process.spawn('git',['-C','path/to/local/repo','fetch'])。一直以来,我在 Web 界面上只看到加载屏幕,但如果我切换到运行节点脚本的命令行窗口,我会看到密码提示。现在让我们假设我无法将窗口切换到控制台,因为我在远程工作。

我想在我的网页界面上看到密码提示。例如,如果 child_process 在提示用户输入时会在child.stdin(或其他地方)上发出一些事件,这将很容易实现。在这种情况下,我会将字符串“来吧,伙计,git 想知道你的密码!在此处输入:_______”发送回 Web 客户端(response.end(str)),并将继续等待下一个带有客户端响应的 http 连接,包含所需的密码。然后只需 child.stdin.write(pass) 将其转至 git 进程。

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

更新2

刚刚尝试将侦听器附加到官方文档中描述的所有可能事件:stdout 和 stderr(可读、数据、结束、关闭、错误)、stdin(drain、finish、pipe、unpipe、error)、child(消息、退出、关闭、断开连接、消息)。

在将 git 流传递给它之后,在 process.stdout、process.stderr 上尝试了相同的侦听器。

密码请求没有任何反应...

【问题讨论】:

  • 卡在同一个地方。您找到任何解决方案了吗? xkcd.com/979
  • @ShashankGoyal 不,很遗憾。仍在切换到我的终端以获取提示...

标签: node.js git stream child-process


【解决方案1】:

你的代码不能工作的主要原因是你只知道你的 Git 进程在执行之后发生了什么。

使用spawn的主要原因是因为spawn的进程可以配置,stdout和stderr是父进程中的可读流。

我刚刚试用了这段代码,效果很好。这是一个生成进程以执行 git push 的示例。但是,您可能知道 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 repo 并设置一些东西,以便您可以执行上述推送命令。但是,你真的可以执行任何 git 命令。
  2. 将其复制到名为 git_process.js 的文件中。
  3. 使用节点 git_process.js 运行

【讨论】:

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

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

和你一样,我在互联网上的节点中找不到任何关于子进程提示的信息。有人会怀疑它应该去标准输出,然后你必须写信给标准输入。如果我没记错的话,您可能会发现提示正在发送到 stderr。

其他人没有遇到这个问题,这让我有点惊讶。也许我们只是做错了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-18
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    • 2013-09-14
    • 2018-03-24
    • 2016-05-02
    • 1970-01-01
    相关资源
    最近更新 更多