denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
97.95k stars 5.39k forks source link

Redirect between stderr and stdout in `Deno.Command` #2750

Open nayeemrmn opened 5 years ago

nayeemrmn commented 5 years ago

Ref https://github.com/denoland/deno/pull/1828#issuecomment-467719574

Rather than adding Process::combinedOutput(), I propose modelling 2>&1 in RunOptions.

Ref https://docs.python.org/3/library/subprocess.html#using-the-subprocess-module

export interface RunOptions {
  cmd: string[];
  cwd?: string;
  env?: {
    [key: string]: string;
  };
  stdout?: ProcessStdio | number;
  stderr?: ProcessStdio | number;
  stdin?: ProcessStdio | number;
}

->

export interface RunOptions {
  cmd: string[];
  cwd?: string;
  env?: {
    [key: string]: string;
  };
  stdout?: ProcessStdio | number;
  stderr?: ProcessStdio | "stdout" | number;
  stdin?: ProcessStdio | number;
}
brandonkal commented 4 years ago

This would be very convenient when a program outputs on stdout when it should be on Deno's stderr. This would be especially nice if it streamed.

Process::combinedOutput() may be nice as well but not as useful if the Promise only resolved when the process exits.

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

jeff-hykin commented 2 years ago

Thanks to some help from crowlKats in the discord, I created a Sprinter to make subprocesses more convenient. If people find it useful I'll upgrade it over time.

import { run, Out, Stdout, Stderr, Overwrite, AppendTo, Timeout } from "https://deno.land/x/sprinter@0.2.0/index.js"

// yes &> my_log.txt
await run("yes", Out(Overwrite("my_log.txt")))

// yes &>> my_log.txt
await run("yes", Out(AppendTo("my_log.txt")))

// yes 1>> my_log.txt
await run("yes", Stdout(AppendTo("my_log.txt")))

// yes 1>my_log.txt 2>>my_error_log.txt
await run("yes", Stdout(Overwrite("my_log.txt")), Stderr(AppendTo("my_error_log.txt")))

// using an already-open file
const file = await Deno.open("./my_log.txt", { read: false, write: true, create: true, })
await run("yes", Out(AppendTo(file)))

// with a timeout
await run("yes", Out(AppendTo(file)), Timeout({ gentlyBy: 100, waitBeforeUsingForce: 500}))

There's more, like piping multiple files as input and multiple files as output, but those above should cover the basic use-cases.