🦀

Rust製コマンドで意味付けされた終了ステータスを返す

2024/09/21に公開

はじめに

Rust<sysexits.h>で定義されている終了ステータスを使えるようにするクレートを開発しているので紹介します。

https://github.com/sorairolake/sysexits-rs

<sysexits.h>とは

<sysexits.h>はBSD系に由来する定義付けされた終了ステータスです。
64から78までの終了ステータスの意味が定義されています。

https://github.com/freebsd/freebsd-src/blob/9046ecff409c45205aad34ef8d959d79dd20cf8f/include/sysexits.h#L35-L111

sysexitsクレートについて

sysexits<sysexits.h>で定義されている終了ステータスを使えるようにするクレートです。
Terminationトレイトを実装しているのでmain関数の戻り値として利用できます。

<sysexits.h>では終了ステータスは定数として定義されていますが、sysexitsクレートでは列挙型として定義しています。

https://github.com/sorairolake/sysexits-rs/blob/e215e3d292d2f5721c6c9924ac4d84b041b8f607/src/exit_code.rs#L20-L217

メソッドとしては終了ステータスが成功を表すときにtrueを返すExitCode::is_successメソッド、失敗を表すときにtrueを返すExitCode::is_failureメソッド、指定した終了ステータスでプロセスを終了するExitCode::exitメソッドを実装しています。

is_success.rs
assert_eq!(ExitCode::Ok.is_success(), true);
assert_eq!(ExitCode::Usage.is_success(), false);
is_failure.rs
assert_eq!(ExitCode::Ok.is_failure(), false);
assert_eq!(ExitCode::Usage.is_failure(), true);
exit.rs
fn main() {
    ExitCode::Ok.exit();
}

また、Fromによる終了ステータスのプリミティブ整数型への変換、io::Errorなどからの終了ステータスへの変換を実装しています。

使い方

前述の通り、sysexitsクレートはTerminationトレイトを実装しているのでmain関数の戻り値として利用できます。

main.rs
use std::str;

use sysexits::ExitCode;

fn main() -> ExitCode {
    let bytes = [0xf0, 0x9f, 0x92, 0x96];
    match str::from_utf8(&bytes) {
        Ok(string) => {
            println!("{string}");
            ExitCode::Ok
        }
        Err(err) => {
            eprintln!("{err}");
            ExitCode::DataErr
        }
    }
}

<sysexits.h>で定義されていない終了ステータスも返したいときは、sysexits::ExitCodestd::process::ExitCodeに変換します。

https://github.com/sorairolake/sysexits-rs/blob/e215e3d292d2f5721c6c9924ac4d84b041b8f607/examples/cat.rs#L16-L59

終わりに

Rustで<sysexits.h>で定義されている終了ステータスを使えるようにするsysexitsクレートを紹介しました。

詳しい使い方については以下を参照して下さい。

https://docs.rs/sysexits

GitHubで編集を提案

Discussion