When you're writing command-line tools, you need to be a good citizen and return an error code to the shell that has invoked your program. This way shell scripts can determine if they can continue execution or if they should abort and report an error.
The main()
function in a Rust program doesn't return a value to the shell, but you can set the
exit code with std::process::exit
, as detailed in the
documentation.
Here is a small example that builds on the example found in the documentation. It returns an exit code of 0 if all is well, and 1 if there were no command line arguments supplied.
use std::env;
fn run_app(args: &[String]) -> Result<(), &'static str> {
if args.len() < 1 {
Err("missing command line argument")
}
else {
println!("{}", args[0]);
Ok(())
}
}
fn main() {
let args: Vec<String> = env::args().collect();
std::process::exit(match run_app(&args[1..]) {
Ok(_) => 0,
Err(err) => {
eprintln!("error: {:?}", err);
1
}
});
}
The main
function passed all the command line arguments except the first
(which is the name of the program) to the run_app
function. That function
returns a Result
with an empty type of all is well, or a static string with an
error message in case of error.
The exit code set by std::process::exit
is determined from the result returned by
the run_app
function using a match
expression.
If the program is invoked with no command line arguments, an error message is printed in the shell, and the error code is 1:
% cargo run --quiet error: "missing command line argument" % echo $? 1
But if you run the program with a command line argument, it will echo back the argument you gave and set the return code to zero:
% cargo run --quiet -- hello hello % echo $? 0
Note that if you give command line arguments to Cargo when you run your program,
you need to separate the arguments intended for your own program with --
.
Hope you find this useful in your command line tool projects.