我正在编写一个电子应用程序,它执行终端命令并将输出写入应用程序。如果我只执行一条命令,这很简单:
const { spawn } = require('child_process');
commandOutput = document.getElementById("command-output") // textarea
status = document.getElementById("status") // div
command = "some"
args = ["command"]
dir = "some/dir"
var child = spawn(command, args, {
cwd: dir
});
child.on('error', function (err) {
commandOutput.value += 'error: <' + err + '>';
});
child.stdout.on('data', function (data) {
commandOutput.value += data;
});
child.stderr.on('data', function (data) {
commandOutput.value += 'stderr: <' + data + '>';
});
child.on('close', function (code) {
status.innerHTML = 'child process exited with code ' + code;
});我喜欢这种方法,因为输出是流式的,而不是缓冲的,允许我将其实时写入UI,而不是等待进程完成(这可能需要一些时间)。但是,我想不出一种方法来一个接一个地产生多个同步命令。我知道有一个命令spawnSync可以处理这个问题,但是文档并没有描述如何使用它。或者,如果有更好的方法,我也持开放态度。
发布于 2020-10-06 21:13:46
实现这一点的一种方法是在前一个命令的close事件上生成下一个命令。假设您当前的代码,您可以使用类似以下内容:
child.on ("close", function (code) {
status.innerHTML = 'child process exited with code ' + code;
// Now spawn the second child
var secondChild = spawn (secondCmd, secondArgs, { cwd: dir });
secondChild.on ("error", (err) => { /* error handler */});
// Register all other handlers as well...
});如果您希望对输出进行缓冲,那么这是一种可行的方法。此外,您可以将所有代码生成过程放入一个函数中,并在close事件上调用该函数,就像这样:
function spawnExternalProgram (command, args, dir, next) {
// Suggestion: Clear the commandOutput field here?
var child = spawn(command, args, {
cwd: dir
});
child.on('error', function (err) {
commandOutput.value += 'error: <' + err + '>';
});
child.stdout.on('data', function (data) {
commandOutput.value += data;
});
child.stderr.on('data', function (data) {
commandOutput.value += 'stderr: <' + data + '>';
});
child.on('close', function (code) {
status.innerHTML = 'child process exited with code ' + code;
next ();
});
}
spawnExternalProgram ("some", [ "command" ], "some/dir", function () { // 1
spawnExternalProgram ("some", [ "other", "command" ], "some/dir", function () { //2
spawnExternalProgram ("yet", [ "another", "command" ], "some/dir", () => {}); // 3
});
});一旦前一个进程退出,这将一个接一个地产生命令1、2和3。next的最后一个参数,即() => {}等同于function () {}。
正如您已经提到的,另一个选择是使用spawnSync。有了这个模块,你可以通过一个函数调用一个接一个地产生你的进程。但是,请注意,如果您从渲染器进程派生进程,这可能会阻塞您的UI。用法类似:
const { spawnSync } = require('child_process');
commandOutput = document.getElementById("command-output")
status = document.getElementById("status")
command = "some"
args = ["command"]
dir = "some/dir"
var childResultOne = spawnSync (command, args, { cwd: dir });
// Check if the process terminated:
var childOneHasTerminated = childResultOne.status === null || childResultOne.status !== 0;
// Access the stdout buffer via the childResultOne object:
var childOneOutput = childResultOne.stdout;
// ---
command = "someOther"
args = ["command", "asWell"]
dir = "some/other/dir"
// Spawn a second child process
var childResultTwo = spawnSync (command, args, { cwd: dir });
// Do all the checks as above.请注意,这将仅在进程退出后,即运行成功(status === 0)、终止(status === null && signal !== null)或崩溃(status !== 0)后调用spawnSync之后运行代码。这基本上就是Linux或MacOS Shell或Window的cmd.exe解释shell脚本或批处理文件的方式--一个接一个的命令。
https://stackoverflow.com/questions/64226373
复制相似问题