Rustのstd::process::Commandで引っかかったところ
| 2019/12/26 18:30 | 公開 |
git-authorというgitのサブコマンドを作っているときにstd::process::Commandを使用したのですが、output()の返り値ので引っかかったことがあったのでメモがてら書いていきます。
output()がOkを返してもコマンドの実行に成功したとは限らない
例えばgit config --local user.nameと同じことをしようと思うと
// outputはio::Result<Output>型
let result = std::process::Command::new("git")
.arg("config")
.arg("--local")
.arg("user.name")
.output();
となります。
output()はResult型を返すのでコマンド実行に失敗すればErrが返ってくるのだろうと考えていましが、実行に失敗してもOkが返ってくるパターンがありました。
例えば
// `git hoge`を実行
let result = std::process::Command::new("git").arg("hoge").output();
let output = result.unwrap();
のように存在しないサブコマンドhogeを実行しようとするとコマンドの実行結果は失敗なのにも関わらずoutput()はOkを返します。
ただしoutput.stdoutは空のままでoutput.stderrに文字列が入っています。
また、先程の
// `git config --local user.name`を実行
std::process::Command::new("git")
.arg("config")
.arg("--local")
.arg("user.name")
.output();
も、ローカルのuser.nameが設定されていない時は失敗として扱われますが、output()はOkを返します。
Errを返すとき
ではどのようなときにErrを返すかというと
// `fuga`を実行
let output = std::process::Command::new("fuga").output();
のように存在しないコマンドを実行しようとしたときにErrを返しました。
結論
実行に成功したかどうかを確認したい時はoutput()の返り値がOkかどうかに加えてstatus.success()がtrueかどうかを確認しましょう。
let result = std::process::Command::new("command").output();
if let Ok(output) = result {
if output.status.success() {
// 成功
}
else {
// 失敗
}
}
else {
// 失敗
}