テスト時にstatusコードが0以外になってしまう場合の対処方法
ファイルシステムがRead-Only になってしまうとログの書き込みすらできないから大変な事になるので検出しようと思ってNet::SSHでスクリプト書いたらstatusエラーに遭遇したが、テストを成功させるにはこうすればいいよ、という事を学んだ件です
結論から言うとこうするです
my $status = `echo $?`;
※Linuxの場合でしか確認してないです
そもそも何がしたかったのか
運用しているWEBサーバーなどがリクエストを受け付けてそれをジョブキューに投げたら、実はファイルシステムがHDD障害によってReadonlyになっていてみんな無言で死んでたらいやだよね、という対策をしたかった
で、これを真似をした。
http://github.com/tokuhirom/madeye/blob/master/lib/App/MadEye/Plugin/Agent/WriteDisk.pm
スクリプト
とりあえずこんなディレクトリつくります。
mkdir eg tmp
eg/try_write.plというファイルをつくります。中身は次のとおり
package Hoge; use strict; use warnings; use Net::SSH (); use Try::Tiny; sub try_write { my ($class, $hostname, $dir)=@_; my $file = 'hogefuga.piyo'; my $cmd = << "END_OF"; if [ -d $dir ]; then /bin/touch $dir/$file /bin/rm $dir/$file fi END_OF my @errors = (); try { Net::SSH::ssh_cmd( $hostname, $cmd ) } catch { @errors = split "\n", $_; }; return scalar @errors ? [@errors] : undef; } package main; use strict; use warnings; use Test::More; use FindBin qw/$Bin/; use Path::Class (); my $tmp_dir = Path::Class::Dir->new( $Bin, '..', 'tmp' ); subtest 'touch ok' => sub { my $errors = Hoge->try_write( 'localhost', $tmp_dir ); ok ! $errors; =pod my $status = `echo $?`; chomp($status); is $status, 0; =cut done_testing(); }; subtest 'touch not ok' => sub { chmod 0666, $tmp_dir->stringify or die $@; my $errors = Hoge->try_write( 'localhost', $tmp_dir ); ok scalar @{$errors}; diag(join "\n", @{$errors}); =pod my $status = `echo $?`; chomp($status); is $status, 256; =cut chmod 0755, $tmp_dir->stringify or die $@; done_testing(); }; done_testing();
この状態だとtestが失敗します。exit(0)じゃないからです。
:!prove -vl eg/try_write.pl eg/try_write.pl .. ok 1 1..1 ok 1 - touch ok ok 1 # /bin/touch: cannot touch `/home/okamura/eg/../tmp/hogefuga.piyo': 許可がありません # /bin/rm: cannot remove `/home/okamura/eg/../tmp/hogefuga.piyo': 許可がありません 1..1 # Looks like your test exited with 256 just after 1. not ok 2 - touch not ok # Failed test 'touch not ok' # at eg/try_write.pl line 66. 1..2 # Looks like you failed 1 test of 2. Dubious, test returned 1 (wstat 256, 0x100) Failed 1/2 subtests Test Summary Report ------------------- eg/try_write.pl (Wstat: 256 Tests: 2 Failed: 1) Failed test: 2 Non-zero exit status: 1 Files=1, Tests=2, 0 wallclock secs ( 0.02 usr 0.00 sys + 0.04 cusr 0.02 csys = 0.08 CPU) Result: FAIL
podをはずすとうまくいく
:!prove -vl eg/try_write.pl eg/try_write.pl .. ok 1 ok 2 1..2 ok 1 - touch ok ok 1 # /bin/touch: cannot touch `/home/okamura/eg/../tmp/hogefuga.piyo': 許可がありません # /bin/rm: cannot remove `/home/okamura/eg/../tmp/hogefuga.piyo': 許可がありません ok 2 1..2 ok 2 - touch not ok 1..2 ok All tests successful. Files=1, Tests=2, 0 wallclock secs ( 0.01 usr 0.00 sys + 0.04 cusr 0.02 csys = 0.07 CPU) Result: PASS
YES!!
ということで
あとはエラーがあったらMail送信をしたりするとたぶんうまくいくと思います。たぶんね。
ところで参考にしたmadeyeのlib/App/MadEye/Plugin/Agent/WriteDisk.pmで、ssh_cmdでtouchに失敗したときに例外をキャッチしてないようなのですが、問い合わせに失敗したらdeamonizeされたプロセスが途中で戦死してる気が、、、