ncでディレクトリを転送する

scpでは暗号化なしでもCPUがボトルネックになってしまうため、tarとnc(netcat)を組み合わせてディレクトリを高速に転送する。

※ncは転送の途中でコネクションが閉じられてもエラーを返さないので注意

# 転送先
nc -l -p PORT | tar xf -
# 転送元
tar cfO - DIR | nc HOST PORT

ネットワーク帯域をほぼ1Gbps使い切っても、CPU使用率は転送先、転送元ともにncとtar合わせて10%以下で済んだ。

sshのWarning: Permanently added ...を表示させない方法

SSHでホスト鍵が変わっていても無視する方法 - atsumu-t2の日記を使っていると、シェルスクリプトから複数回sshを実行するとき、毎回Warningが表示されて出力が読みにくくなる。それを防ぐ方法。

ssh host "echo hoge" 2> >(grep -v '^Warning: Permanently added .* to the list of known hosts\.' 1>&2)

標準エラー出力からgrepでWarningの行だけ省き、その出力を標準エラー出力に書き戻している。

Warningの行以外は標準出力にそのまま表示されるので、エラーを見逃すこともない。

MongoDBでObjectId(プライマリキー)だけを使って時刻指定検索する

MongoIdの上位4バイトにはドキュメント挿入時刻がunix timeで格納されているので、例えばPHPの場合このようにして時間を範囲指定できる。

$condition["_id"] =  = array(
    '$gte' => new MongoId(sprintf("%08x%016x", time() - 60, 0)),
    '$lt'  => new MongoId(sprintf("%08x%016x", time(), 0)),
)

インデックスを追加せずに済むので容量や性能的にうれしい。

PHPのfread関数は、第2引数で指定した分だけメモリを消費する

PHPのfread関数は、第2引数で指定した大きさのバッファを確保してそのまま返すらしい。

実際に読み込んだバイト数が小さかったとしても、返された値をそのまま配列に入れてると、すぐにメモリが足りなくなる。

$ echo hoge | php -r '
    $a = memory_get_usage();
    $b = fread(STDIN, 1024 * 1024);
    $c = memory_get_usage();
    printf("%s\n", number_format($c - $a));'
1,057,288
$ echo hoge | php -r '
    $a = memory_get_usage();
    $b = fread(STDIN, 2048 * 2048);
    $c = memory_get_usage();
    printf("%s\n", number_format($c - $a));'
4,203,016

これならfreadで使用したバッファがすぐに開放される。

$ echo hoge | php -r '
    $a = memory_get_usage();
    $b = "".fread(STDIN, 2048 * 2048);
    $c = memory_get_usage();
    printf("%s\n", number_format($c - $a));'
8,712

利用したPHPのバージョン

$ php --version
PHP 5.3.10-1ubuntu3.1 with Suhosin-Patch (cli) (built: May  4 2012 02:20:36)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies

sshfsをfstabでマウントする

こんな感じにマウントできるって教えてもらいました。

sshfs#root@10.232.139.234:/mnt/files /var/www/remote_files fuse allow_other,IdentityFile=/path/to/my_ssh_keyfile,ServerAliveInterval=60 0 0

( http://www.saltycrane.com/blog/2010/04/notes-sshfs-ubuntu/ より )

システムにlibaioをインストールせずにMySQL::Sandboxでmysql5.5を使う

先にlibaioを置いておく。(debian)

mkdir libaio-dev
cd libaio-dev
apt-get source libaio-dev
tar zxf libaio_0.3.107.orig.tar.gz
gzip -d libaio_0.3.107-7.diff.gz
cd libaio-0.3.107
patch -p1 < ../libaio_0.3.107-7.diff
make prefix=$HOME/opt/libaio-0.3.107 install

make_sandboxする

export LD_LIBRARY_PATH="$HOME/opt/libaio-0.3.107/lib:$LD_LIBRARY_PATH"
make_sandbox mysql-5.5.28-linux2.6-x86_64.tar.gz

追記: LD_LIBRARY_PATHが間違ってたので修正