Search code examples
shellgoogle-chrome-devtoolsdeno

Deno: How to run shell command and read output before child process completes?


How do I launch a child process (via shell) and read its output without (before) the child process returns?

I"m launching Google Chrome via the Mac Terminal with the following command: /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --no-first-run --no-default-browser-check --user-data-dir=$(mktemp -d -t 'chrome-remote_data_dir') This works well but the process does not end/return until I'me done with the browser. As soon as its launched, however, it prints the following to the console: "DevTools listening on ws://127.0.0.1:9222/devtools/browser/d43342be-66bc-41d4-b591-a7ee22d1c528"

I need to scrape that. I can successfully launch this in Deno (v. 1.36.3) using:

const myCMD = `/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome`;

const p = Deno.run({
  cmd: [
    myCMD,
    "--remote-debugging-port=9222",
    "--no-first-run",
    "--no-default-browser-check",
    "--user-data-dir=$(mktemp -d -t 'chrome-remote_data_dir')",
  ],
  stdout: "piped",
  stderr: "piped",
  stdin: "piped",
});

await p.stdin.write(new TextEncoder().encode("Coming from stdin\n"));
await p.status();

But I can't read the value I need because the process does not complete and therefore the output never returns. Is there a way to read what a child process writes to the console before it returns?

FYI... I used the following article for reference: https://medium.com/deno-the-complete-reference/run-shell-commands-in-deno-26c3e9b72e03


Solution

  • You need to read from p.stdout and p.stderr, both are an instance of FsFile so you can use .readable to access the ReadableStream or use the .read method of FsFile

    const myCMD = `/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome`;
    
    const p = Deno.run({
      cmd: [
        myCMD,
        "--remote-debugging-port=9222",
        "--no-first-run",
        "--no-default-browser-check",
        "--user-data-dir=$(mktemp -d -t 'chrome-remote_data_dir')",
      ],
      stdout: "piped",
      stderr: "piped",
      stdin: "piped",
    });
    
    (async() => {
       for await(const chunk of p.stdout.readable) {
           console.log(chunk, new TextDecoder().decode(chunk))
       }
    })();
    
    (async() => {
        for await(const chunk of p.stderr.readable) {
            console.log(chunk, new TextDecoder().decode(chunk))
        }
    })();
    
    await p.stdin.write(new TextEncoder().encode("Coming from stdin\n"));
    await p.status();
    

    Now you'll see the output of the process.