2020-09-12 08:03:18 -04:00
|
|
|
# Creating a subprocess
|
2020-05-06 18:21:13 -04:00
|
|
|
|
2020-09-12 08:03:18 -04:00
|
|
|
## Concepts
|
2020-05-06 18:21:13 -04:00
|
|
|
|
2020-09-12 08:03:18 -04:00
|
|
|
- Deno is capable of spawning a subprocess via
|
2020-09-27 13:49:41 -04:00
|
|
|
[Deno.run](https://doc.deno.land/builtin/stable#Deno.run).
|
|
|
|
- `--allow-run` permission is required to spawn a subprocess.
|
|
|
|
- Spawned subprocesses do not run in a security sandbox.
|
2020-09-12 08:03:18 -04:00
|
|
|
- Communicate with the subprocess via the
|
|
|
|
[stdin](https://doc.deno.land/builtin/stable#Deno.stdin),
|
|
|
|
[stdout](https://doc.deno.land/builtin/stable#Deno.stdout) and
|
2020-09-27 13:49:41 -04:00
|
|
|
[stderr](https://doc.deno.land/builtin/stable#Deno.stderr) streams.
|
2020-10-20 07:11:38 -04:00
|
|
|
- Use a specific shell by providing its path/name and its string input switch,
|
|
|
|
e.g. `Deno.run({cmd: ["bash", "-c", '"ls -la"']});
|
2020-09-12 08:03:18 -04:00
|
|
|
|
|
|
|
## Simple example
|
|
|
|
|
|
|
|
This example is the equivalent of running `'echo hello'` from the command line.
|
2020-05-06 18:21:13 -04:00
|
|
|
|
|
|
|
```ts
|
2020-09-12 08:03:18 -04:00
|
|
|
/**
|
|
|
|
* subprocess_simple.ts
|
|
|
|
*/
|
|
|
|
|
2020-05-06 18:21:13 -04:00
|
|
|
// create subprocess
|
|
|
|
const p = Deno.run({
|
|
|
|
cmd: ["echo", "hello"],
|
|
|
|
});
|
|
|
|
|
|
|
|
// await its completion
|
|
|
|
await p.status();
|
|
|
|
```
|
|
|
|
|
|
|
|
Run it:
|
|
|
|
|
|
|
|
```shell
|
|
|
|
$ deno run --allow-run ./subprocess_simple.ts
|
|
|
|
hello
|
|
|
|
```
|
|
|
|
|
2020-09-12 08:03:18 -04:00
|
|
|
## Security
|
|
|
|
|
|
|
|
The `--allow-run` permission is required for creation of a subprocess. Be aware
|
|
|
|
that subprocesses are not run in a Deno sandbox and therefore have the same
|
|
|
|
permissions as if you were to run the command from the command line yourself.
|
|
|
|
|
|
|
|
## Communicating with subprocesses
|
2020-05-06 18:21:13 -04:00
|
|
|
|
2020-09-12 08:03:18 -04:00
|
|
|
By default when you use `Deno.run()` the subprocess inherits `stdin`, `stdout`
|
|
|
|
and `stderr` of the parent process. If you want to communicate with started
|
|
|
|
subprocess you can use `"piped"` option.
|
2020-05-06 18:21:13 -04:00
|
|
|
|
|
|
|
```ts
|
2020-09-12 08:03:18 -04:00
|
|
|
/**
|
|
|
|
* subprocess.ts
|
|
|
|
*/
|
2020-05-06 18:21:13 -04:00
|
|
|
const fileNames = Deno.args;
|
|
|
|
|
|
|
|
const p = Deno.run({
|
|
|
|
cmd: [
|
|
|
|
"deno",
|
|
|
|
"run",
|
|
|
|
"--allow-read",
|
2020-07-31 05:12:20 -04:00
|
|
|
"https://deno.land/std@$STD_VERSION/examples/cat.ts",
|
2020-05-06 18:21:13 -04:00
|
|
|
...fileNames,
|
|
|
|
],
|
|
|
|
stdout: "piped",
|
|
|
|
stderr: "piped",
|
|
|
|
});
|
|
|
|
|
|
|
|
const { code } = await p.status();
|
|
|
|
|
|
|
|
if (code === 0) {
|
|
|
|
const rawOutput = await p.output();
|
|
|
|
await Deno.stdout.write(rawOutput);
|
|
|
|
} else {
|
|
|
|
const rawError = await p.stderrOutput();
|
|
|
|
const errorString = new TextDecoder().decode(rawError);
|
|
|
|
console.log(errorString);
|
|
|
|
}
|
|
|
|
|
|
|
|
Deno.exit(code);
|
|
|
|
```
|
|
|
|
|
|
|
|
When you run it:
|
|
|
|
|
|
|
|
```shell
|
|
|
|
$ deno run --allow-run ./subprocess.ts <somefile>
|
|
|
|
[file content]
|
|
|
|
|
|
|
|
$ deno run --allow-run ./subprocess.ts non_existent_file.md
|
|
|
|
|
|
|
|
Uncaught NotFound: No such file or directory (os error 2)
|
|
|
|
at DenoError (deno/js/errors.ts:22:5)
|
|
|
|
at maybeError (deno/js/errors.ts:41:12)
|
|
|
|
at handleAsyncMsgFromRust (deno/js/dispatch.ts:27:17)
|
|
|
|
```
|