txt: ## ipc.md
  Inter-process communication
  
  Programs running other programs and communicating with them
  
  # [Running programs](#Inter-process_communication "go to top of document")[§](#Running_programs "direct link")
  
  Many programs need to be able to run other programs, and we need to pass information to them and receive their output and exit status. Running a program in Raku is as easy as:
  
  ```raku
  run 'git', 'status';
  ```
  
  This line runs the program named "git" and passes "git" and "status" to its command-line. It will find the program using the `%*ENV<PATH>` setting.
  
  If you would like to run a program by sending a command-line to the shell, there's a tool for that as well. All shell metacharacters are interpreted by the shell, including pipes, redirects, environment variable substitutions and so on.
  
  ```raku
  shell 'ls -lR | gzip -9 > ls-lR.gz';
  ```
  
  Caution should be taken when using `shell` with user input.
  
  # [The](#Inter-process_communication "go to top of document") [`Proc`](/type/Proc) object[§](#The_Proc_object "direct link")
  
  Both `run` and `shell` return a [`Proc`](/type/Proc) object, which can be used to communicate with the process in more detail. Please note that unless you close all output pipes, the program will usually not terminate.
  
  ```raku
  my $git = run 'git', 'log', '--oneline', :out;
  for $git.out.lines -> $line {
      my ($sha, $subject) = $line.split: ' ', 2;
      say "$subject [$sha]";
  }
  $git.out.close();
  ```
  
  If the program fails (exits with a non-zero exit code), it will throw an exception when the returned [`Proc`](/type/Proc) object is sunk. You can save it into a variable, even anonymous one, to prevent the sinking:
  
  ```raku
  $ = run '/bin/false'; # does not sink the Proc and so does not throw
  ```
  
  You can tell the [`Proc`](/type/Proc) object to capture output as a filehandle by passing the `:out` and `:err` flags. You may also pass input via the `:in` flag.
  
  ```raku
  my $echo = run 'echo', 'Hello, world', :out;
  my $cat  = run 'cat', '-n', :in($echo.out), :out;
  say $cat.out.get;
  $cat.out.close();
  ```
  
  You may also use [`Proc`](/type/Proc) to capture the PID, send signals to the application, and check the exitcode.
  
  ```raku
  my $crontab = run 'crontab', '-l';
  if $crontab.exitcode == 0 {
      say 'crontab -l ran ok';
  }
  else {
      say 'something went wrong';
  }
  ```
  
  ## [Example with shell](#Inter-process_communication "go to top of document")[§](#Example_with_shell "direct link")
  
  Suppose there is a utility that will takes input from STDIN and outputs to STDOUT, but there isn't yet a Raku wrapper. For this example, lets use [sass](https://sass-lang.com/documentation/cli/dart-sass/), which preprocesses a more convenient form of CSS called SCSS into standard CSS. In a terminal the utility would be used as sass --stdin
  
  We want to convert multiple strings of SCSS into CSS. The code below only converts one string and captures the output into a variable, but it should be obvious how to adapt this into a loop.
  
  ```raku
      #| process with utility, first check it exists in the environment
      my $proc = shell( <<sass --version>>, :out, :merge);
      exit note 'Cannot run sass' unless $proc.out.slurp(:close) ~~ / \d \. \d+ /;
  
      # start loop here for multiple SCSS strings
      # set up the process for stdin.
      $proc = shell( <<sass --stdin --style=compressed>>, :in, :err, :out );
      my $scss = q:to/SCSS/;
          div.rendered-formula {
              display: flex;
              justify-content: space-around;
              align-items: center;
              img.logo {
                  align-self: center;
              }
          }
          SCSS
      # now pipe the SCSS string into the process as STDIN (remembering to close the pipe)
      $proc.in.spurt($scss,:close);
      # extract the output or the error
      my $error  = $_ with $proc.err.slurp(:close);
      my $output = $_ with $proc.out.slurp(:close);
  
      # end loop here
  
  ```
  
  # [The](#Inter-process_communication "go to top of document") [`Proc::Async`](/type/Proc/Async) object[§](#The_Proc::Async_object "direct link")
  
  When you need more control over the communication with and from another process, you will want to make use of [`Proc::Async`](/type/Proc/Async). This class provides support for asynchronous communication with a program, as well as the ability to send signals to that program.
  
  ```raku
  # Get ready to run the program
  my $log = Proc::Async.new('tail', '-f',  '/var/log/system.log');
  $log.stdout.tap(-> $buf { print $buf });
  $log.stderr.tap(-> $buf { $*ERR.print($buf) });
  
  # Start the program
  my $done = $log.start;
  sleep 10;
  
  # Tell the program to stop
  $log.kill('QUIT');
  
  # Wait for the program to finish
  await $done;
  
  ```
  
  The small program above uses the "tail" program to print out the contents of the log named `system.log` for 10 seconds and then tells the program to stop with a QUIT signal.
  
  Whereas [`Proc`](/type/Proc) provides access to output using [`IO::Handle`](/type/IO/Handle)s, [`Proc::Async`](/type/Proc/Async) provides access using asynchronous supplies (see [`Supply`](/type/Supply)).
  
  If you want to run a program and do some work while you wait for the original program to finish, the `start` routine returns a [`Promise`](/type/Promise), which is kept when the program quits.
  
  Use the `write` method to pass data into the program.
  