执行:显示标准输出“实时”
Exec : display stdout "live"
我有这个简单的脚本:
var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee', function(error, stdout, stderr) {
console.log(stdout);
});
我只是执行一个命令来编译咖啡脚本文件。但是 stdout 永远不会显示在控制台中,因为命令永远不会结束(因为 coffee 的 -w 选项)。如果我直接从控制台执行命令,我会收到如下消息:
18:05:59 - compiled my_file.coffee
我的问题是:是否可以使用节点.js执行显示这些消息?如果是,如何 ?!
不要使用 exec
.使用spawn
,这是一个EventEmmiter
对象。然后,您可以收听stdout
/stderr
事件(spawn.stdout.on('data',callback..)
)发生时。
来自 NodeJS 文档:
var spawn = require('child_process').spawn,
ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});
ls.on('exit', function (code) {
console.log('child process exited with code ' + code.toString());
});
exec
缓冲输出,通常在命令完成执行后返回输出。
exec
还将返回一个作为 EventEmitter 的 ChildProcess 对象。
var exec = require('child_process').exec;
var coffeeProcess = exec('coffee -cw my_file.coffee');
coffeeProcess.stdout.on('data', function(data) {
console.log(data);
});
或者pipe
子进程的标准输出到主标准输出。
coffeeProcess.stdout.pipe(process.stdout);
或者使用生成继承 stdio
spawn('coffee -cw my_file.coffee', { stdio: 'inherit' });
已经有几个答案,但是没有一个提到执行此操作的最佳(也是最简单的)方法,即使用spawn
和{ stdio: 'inherit' }
选项。它似乎会产生最准确的输出,例如在显示来自git clone
的进度信息时。
只需这样做:
var spawn = require('child_process').spawn;
spawn('coffee', ['-cw', 'my_file.coffee'], { stdio: 'inherit' });
感谢@MorganTouvereyQuilling在此评论中指出这一点。
受到Nathanael Smith的回答和Eric Freese的评论的启发,它可以像这样简单:
var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee').stdout.pipe(process.stdout);
我只想补充一点,使用 console.log()
从生成的进程中输出缓冲区字符串的一个小问题是它添加了换行符,这可以将生成的进程输出分散到其他行上。如果使用process.stdout.write()
而不是console.log()
输出stdout
或stderr
,则"按原样"从生成的进程中获得控制台输出。
我在这里看到了该解决方案:节点.js:打印到控制台而不带尾随换行符?
希望可以帮助使用上述解决方案的人(这对于实时输出来说是一个很好的解决方案,即使它来自文档)。
我发现将自定义 exec 脚本添加到执行此操作的实用程序中很有帮助。
公用事业.js
const { exec } = require('child_process')
module.exports.exec = (command) => {
const process = exec(command)
process.stdout.on('data', (data) => {
console.log('stdout: ' + data.toString())
})
process.stderr.on('data', (data) => {
console.log('stderr: ' + data.toString())
})
process.on('exit', (code) => {
console.log('child process exited with code ' + code.toString())
})
}
应用.js
const { exec } = require('./utilities.js')
exec('coffee -cw my_file.coffee')
在查看了所有其他答案后,我最终得出了这个答案:
function oldSchoolMakeBuild(cb) {
var makeProcess = exec('make -C ./oldSchoolMakeBuild',
function (error, stdout, stderr) {
stderr && console.error(stderr);
cb(error);
});
makeProcess.stdout.on('data', function(data) {
process.stdout.write('oldSchoolMakeBuild: '+ data);
});
}
有时data
将是多行,因此oldSchoolMakeBuild
标题将针对多行显示一次。 但这并没有困扰我来改变它。
child_process.spawn 返回一个包含 stdout 和 stderr 流的对象。您可以点击标准输出流来读取子进程发送回 Node 的数据。作为流的 stdout 具有流具有流具有的"数据"、"结束"和其他事件。当您希望子进程将大量数据返回给 Node 时,生成最适合使用——图像处理、读取二进制数据等。
因此,您可以使用下面使用的 child_process.spawn 来解决您的问题。
var spawn = require('child_process').spawn,
ls = spawn('coffee -cw my_file.coffee');
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});
ls.on('exit', function (code) {
console.log('code ' + code.toString());
});
这是一个用打字稿编写的异步帮助程序函数,似乎可以为我解决问题。我想这不适用于长期进程,但对某人来说仍然很方便?
import * as child_process from "child_process";
private async spawn(command: string, args: string[]): Promise<{code: number | null, result: string}> {
return new Promise((resolve, reject) => {
const spawn = child_process.spawn(command, args)
let result: string
spawn.stdout.on('data', (data: any) => {
if (result) {
reject(Error('Helper function does not work for long lived proccess'))
}
result = data.toString()
})
spawn.stderr.on('data', (error: any) => {
reject(Error(error.toString()))
})
spawn.on('exit', code => {
resolve({code, result})
})
})
}
我找到了另一种方法:
const { spawn } = require('child_process');
export const execCommand = async (command) => {
return new Promise((resolve, reject) => {
const [cmd, ...args] = command.split(' ');
const childProcess = spawn(cmd, args);
childProcess.stdout.on('data', (data) => {
process.stdout.write(data.toString());
});
childProcess.stderr.on('data', (data) => {
process.stderr.write(data.toString());
});
childProcess.on('error', (error) => {
reject(error);
});
childProcess.on('exit', (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`Command exited with code ${code}.`));
}
});
});
};
此代码提供了从执行的命令获取实时输出并将所有标准输出和标准derr重定向到父进程的能力。它还允许以与在 bash/sh(单字符串输入)中相同的方式使用该命令。在这里,我使用 process.stdout.write
来获得更准确的输出,而不是在其他答案中使用的console.log
。
用法:
await execCommand('sudo apt-get update');
await execCommand('sudo apt-get install -y docker.io docker-compose');
注意:与exec
相比,它不支持使用 &&
执行多个命令。因此,每个命令都应使用单个execCommand
语句执行。
下面是一个同时支持实时流式传输和 shell 执行的简化版本:
const { spawn } = require('child_process');
export const execCommand = async (command) => {
return new Promise((resolve, reject) => {
const childProcess = spawn(command, {
stdio: 'inherit',
shell: true
});
childProcess.on('error', (error) => {
reject(error);
});
childProcess.on('exit', (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`Command exited with code ${code}.`));
}
});
});
};
用法:
await execCommand('sudo apt-get update && sudo apt-get install -y docker.io docker-compose');
- 将咖啡转换为javascript,并将结果显示在Emacs中的标准输出中
- 在文本区域中显示 SSH2 标准输出和标准输出
- 如何处理节点.js中/从节点输出的 (cli) 标准输出流的字符编码
- 在 Jasmine 测试中将 console.log() 的调用重定向到标准输出
- 获取块上的可执行文件标准输出
- 执行:显示标准输出“实时”
- 过程和过程之间的区别是什么?标准和进程.标准输出与HTTP请求和响应
- Nodejs child_process.exec:在控制台上禁用标准输出打印
- 我怎么能使用回调时,输出被打印到标准输出在ruby
- 从node.js运行脚本,捕获标准输出,通过web套接字发送
- 分割标准输出并将每个部分管道到命令
- 将标准输出流转换为html (add
在美化下) - 在Meteor/Node中确定从服务器返回的输出是标准错误还是标准输出
- 奇怪的执行问题-标准输出不显示-回调不工作
- 从金字塔视图动态输出标准输出'子流程.打开到网页
- 从正在等待输入的衍生进程中读取标准输出
- Node.js实时流式传输ffmpeg标准输出到res
- Node.js调用perl脚本并获得标准输出
- 如何将标准输出从nodejs实时发送到angularjs
- 节点.js生成进程如何使用标准输出分离的每一行在函数中使用