How do I fork/exec a process which forwards all arguments in Rust?

Viewed 1483

I want to write the following in Rust. I cannot figure out how to do this with Command API.

if [[ -z "${DEPLOY_ENV}" ]]; then
  $old_program "$@"
else
  $new_program "$@"
fi
2 Answers

The Command API is cross-platform and not all platforms have a concept of exec and fork. However, the standard library does provide the exec() method for Commands on Unix platforms via the std::os::unix::process::CommandExt extension trait.

use std::process::Command;
use std::os::unix::process::CommandExt;

fn main() {
    let args: Vec<_> = std::env::args_os().skip(1).collect();
    let err = Command::new("new_program")
        .args(&args)
        .exec();
    println!("Error: {}", err);
}

Alternatively, you can use the fork crate:

use fork::{fork, Fork};

fn main() {
    // keeps the same arguments of course
    match fork() {
       Ok(Fork::Parent(child)) => println!("Continuing execution in parent process, new child has pid: {}", child),
       Ok(Fork::Child) => println!("I'm a new child process"),
       Err(_) => println!("Fork failed"),
    }
}

or the exec crate:

use exec::Command;

fn main() {
    let args: Vec<_> = std::env::args_os().skip(1).collect();
    let err = Command::new("new_program")
        .args(&args)
        .exec();
    println!("Error: {}", err);
}

Or if you're feeling up to it, call them more directly with the nix or libc crates.

You can get the process' arguments via std::env::args_os and pass them to a child process via std::process::Command::args.

For example:

use std::process::Command;
use std::env::args_os;

fn main() {
    Command::new("cmd")
        .args(args_os())
        .output()
        .expect("cmd exited with error code");
}
Related