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();

Tags:

Deno