Ruby の子プロセスの終了ステータスの取得方法

備忘録。

Ruby での子プロセスの終了ステータスの取得方法について、定期的に自分でやらかしたり他の人がやらかしているのを目撃するので書き残す。

Kernel#.system、バッククォート文字列、もしくは open3 系のメソッドなどで作った子プロセスは $? で取れる。実態は Process::Statusインスタンスだが、終了ステータスを $?.to_i として取ってはいけない

ドキュメントにある通り、Process::Status#to_i の返す値は実装依存。終了ステータスを取るなら exitstatus、終了させたシグナルを取るなら termsig を使うべきである。

例えば何かしらのプロセスの結果をログに出す時に

system(cmd)
log("exit status #{$?.to_i}")

とすると、いざという時に使いものにならず、頭を抱えることになる。こちらの方がいい。

system(cmd)
log("exit status #{$?.exitstatus.inspect}, signal #{$?.termsig.inspect}") # nil を明示するために inspect