💎
Perl: eval 中の die と exit の挙動
要約
eval の中では die を基本的に使う。
exit だと eval でエラーをトラップ出来ない。
概要
Perl の (eval 中の) die, exit の挙動について確認したので書き残しておく。
きっかけは、以下のようなコマンドロガーがあり、一部のコマンドのログが吐き出されていないことがあったため。
# こんなかんじのコマンドロガーみたいなの
eval { $result = command(); }; # コマンド実行
if ( $result ) {
print("result is $result\n"); # 成功していたら結果表示
} else {
print("some error is occured: $@\n")
# slack 通知とか
}
挙動を確認
die の場合
以下のような die するサブルーチンを用意して、eval の中で呼び出してやる。
sub command_die {
print("command with die\n");
die("failed command_die");
}
print("start\n");
eval { $result = command_die(); };
if ( $result ) {
print("result is $result");
} else {
print("some error is occured");
print("error log: $@");
}
print("end\n");
結果は以下。eval でエラーをトラップして処理できている 👍
start
command with die
some error is occurederror log: failed command1 at main.pl line 8.
end
exit の場合
次は exit するサブルーチンを用意して呼び出してみる。
sub command_exit {
print("command with exit\n");
exit;
}
print("start\n");
eval { $result = command_exit(); };
if ( $result ) {
print("result is $result");
} else {
print("some error is occured");
print("error log: $@");
}
print("end\n");
結果は以下。eval 以降の log が出ていないので、exit 以降が実行されていない 😭
start
command with exit
まとめ
エラーをトラップしたいサブルーチン中では die を使う。
eval の中で die を使うとエラーをトラップできるのに対して、exit だとその時点でプログラムが終了してしまう。
perldoc にも以下のように明記してあった 💦
Don't use exit to abort a subroutine if there's any chance that someone might want to trap whatever error happened. Use die instead, which can be trapped by an eval.
でもきっかけのケースだと、ログの処理部分が違うファイルに切り出してあったので、ちゃんと意識しないと書いている部分が eval 中で実行されるのを忘れちゃうようなと思ったり...
Discussion