2015年04月03日

元ネタ: 「tail -f」を使うのは情弱、情強は「less +F」を使う

だいたいウェッブザービスなのでログファイルなんかは symlink かログのローテートを行っているはずなので、

$ tail -f access_log

ではなく

$ tail -F access_log

とすれば、symlink の先が変わったりローテートた場合 (rename など) にも追随してくれて便利ですね。

ちなみに、最近 logtop というのを知ったのだが便利そうなのでそのうち試したいですね。

あと、情弱なので less +F 試してみたいと思いました。



xaicron at 01:37コメント(19) このエントリーをはてなブックマークに追加

2015年01月10日

すでに昨年の話ですが、2014年10月24日に開催された perlcasual#06 で何故か基調講演しました。

http://xaicron.github.io/slide/perlcasual-06/

最近は勉強会的なものにめっきりいかなくなっていましたが、久々に参加して楽しかったです。
perlcasual といいつつ、主催者自体が perl 全然関係な話をしていたりしましたが、気軽に参加できる勉強会があるのはなかなかよいですね。

2014年は3月あたりからハッカドールというアプリをちまちま作っており、おかげさまで AppStore の2014年ベストアプリに選ばれたりしました。たぶん AppStore の中の人が重度のオタクなのだと思います。

今年も何かしら楽しんでもらえるようなことをやっていきたいような気がしなくもないですね。



xaicron at 16:22コメント(10)Perl このエントリーをはてなブックマークに追加

2014年07月10日

タイトルですべてを語っていますし、http://blog.livedoor.jp/sonots/archives/32645828.html あたりを読むと良いのですがメモ。

最初にまとめると

  • CORE::print() を使う場合は 4096 or 8192 byte 以下に収めること
  • CORE::syswrite() なら混ざらない
  • 男は度胸。flock(2)する

ということです。
これでわかった人は読む必要ありません。

以下蛇足。

はじめに

perl ではファイルハンドルに書き込むときには何も考えずに CORE::print() を利用しますが、この人はなんかいい感じにバッファリングしたり、長い文字列だったらぶった切ってくれたりしてくれます。

で、普通はバッファリングのことはみんな意識しているので以下のようにヒットアンドアウェイをやったりしますね。close() で自動的に flush されるので、まぁだいたい autoflush(1) しているのと同じでしょうという発想です。

open my $fh, '>>', $file;
print $fh $message, "\n";
close $fh;

大抵のケースでは嬉しい事にこれでログが混ざらずに綺麗に見れます。
しかし、超絶に長いメッセージを書き込もうとした場合にこれだと混ざる可能性があります。

分割されてしまうサイズを調べる

超絶長いのがいくつかというとこれまた環境によって異なるのですが、以下のようにするとさくっとわかります。

$ cat > foo.pl
my $s = 'a' x (1024 * 100);
open my $fh, '>>', "/tmp/$$";
print $fh $s;
close $fh;
^D
$ strace perl foo.pl 2>&1 | grep write
write(3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 8192) = 8192
write(3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 8192) = 8192
write(3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 8192) = 8192
write(3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 8192) = 8192
write(3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 8192) = 8192
write(3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 8192) = 8192
write(3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 8192) = 8192
...

とかなって、write(2) が複数回呼ばれていることがわかりますね。
そして、どうやら 8192byte で切られている模様です。*1

こうなると、普通にマルチプロセスで書き込んでいた場合は context switch が発生してログが混ざること請け合いですね。

具体的には以下のようにすると簡単に確認できます。

$ cat > bar.pl
my $char = shift || 'X';
my $str = $char x (1024 * 10); # 8096 byte 以上書き込む

for (1..1000) {
    open my $fh, '>>', '/tmp/test';
    print $fh $str, "\n";
    close $fh;
}
^D
$ perl bar.pl A &; perl bar.pl B &
$ grep A /tmp/test | grep B | wc -l
13

13行ぐらい混ざっちゃったっぽい!

syswrite を使う

print() では混ざっちゃうことが確認できたので、syswirte を使いましょう。

