txt: ## proc.md
  class Proc
  
  Running process (filehandle-based interface)
  
  ```raku
  class Proc {}
  ```
  
  `Proc` is a representation of an invocation of an external process. It provides access to the input, output and error stream as well as the exit code. It is typically created through the `run` subroutine:
  
  ```raku
  my $proc = run 'echo', 'Hallo world', :out;
  my $captured-output = $proc.out.slurp: :close;
  say "Output was $captured-output.raku()";# OUTPUT: «Output was "Hallo world\n"␤»
  
  ```
  
  Piping several commands is easy too. To achieve the equivalent of the pipe `echo "Hello, world" | cat -n` in Raku, and capture the output from the second command, you can do
  
  ```raku
  my $p1 = run 'echo', 'Hello, world', :out;
  my $p2 = run 'cat', '-n', :in($p1.out), :out;
  say $p2.out.get;
  
  ```
  
  You can also feed the `:in` (standard input) pipe directly from your program, by setting it to `True`, which will make the pipe available via `.in` method on the `Proc`:
  
  ```raku
  my $p = run "cat", "-n", :in, :out;
  $p.in.say: "Hello,\nworld!";
  $p.in.close;
  say $p.out.slurp: :close;
  # OUTPUT: «1  Hello,␤
  #          2  world!␤»
  
  ```
  
  In order to capture the standard error, `:err` can be supplied:
  
  ```raku
  my $p = run "ls", "-l", ".", "qqrq", :out, :err;
  my $captured-output = $p.out.slurp: :close;
  my $captured-error  = $p.err.slurp: :close;
  my $exit-code       = $p.exitcode;
  
  ```
  
  In sink context, a `Proc` will call its `sink` method, throwing an exception if the process has exited with an exit code different from zero:
  
  ```raku
  shell 'exit 1'
  # OUTPUT: «(exit code 1) The spawned command 'exit 1' exited unsuccessfully (exit code: 1)␤»
  
  ```
  
  **Note:** Versions of [Rakudo](/language/glossary#Rakudo) older than 2017.04 do not have `.slurp` available on [`IO::Pipe`](/type/IO/Pipe) objects; use [`.slurp-rest`](/routine/slurp-rest) instead.
  
  Use [`Proc::Async`](/type/Proc/Async) for non-blocking operations.
  
  # [Potential Deadlocks](#class_Proc "go to top of document")[§](#Potential_Deadlocks "direct link")
  
  If you run an external program with `:out` and `:err` (so capturing standard output and standard error separately), a deadlock can occur, for example in the following scenario:
  
  * Your Raku script reads from the program's standard output until the End of File (EOF) marker).
  * The external program writes to its standard error stream.
  * The external program runs into the standard error's buffer limit.
  * Your Raku script blocks, waiting for input on the output stream, while the external program blocks until its standard error buffer is being drained.
  
  You can avoid this by using `:merge` to join the external program's standard output and error streams, so that you only need to read from one pipe. This presupposes that you do not need separate access to the two streams. If you do, the only safe approach is to use [`Proc::Async`](/type/Proc/Async).
  
  A similar deadlock can occur when you call an external program with both the `:in` option (to open a pipe to its standard input) and one of the `:out`, `:err` or `:merge` options. In this scenario, it can happen that your Raku script blocks reading from the external program's output while it waits for input, and vice versa.
  
  In this scenario, switching to [`Proc::Async`](/type/Proc/Async) is the most robust solution.
  
  # [Methods](#class_Proc "go to top of document")[§](#Methods "direct link")
  
  ## [routine new](#class_Proc "go to top of document")[§](#routine_new "direct link")
  
  ```raku
  method new(Proc:U:
          :$in = '-',
          :$out = '-',
          :$err = '-',
          Bool :$bin = False,
          Bool :$chomp = True,
          Bool :$merge = False,
          Str:D :$enc = 'UTF-8',
          Str:D :$nl = "\n",
      --> Proc:D)
  
  sub shell(
          $cmd,
          :$in = '-',
          :$out = '-',
          :$err = '-',
          Bool :$bin = False,
          Bool :$chomp = True,
          Bool :$merge = False,
          Str:D :$enc = 'UTF-8',
          Str:D :$nl = "\n",
          :$cwd = $*CWD,
          Hash() :$env = %*ENV
      --> Proc:D)
  
  ```
  
  `new` creates a new `Proc` object, whereas `run` or `shell` create one and spawn it with the command and arguments provided in `@args` or `$cmd`, respectively.
  
  `$in`, `$out` and `$err` are the three standard streams of the to-be-launched program, and default to `"-"` meaning they inherit the stream from the parent process. Setting one (or more) of them to `True` makes the stream available as an [`IO::Pipe`](/type/IO/Pipe) object of the same name, like for example `$proc.out`. You can set them to `False` to discard them. Or you can pass an existing [`IO::Handle`](/type/IO/Handle) object (for example [`IO::Pipe`](/type/IO/Pipe)) in, in which case this handle is used for the stream.
  
  Please bear in mind that the process streams reside in process variables, not in the dynamic variables that make them available to our programs. Thus, modifying [the dynamic filehandle variables (such as `$*OUT`)](/language/variables#Special_filehandles:_STDIN,_STDOUT_and_STDERR) inside the host process will have no effect in the spawned process, unlike `$*CWD` and `$*ENV`, whose changes will be actually reflected in it.
  
  ```raku
  my $p-name = "/tmp/program.raku";
  my $program = Q:to/END/;
      #!/usr/bin/env raku
  
      $*OUT.say( qq/\t$*PROGRAM: This goes to standard output/ );
  END
  
  spurt $p-name, $program;
  
  $*OUT.put: "1. standard output before doing anything weird";
  
  {
      temp $*OUT = open '/tmp/out.txt', :w;
      $*OUT.put: "2. temp redefine standard output before this message";
      shell( "raku $p-name" ).so;
  }
  
  $*OUT.put: "3. everything should be back to normal";
  # OUTPUT
  # 1. standard output before doing anything weird
  #     /tmp/program.raku: This goes to standard output
  # 3. everything should be back to normal
  
  # /tmp/out.txt will contain:
  # 2. temp redefine standard output before this message
  
  ```
  
  This program shows that the program spawned with `shell` is not using the temporary `$*OUT` value defined in the host process (redirected to `/tmp/out.txt`), but the initial `STDOUT` defined in the process.
  
  `$bin` controls whether the streams are handled as binary (i.e. [`Blob`](/type/Blob) object) or text (i.e. [`Str`](/type/Str) objects). If `$bin` is False, `$enc` holds the character encoding to encode strings sent to the input stream and decode binary data from the output and error streams.
  
  With `$chomp` set to `True`, newlines are stripped from the output and err streams when reading with `lines` or `get`. `$nl` controls what your idea of a newline is.
  
  If `$merge` is set to True, the standard output and error stream end up merged in `$proc.out`.
  
  ## [method sink](#class_Proc "go to top of document")[§](#method_sink "direct link")
  
  ```raku
  method sink(--> Nil)
  ```
  
  When sunk, the `Proc` object will throw [`X::Proc::Unsuccessful`](/type/X/Proc/Unsuccessful) if the process it ran exited unsuccessfully.
  
  ```raku
  shell 'ls /qqq';
  # OUTPUT:
  # (exit code 1) ls: cannot access '/qqq': No such file or directory
  # The spawned command 'ls /qqq' exited unsuccessfully (exit code: 2)
  #   in block <unit> at /tmp/3169qXElwq line 1
  #
  
  ```
  
  ## [method spawn](#class_Proc "go to top of document")[§](#method_spawn "direct link")
  
  ```raku
  method spawn(*@args ($, *@), :$cwd = $*CWD, Hash() :$env = %*ENV, :$arg0,
               :$win-verbatim-args = False --> Bool:D)
  ```
  
  Runs the `Proc` object with the given command, argument list, working directory, and environment.
  
  If `:arg0` is set to a value, that value is passed as arg0 to the process instead of the program name.
  
  On Windows the flag `$win-verbatim-args` disables all automatic quoting of process arguments. See [this blog](https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way) for more information on windows command quoting. The flag is ignored on all other platforms. The flag was introduced in Rakudo version 2020.06 and is not present in older releases.
  
  ## [method shell](#class_Proc "go to top of document")[§](#method_shell "direct link")
  
  ```raku
  method shell($cmd, :$cwd = $*CWD, :$env --> Bool:D)
  ```
  
  Runs the `Proc` object with the given command and environment which are passed through to the shell for parsing and execution. See [`shell`](/type/independent-routines#sub_shell) for an explanation of which shells are used by default in the most common operating systems.
  
  ## [method command](#class_Proc "go to top of document")[§](#method_command "direct link")
  
  ```raku
  method command(Proc:D: --> List:D)
  ```
  
  The command method is an accessor to a list containing the arguments that were passed when the Proc object was executed via `spawn` or `shell` or `run`.
  
  ## [method Bool](#class_Proc "go to top of document")[§](#method_Bool "direct link")
  
  ```raku
  multi method Bool(Proc:D:)
  ```
  
  Awaits for the process to finish and returns `True` if both exit code and signal of the process were 0, indicating a successful process termination. Returns `False` otherwise.
  
  ## [method pid](#class_Proc "go to top of document")[§](#method_pid "direct link")
  
  ```raku
  method pid()
  ```
  
  Returns the `PID` value of the process if available, or [`Nil`](/type/Nil).
  
  ## [method exitcode](#class_Proc "go to top of document")[§](#method_exitcode "direct link")
  
  ```raku
  method exitcode(Proc:D: --> Int:D)
  ```
  
  Returns the exit code of the external process, or -1 if it has not exited yet.
  
  ## [method signal](#class_Proc "go to top of document")[§](#method_signal "direct link")
  
  ```raku
  method signal(Proc:D:)
  ```
  
  Returns the signal number with which the external process was killed, or `0` or an undefined value otherwise.
  
  # [Typegraph](# "go to top of document")[§](#typegraphrelations "direct link")
  
  Type relations for `Proc`
  
  
  
  raku-type-graph
  
  
  
  Proc
  Proc
  
  
  Any
  Any
  
  
  Proc->Any
  
  
  
  Mu
  Mu
  
  
  Any->Mu
  
  [Expand chart above](/assets/typegraphs/Proc.svg)
  