新しいblogに移行しました

新ブログ "All Yout Bugs Are Belong To Ass" に移行しました!

ラベル バッドノウハウ の投稿を表示しています。 すべての投稿を表示
ラベル バッドノウハウ の投稿を表示しています。 すべての投稿を表示

2012-12-27

[Perl]Email::SendつかったらReturn::Valueにdeprecatedだと怒られた

Email::Send自体がdeprecatedなのですが、Email::SenderはMoose依存だそうなので(Mouseに切り替えるという話は無理だったらしい?)、Email::Send使ってメールを送ることにしました。
ですが、こいつはReturn::Valueというモジュールを内部的に使用していて、これを普通に使おうとすると

Return::Value is deprecated

と言われました。でもEmail::Senderは使いたくないので、

BEGIN {
    $Return::Value::NO_CLUCK = 1;
}
use Email::Send;

としたのでした。だいぶアレ。

[2012/12/28 追記]
なあんてことを某所でぼやぼや言ってたんだけど、寝て起きてたらMail::Krohnというものがつくられていた。激速。本当にすごい。

 http://blog.64p.org/entry/2012/12/28/002634

[2013/07/31 追記]
サンプルに間違いがあったので直しました。

誤: BEGIN { Return::Value::NO_CLUCK = 1; ...
正: BEGIN { $Return::Value::NO_CLUCK = 1; ...

nekoyaさん、ご指摘感謝致します。

それからEmail::SenderはMoose依存ではなくなり、Moo依存になりました。
それに伴い、Email::Krohnは必要なくなったとされ、deleteされました。

2012-12-19

コマンドラインからTwitterにPOST(もしくは自分にD)するだけのツールをつくってみた

VPSで定期的にcronとかでバッチぶん回したりして、その結果をある程度すぐにみれる状況にしたいなーとおもったので、App-Shirohというツールをつくりました。ようするに、ものすごい単純なTwitterクライアントなんですけど。

https://github.com/ytnobody/App-Shiroh

前準備
手始めに、通知を送信するためのTwitterアカウントが必要なので、どうにかこうにか取得しましょう。
次に、通知を受け取る側のアカウントと、今しがた作ったアカウントを相互フォローさせましょう(D送るのに必要)。
そして、さっき作ったTwitterアカウントをつかって、このあたりを参考に、認証に必要な各種情報を揃えます。
ここまでで準備はオッケー。

インストール&設定
まず、App::Shirohをインストールします。cpanmをつかいますので、あらかじめ用意しておきましょう。

git clone git://github.com/ytnobody/App-Shiroh.git
cd App-Shiroh
cpanm ./

インストールできたら、今度は以下のような内容で~/.shirohというファイルを新規作成します。(適宜置き換える)

  {
     consumar_key        => 'YOUR CONSUMER KEY',
     consumer_secret     => 'YOUR CONSUMER SECRET',
     access_token        => 'YOUR ACCESS TOKEN',
     access_token_secret => 'YOUR ACCESS TOKEN SECRET',
     message_to          => 'some_nickname', ### 無くてもOK。このアカウントにDを送る。
  };

ここまでできたら、あとは

shiroh '通知です'

とか

cat /path/to/file | shiroh

とかすれば、新しく作ったアカウントが(つぶやいて|Dして)くれます。 パイプ経由で複数行のデータを食わせた場合、その行数分だけつぶやきます。
あと今のところ、文字数が140文字越えたときにどうするかとか全然考慮せずにNet::Twitter::Liteに丸投げしてます。
大事なこととしては、ばれるorもれるとやばいものとかには向きません。

2011-01-27

[Perl]evalの中で起こったエラーを検出する

この前、実稼働中のかなり古いコードの不具合対応ということで、そのコードをチェックしていたのですが、その中で
my $dbh = DBI->connect(...);
eval {  
    my $sth = $dbh->prepare(...);
    $sth->execute;
    $sth->finish;
};
みたいな箇所(上のコードは実物じゃないですよ)があったんですね。で、evalで被ってやるのはまあ100歩譲って「仕方ないなあ」で済ませましたけど、よりによって、$@に入ってきた値をキャッチするロジックがなかったんです。
当然エラーとかが起こってもエラーログすら吐かず、何食わぬ顔で突っ走ってしまう。そんなわけで、SQL周りの不具合を見つけるのに数時間を要してしまったわけです。

その場ですぐに修正パッチを作成・適用して事なきを得ましたが、僕は心の奥底で思いました。「evalの中でエラーが起こったら、無理やりにでもエラーログにその内容を吐かせたい!」と。

で、調べてみたら、$SIG{__DIE__}にコードリファレンスを食わせることで、その願いは叶えられるとのことでした。
これを使って、ついでにエラー発生時刻も併せて吐いてやれば、後の不具合調査時に役立つでしょう。

というわけで、試しにコードを書いてみました。
use warnings;
use strict;
use Time::Zone;
use DateTime;
use DBI;

$SIG{__DIE__} = sub {
    my $now = DateTime->from_epoch( epoch => time() + tz_local_offset() )->strftime( '%Y/%m/%d %H:%M:%S' );
    warn join( " - ", $now, "CRITICAL", shift );
};

### DBD::sqrightなんてないので、このコードはエラーとなる。
eval {
    my $dbh = DBI->connect( 'dbi:sqright:hoge.txt' );
};

END {
    print "FINISHED!!!\n";
}

この動作結果は、以下の様になります。
2011/01/27 15:19:20 - CRITICAL - Can't locate DBD/sqright.pm in @INC (@INC contains: /home/yt/perl5/perlbrew/perls/perl-5.12.2/lib/site_perl/5.12.2/x86_64-linux /home/yt/perl5/perlbrew/perls/perl-5.12.2/lib/site_perl/5.12.2 /home/yt/perl5/perlbrew/perls/perl-5.12.2/lib/5.12.2/x86_64-linux /home/yt/perl5/perlbrew/perls/perl-5.12.2/lib/5.12.2 .) at (eval 901) line 3.
2011/01/27 15:19:20 - CRITICAL - install_driver(sqright) failed: Can't locate DBD/sqright.pm in @INC (@INC contains: /home/yt/perl5/perlbrew/perls/perl-5.12.2/lib/site_perl/5.12.2/x86_64-linux /home/yt/perl5/perlbrew/perls/perl-5.12.2/lib/site_perl/5.12.2 /home/yt/perl5/perlbrew/perls/perl-5.12.2/lib/5.12.2/x86_64-linux /home/yt/perl5/perlbrew/perls/perl-5.12.2/lib/5.12.2 .) at (eval 901) line 3.
Perhaps the DBD::sqright perl module hasn't been fully installed,
or perhaps the capitalisation of 'sqright' isn't right.
Available drivers: DBM, ExampleP, File, Gofer, Proxy, SQLite, Sponge.
 at /home/yt/perl/warn.pl line 13

ちなみにこちらの記事によれば、これだけでは処理が不十分のようで、$^Sを使ってeval経由の呼び出しか否か(=本当にdieする時)で処理を分けた方が良い様です。

2010-06-28

[Perl]Catalystアプリ配下のロジックを叩きたい

逃げ口上


この記事は、所謂「モダンperl」とは全くもって相反するものと思われます。しかしながら、ユースケースとして記録しておくこと自体に意義の有ることと判断し、ここに掲載する次第です。
この手法を使わざるを得ない時は、設計がぐちゃぐちゃな状態であるか、単に「モダンな」設計ではないものと思われます。今一度、よく設計を見直すことを考慮すべきでしょう。


…この記事があるということは、現に僕自身がぐちゃぐちゃな設計で作ったcatalystアプリケーションを世に出してしまい、そのためにこんな妙な解決策 - バッドノウハウ - を使う必要に迫られたのだということです。これについては、過去の自分を叱咤するとともに、現在の自分の糧とすべしと肝に命じております。
無論、この方法自体はバッドノウハウとはいえ、より研ぎ澄ませば、まさに「モダンな」ノウハウとなり得るものかもしれませんが、僕自身にはそのようなユースケースは思いつきませんでした。

バッドノウハウ?上等!

さて、逃げ口上はこの辺にしときます。色々とキリがないので^^;

このノウハウ自体は、えらくあっさりとしたものです。
例えば、バッチスクリプト./script/batch.plで、アプリケーションMyApp配下のパス/ugly/batch_targetを、引数付きで定期的に叩きたい場合。
./script/batch.plは以下のようになります。
use warnings;
use strict;
use MyApp;
use Catalyst::Stats;
my $app = MyApp->new( stats => Catayst::Stats->new );
my $res = $app->forward( '/ugly/batch_target', [ time() ] );
print $res;

これだけです。あとはこのスクリプトをcronに食わせるなりするだけで、定期的に/ugly/batch_targetをぶっ叩いてくれます。
ちなみに、今回は引数をtime()としました。あくまでサンプルなので。
ポイントは、Catalyst::StatsオブジェクトをMyApp->statsに食わせる所です。

なぜ僕はこの方法を「モダン」じゃないと主張するのか

さっきから勿体ぶった書き方をしてきましたが、そもそもこの方法が「モダン」ではないと僕が主張するのは、

ロジックとコントローラの分離が為されていない故のノウハウである

という、香箱を組む猫すら青ざめる(?)、えらく間接的な理由からです。
コントローラ配下のロジックを叩くということはつまり、「コントローラ」配下に「ロジック」が実装されていることに他ならない。これはこのあたりのスライドにもあるように、コントローラをぐちゃぐちゃにする最短ルートといえます。