RUST
Controlling processes and using Unix signals
Join Mihalis Tsoukalos as he demonstrates how to use Rust to work and manage child processes, and handle Unix signals.
OUR EXPERT
Mihalis Tsoukalos is a systems engineer and a technical writer. You can find him at @mactsouk.
QUICK TIP
Get the code for this tutorial from the Linux Format archive: www.linuxformat.com/archives?issue=291.
You can learn more about Rust at www.rust-lang.org.
The subject of this tutorial is signal handling and working with processes in Rust. We’ll begin by T showing how to spawn a new process in Rust – the relevant source file is named spawnNew.rs– without doing anything useful with it, just to show you the simplest form of process spawning. So, the logic of spawnNew.rsis found in the following code excerpt: Command::new(“ls”).spawn().expect(“Error in command”);
All of the work is done by the call to Command ::new() and the use of spawn() . As you might recall from the previous Rust tutorials, the expect() part is executed in case of error. As a reminder, you can replace expect() with unwrap(), but in that case you’re not going to be able to print your own error message.
The screenshot (right) shows part of the code of spawnNew.rsthat contains multiple variations of Command::new() that show how to pass arguments to Command::new() and how to set the current directory. You can learn more details about std::process::Command at https://doc.rust-lang.org/std/process/struct.Command.html.
Running spawnNew.rsgenerates the output shown in the screenshot (opposite page). What’s important in the output is the fact that the error message from the last Command::new() call is printed before the Command::new() call with the .arg(“/doesNotExist”) parameter. This means that currently, we can’t be sure about the order of execution. Put simply, our code doesn’t wait for a command to finish before executing the next Command::new() call – this happens due to the use of spawn().
This time we’re going to use output() instead of spawn() when calling Command::new() because output() tells Rust to wait for the child process to finish before continuing. So, the technique is illustrated in the following code from output.rs: let o1 = Command::new(“ls”) .output() .expect(“Error in command”);
Apart from the use of output() in the place of spawn() , we need a variable to keep the output from the Command::new() call. Running output.rsprints the expected output sequentially. However, spawning a process without any control over it isn’t usually enough. We need to be able to check the status of that child process, which is the subject of the next section.
Here’s the Rust code of
spawnNew.rs. There are many ways to invoke Command::new() based on the external command we want to execute.