$ cat > hoge.pl
my $s = 'a' x (1024 * 100);
open my $fh, '>>', "/tmp/$$";
syswrite $fh, $s;
close $fh;
^D
$ strace perl hoge.pl 2>&1 | grep write
write(3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 102400) = 102400

こうすると、write(2) 一回だけになっていることがわかります。
上記の記事にあるように write(2) 一発は atomic であることがある程度保証されているので、基本的にはこれだけでおっけーでしょう。

ファイルシステムのことを気にしたくないひと

flock(2) しましょう。

まとめ

でかいログを吐かない。

  • *1 : ちなみに 4096 の環境もありました。 PERLIOBUF_DEFAULT_BUFSIZ だと思ったけど違うのかな?


xaicron at 02:40コメント(28)Perl このエントリーをはてなブックマークに追加

2014年04月01日

Web::Query 0.26 より、prev()next() というメソッドが追加されました。
なにかというと、previousSibling と nextSibling のことであります。つまり同一階層の前後の node が簡単に取れるやつですね。

use feature 'say';
use Web::Query;

my $html = << 'HTML';
<div id="container">
  <p class="a1">foo</p>
  <p class="a2">bar</p>
</div>
HTML

say wq($html)->find('.a1')->next->as_html; # <p class="a2">bar</p>

って感じ。



xaicron at 01:31コメント(19)Perl このエントリーをはてなブックマークに追加

2014年01月25日

tag だけ打って CPAN には上げたくないなーってときは

$ FAKE_RELEASE=1 minil release

としますが、仕事のプロダクトとかで絶対に CPAN にあげないようなものの場合は毎回指定するの面倒な上にミスったら死ぬのでなんとかしたいことでしょう。

でも v0.9.0 からは release.do_not_upload_to_cpan という設定が追加されたので、minil.toml に

[release]
do_not_upload_to_cpan= true

とか書いておけばハッピーですね。



xaicron at 01:41コメント(21)Perl このエントリーをはてなブックマークに追加

2014年01月08日

JSON::XS 3.0 から JSON::XS::true|false が JSON::XS::Boolean クラスから JSON::PP::Boolean に変わってたので、Data:Util::is_instance() とかで JSON::XS::Boolean かどうかで分岐していた部分が動かなくなっていて諦めて

if (is_instance $bool, 'JSON::XS::Boolean' or is_instance $bool, 'JSON::PP::Boolean') {
    ...
} 

とかにした。(モジュールのバージョンが環境によって 3.0 だったりその前だったりすることがあるため)

が、JSON::PP::Boolean は Types::Serializer::Boolean の alias であるため

if ($bool && Types::Serialiser::is_bool $bool) {
    ...
}

とかするのがよいのであろうこと請け合い。



xaicron at 20:21コメント(32)Perl このエントリーをはてなブックマークに追加

2013年07月18日

Perl徹底攻略 (WEB+DB PRESS plus) [大型本]

大沢 和宏 cho45(さとう) 小林 篤 和田 裕介 嶋田 裕二(xaicron) 牧 大輔(lestrrat) 奥 一穂 広木 大地 伊藤 直也 長野 雅広 藤原 俊一郎 伊藤 智章 まかまか般若波羅蜜 小飼 弾 近藤 嘉雪 中川 勝樹 宮川 達彦 tokuhirom 藤 吾郎(gfx) 村瀬 大輔
技術評論社


最近の Perl 事情はもとより、第一線で働いている人たちが書いているので、内容は超実用的です。
Perl を書いてる人や、昔書いてた人、さらにはこれからやろっかな〜って人にはおすすめの一冊です。

なにげに描き下ろしもかなり豪華です。



xaicron at 15:20コメント(131)Perl このエントリーをはてなブックマークに追加
プロフィール

Perlが少しだけ出来る気になってます。
JavaScriptはよくわかりません。
Rubyもちんぷんかんぷんです。
Pythonは難しいです。
ActionScript勘弁してください。
Javaあばばばばば。
低級言語できません。

github
記事検索
  • ライブドアブログ