从子进程流式传输标准输出
Stream stdout from subprocess
我 运行 一个 Docker 在 Deno 中构建为一个子进程,并且希望将标准输出流式传输到父标准输出 (Deno.stdout),以便它立即输出。
我怎样才能做到这一点?
目前我有以下内容,但在子流程完成之前它不会输出任何内容。
const p = Deno.run({
cmd: ['docker', 'build', '.'],
stdout: 'piped'
});
const stdout = await p.output();
await Deno.stdout.write(stdout);
p
代表进程,Deno.run
returns the process state 在 return 上(不是标准输出):
console.log(await p.status());
// { success: true, code: 0 }
由于您正在等待状态,stdout 将不会流式传输输出,直到该过程完成。
尝试 using the process 像这样:
const p = Deno.run({ cmd, stderr: 'piped', stdout: 'piped' });
const [status, stdout, stderr] = await Promise.all([
p.status(),
p.output(),
p.stderrOutput()
]);
console.log(new TextDecoder().decode(stdout)); // since it's returned as UInt8Array
p.close();
但它仍然会等到子进程完成。
你已经不远了;您只需要在等待该过程之前开始管道输出过程。您还可以进行一些其他优化,例如使用 Deno.copy
将子进程的输出通过管道传输到主进程的标准输出,而无需在内存中复制内容。
import { copy } from "https://deno.land/std@0.104.0/io/util.ts";
const cat = Deno.run({
cmd: ["docker", "build", "--no-cache", ".", "-t", "foobar:latest"],
cwd: "/path/to/your/project",
stdout: "piped",
stderr: "piped",
});
copy(cat.stdout, Deno.stdout);
copy(cat.stderr, Deno.stderr);
await cat.status();
console.log("Done!");
如果你想在每一行前面加上它来自的进程的名称(当你有多个子进程时很有用运行,你可以创建一个使用标准库的简单函数readLines
功能和一个文本编码器来做到这一点
import { readLines } from "https://deno.land/std@0.104.0/io/mod.ts";
import { writeAll } from "https://deno.land/std@0.104.0/io/util.ts";
async function pipeThrough(
prefix: string,
reader: Deno.Reader,
writer: Deno.Writer,
) {
const encoder = new TextEncoder();
for await (const line of readLines(reader)) {
await writeAll(writer, encoder.encode(`[${prefix}] ${line}\n`));
}
}
const cat = Deno.run({
cmd: ["docker", "build", "--no-cache", ".", "-t", "foobar:latest"],
cwd: "/path/to/your/project",
stdout: "piped",
stderr: "piped",
});
pipeThrough("docker", cat.stdout, Deno.stdout);
pipeThrough("docker", cat.stderr, Deno.stderr);
await cat.status();
console.log("Done!");
我 运行 一个 Docker 在 Deno 中构建为一个子进程,并且希望将标准输出流式传输到父标准输出 (Deno.stdout),以便它立即输出。
我怎样才能做到这一点?
目前我有以下内容,但在子流程完成之前它不会输出任何内容。
const p = Deno.run({
cmd: ['docker', 'build', '.'],
stdout: 'piped'
});
const stdout = await p.output();
await Deno.stdout.write(stdout);
p
代表进程,Deno.run
returns the process state 在 return 上(不是标准输出):
console.log(await p.status());
// { success: true, code: 0 }
由于您正在等待状态,stdout 将不会流式传输输出,直到该过程完成。
尝试 using the process 像这样:
const p = Deno.run({ cmd, stderr: 'piped', stdout: 'piped' });
const [status, stdout, stderr] = await Promise.all([
p.status(),
p.output(),
p.stderrOutput()
]);
console.log(new TextDecoder().decode(stdout)); // since it's returned as UInt8Array
p.close();
但它仍然会等到子进程完成。
你已经不远了;您只需要在等待该过程之前开始管道输出过程。您还可以进行一些其他优化,例如使用 Deno.copy
将子进程的输出通过管道传输到主进程的标准输出,而无需在内存中复制内容。
import { copy } from "https://deno.land/std@0.104.0/io/util.ts";
const cat = Deno.run({
cmd: ["docker", "build", "--no-cache", ".", "-t", "foobar:latest"],
cwd: "/path/to/your/project",
stdout: "piped",
stderr: "piped",
});
copy(cat.stdout, Deno.stdout);
copy(cat.stderr, Deno.stderr);
await cat.status();
console.log("Done!");
如果你想在每一行前面加上它来自的进程的名称(当你有多个子进程时很有用运行,你可以创建一个使用标准库的简单函数readLines
功能和一个文本编码器来做到这一点
import { readLines } from "https://deno.land/std@0.104.0/io/mod.ts";
import { writeAll } from "https://deno.land/std@0.104.0/io/util.ts";
async function pipeThrough(
prefix: string,
reader: Deno.Reader,
writer: Deno.Writer,
) {
const encoder = new TextEncoder();
for await (const line of readLines(reader)) {
await writeAll(writer, encoder.encode(`[${prefix}] ${line}\n`));
}
}
const cat = Deno.run({
cmd: ["docker", "build", "--no-cache", ".", "-t", "foobar:latest"],
cwd: "/path/to/your/project",
stdout: "piped",
stderr: "piped",
});
pipeThrough("docker", cat.stdout, Deno.stdout);
pipeThrough("docker", cat.stderr, Deno.stderr);
await cat.status();
console.log("Done!");