How do I run an arbitrary shell command from Deno?
Make sure to await
status
or output
of the child process created with Deno.run
.
Otherwise, the process might be killed, before having executed any code. For example:
deno run --allow-run main.ts
main.ts:
const p = Deno.run({
cmd: ["deno", "run", "--allow-write", "child.ts"],
});
const { code } = await p.status(); // (*1); wait here for child to finish
p.close();
child.ts:
// If we don't wait at (*1), no file is written after 3 sec delay
setTimeout(async () => {
await Deno.writeTextFile("file.txt", "Some content here");
console.log("finished!");
}, 3000);
Pass arguments via stdin
/ stdout
:
main.ts:
const p = Deno.run({
cmd: ["deno", "run", "--allow-write", "child.ts"],
// Enable pipe between processes
stdin: "piped",
stdout: "piped",
stderr: "piped",
});
if (!p.stdin) throw Error();
// pass input to child
await p.stdin.write(new TextEncoder().encode("foo"));
await p.stdin.close();
const { code } = await p.status();
if (code === 0) {
const rawOutput = await p.output();
await Deno.stdout.write(rawOutput); // could do some processing with output
} else { /* error */ }
child.ts:
import { readLines } from "https://deno.land/std/io/bufio.ts"; // convenient wrapper
// read given input argument
let args = "";
for await (const line of readLines(Deno.stdin)) {
args += line;
}
setTimeout(async () => {
await Deno.writeTextFile("file.txt", `Some content here with ${args}`);
console.log(`${args} finished!`); // prints "foo finished!""
}, 3000);
There is also a good example resource in Deno docs.
In order to run a shell command, you have to use Deno.run
, which requires --allow-run
permissions.
There's an ongoing discussion to use --allow-all
instead for running a subprocess
The following will output to stdout
.
// --allow-run
const process = Deno.run({
cmd: ["echo", "hello world"]
});
// Close to release Deno's resources associated with the process.
// The process will continue to run after close(). To wait for it to
// finish `await process.status()` or `await process.output()`.
process.close();
If you want to store the output, you'll have to set stdout/stderr
to "piped"
const process = Deno.run({
cmd: ["echo", "hello world"],
stdout: "piped",
stderr: "piped"
});
const output = await process.output() // "piped" must be set
const outStr = new TextDecoder().decode(output);
/*
const error = await p.stderrOutput();
const errorStr = new TextDecoder().decode(error);
*/
process.close();