Programs running other programs and communicating with them
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:
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.
shell 'ls -lR | gzip -9 > ls-lR.gz';
Caution should be taken when using shell
with user input.
Proc
objectBoth run
and shell
return a 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.
my = run 'git', 'log', '--oneline', :out;for .out.lines ->.out.close();
If the program fails (exits with a non-zero exit code), it will throw an exception when the returned Proc object is sunk. You can save it into a variable, even anonymous one, to prevent the sinking:
$ = run '/bin/false'; # does not sink the Proc and so does not throw
You can tell the Proc
object to capture output as a filehandle by passing the :out
and :err
flags. You may also pass input via the :in
flag.
my = run 'echo', 'Hello, world', :out;my = run 'cat', '-n', :in(.out), :out;say .out.get;.out.close();
You may also use Proc
to capture the PID, send signals to the application, and check the exitcode.
my = run 'crontab', '-l';if .exitcode == 0else
Proc::Async
objectWhen you need more control over the communication with and from another process, you will want to make use of Proc::Async. This class provides support for asynchronous communication with a program, as well as the ability to send signals to that program.
# Get ready to run the programmy = Proc::Async.new('tail', '-f', '/var/log/system.log');.stdout.tap(-> );.stderr.tap(-> );# Start the programmy = .start;sleep 10;# Tell the program to stop.kill('QUIT');# Wait for the program to finishawait ;
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
provides access to output using IO::Handle
s, Proc::Async
provides access using asynchronous supplies (see 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, which is kept when the program quits.
Use the write
method to pass data into the program.