gpt4 book ai didi

node.js - child_process.spawn() 在子进程提示输入时挂起

转载 作者:搜寻专家 更新时间:2023-10-31 23:44:22 40 4
gpt4 key购买 nike

我编写了一个 Node 脚本来管理将 git 存储库部署到 AWS 自动缩放组。

该脚本使用 child_process.spawn() 来自动化 git、克隆存储库、 checkout 标签等。

如果 git 可以找到合适的凭据,它就可以正常工作。但是,如果未自动找到凭据,则生成的进程将尝试提示输入凭据,此时将挂起。即使是 Ctrl-C 也无法退出。必须结束整个 shell session 。

spawn() 调用被包装在一个返回 Promise 的函数中。我的功能看起来像这样......

const cp = require('child_process');

let spawn_promise = (command, args, options, stream_output) => {
return new Promise((resolve, reject) => {
console.log(chalk.cyan(`${command} [${args}]`));

let childProcess = cp.spawn(command, args, options);
let std_out = '';
let std_err = '';

childProcess.stdout.on('data', function (data) {
std_out += data.toString();
if (stream_output)
console.log(chalk.green(data.toString()));
});
childProcess.stderr.on('data', function (data) {
std_err += data.toString();
if (stream_output)
console.log(chalk.red(data.toString()));
});

childProcess.on('close', (code) => {
if (code === 0) {
console.log(chalk.blue(`exit_code = ${code}`));
return resolve(std_out);
}
else {
console.log(chalk.yellow(`exit_code = ${code}`));
return reject(std_err);
}
});

childProcess.on('error', (error) => {
std_err += error.toString();
if (stream_output)
console.log(chalk.red(error.toString()));
});
});
}

我是这样调用它的……

return spawn_promise('git', ['fetch', '--all'], {env: process.env})
.then(() => {
...

它大部分工作得很好,并且可以很容易地操纵输出和错误等。

不过,如果生成的进程需要输入,我很难找到处理输入的好方法。

该问题的临时解决方法是添加一个环境变量以防止 git 提示输入凭据,如果它在用户环境中找不到凭据则抛出错误。然而这并不理想。理想情况下,我希望能够优雅地处理标准输入,并且仍然能够像我目前所做的那样捕获和处理输出和错误。

我可以通过这样做来解决输入问题...

let childProcess = cp.spawn(command, args, { stdio: [process.stdin, process.stdout, process.stderr] });

这允许 git 正确提示输入凭据。但是,我随后失去了捕获命令输出的能力。

处理这个问题的正确方法是什么?

我还应该提一下,该函数还会自动执行一些运行时间相对较长的进程,以构建 AMI 等。这就是“stream_output”参数的用途。我希望能够实时查看命令的输出,而不是等到过程完成。

最佳答案

child_processstdin 来处理输入,当 child_process 运行时,同样可以用来输入输入。

看下面的例子:

test.sh:

#!/bin/sh

echo "Please enter something:"
read ch
echo "Thanks"

当我在这个终端上运行时:

shell-input $ ./test.sh 
Please enter something:
something
Thanks
shell-input $

当我使用您的代码运行时:测试.js:

const cp = require('child_process');
const chalk = require('chalk');

let spawn_promise = (command, args, options, stream_output) => {
return new Promise((resolve, reject) => {
console.log(chalk.cyan(`${command} [${args}]`));

let childProcess = cp.spawn(command, args, options);
let std_out = '';
let std_err = '';

childProcess.stdout.on('data', function (data) {
std_out += data.toString();
if (stream_output)
console.log(chalk.green(data.toString()));
});
childProcess.stderr.on('data', function (data) {
std_err += data.toString();
if (stream_output)
console.log(chalk.red(data.toString()));
});

childProcess.on('close', (code) => {
if (code === 0) {
console.log(chalk.blue(`exit_code = ${code}`));
return resolve(std_out);
}
else {
console.log(chalk.yellow(`exit_code = ${code}`));
return reject(std_err);
}
});

childProcess.on('error', (error) => {
std_err += error.toString();
if (stream_output)
console.log(chalk.red(error.toString()));
});
});
}

spawn_promise('./test.sh', { env: process.env})
.then(() => {
});

输出:

 $ node test.js 
./test.sh [[object Object]]

<stuck here>

我修改了您的代码以包含以下内容:

...
childProcess.stdout.on('data', function (data) {


if (data == "Please enter something:\n")
{
childProcess.stdin.write("something\n");
//childProcess.stdin.end(); // Call this to end the session
}

std_out += data.toString();
if (stream_output)
console.log(chalk.green(data.toString()));
});
...

然后我再次运行:

$ node test.js 
./test.sh [[object Object]]
exit_code = 0

它有效。基本上你需要找出 stdin 何时等待输入。为此,您可以在 stdout 上使用 data 事件,然后在 stdin 上写入。如果您没有要写入的凭据,则可以通过调用 childProcess.stdin.end();

结束 session

关于node.js - child_process.spawn() 在子进程提示输入时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55723644/

40 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com