Home

技術系のメモと日々の雑感

そろそろ xz を使ってみる

ちょっと前に話題になっていた XZ Utils。
当時は本家のサイトにもソースが見当たらなかった。
アクセスが集中したのでダウンロードできなくしてたのかな。
まぁ、それはともかく、この前ふとそれを思い出してサイトを覗いてみたら、ちゃんとソースが置いてあった。
ということで、すでに話題に乗り遅れた感があるけど、個人的に興味があったので試してみよう。

# tar zxvf xz-4.999.9beta.tar.gz
# cd xz-4.999.9beta
# ./configure --prefix=/usr/local
# make
# cp src/xz/xz /usr/local/bin

今回はお試しなので、make install せずに xz だけコピーしておいた。
さて、gzip と比較するのには何のファイルがいいかな。
あ、手っ取り早く xz のソースを利用してみるか。

$ ls -l
合計 1020
-rw-r--r-- 1 root root 1037541  9月 27 07:56 xz-4.999.9beta.tar.gz

gzip で圧縮したサイズは 1MB ぐらい。
一旦 tar に戻して xz で圧縮してみると

$ gunzip xz-4.999.9beta.tar.gz
$ xz -9 xz-4.999.9beta.tar
xz: Adjusted LZMA2 dictionary size from 64 MiB to 8 MiB to not exceed the memory usage limit of 99 MiB
$ ls -l
合計 720
-rw-r--r-- 1 root root 729480  9月 27 07:56 xz-4.999.9beta.tar.xz

おぉ〜!
30% ぐらい小さくなってる。
なるほど。
これは話題になるのも納得。
他のバイナリファイルとかテキストファイルでも試してみたところ、gzip と比べて 20%〜30% ぐらいサイズが小さくなった。
速度は gzip と比べると遅いけど、この圧縮率は魅力だな〜。
ところで、圧縮するときに何やらメッセージが出てるね。
「メモリ使用量が 99 MB を上回らないように、LZMA2 の辞書サイズを 64MB から 8MB に調整した」ってところかな。
そういえば、試したマシンが積んでるメモリは、たったの 256MB。
こんな貧弱なマシンで使っても負荷がかからないようになってるのはありがたい。

Postfix の deferred のメッセージ数を MRTG でグラフ化

Postfix の deferred キューに溜まっているメッセージ数を MRTG でグラフ化することにした。
リファレンス
によると Target に指定する値は 4 つで、グラフ 1 の値、グラフ 2 の値、監視対象の稼動時間、監視対象の名前とのこと。
メッセージ数は qshape で取得するので、とりあえず次のようなシェルスクリプトを作る。

#!/bin/sh
/usr/sbin/qshape deferred | grep TOTAL | awk '{print $2}'
/usr/sbin/qshape | grep TOTAL | awk '{print $2}'
uptime | awk '{print $3$4}' | sed 's/,//g'
echo 'Postfix Queue Status'

グラフ 2 には、qshape がデフォルトで出力する incoming キューと active キューの合計を表示させるようにしてみた。
0 以外が返ってくることはほとんどないので、おまけのようなものだけどね。
あとは mrtg.cfg に次のような設定を追加すればいい。

Target[postfix]:`/usr/local/sbin/queue_status.sh`
Title[postfix]: Postfix Queue Status
PageTop[postfix]: <H1>Postfix Queue Status</H1>
Options[postfix]: absolute,gauge,growright,integer,nolegend,nopercent
MaxBytes[postfix]: 10000
YLegend[postfix]: Queue Status
ShortLegend[postfix]: Messages
LegendI[postfix]: deferred
LegendO[postfix]: Incoming

こんなに簡単なら、他にも色々とグラフ化してみたくなるなぁ。

親ディレクトリは絶対パスの中にあってもいい

とあるシェルスクリプトの中に

cd /usr/local/apache/htdocs/../conf

という行を発見。
へぇ〜。
親ディレクトリ「..」って絶対パスの途中で使ってもいいのか。
でも、混乱の元だろうな。
敢えてこんな風に書いてる理由は・・・、いまだに謎。

HTTP 限定のアプリケーションを SSL 対応にする

なんか変なタイトルだけど、要は HTTP にしか対応してない trac を HTTPS でアクセスできるようにしたかったという話。
といっても、trac に限らず、HTTP で待ち受ける形のアプリケーションなら何にでも流用できるテクニックだ。
実は以前、mod_python で動かそうとしたら、configure で

./configure: line 3427: syntax error near unexpected token `('
./configure: line 3427: `  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`'

というエラーにぶつかってしまった。
参考までに、このとき Apache のバージョンは 2.2.4、mod_python は 3.2.7 だった。
で、今は tracd は単体のデーモンとして起動していて、今回 SSL を通さないといけなくなったわけ。
前置きが長くなってしまった。
具体的には、Apache の SSL を有効にして、mod_proxy と mod_rewrite を使ってリバースプロキシを組むだけだ。
SSL の設定は敢えて書くほどのことでもないけど、一応。

cd /usr/local/apache/conf
# sed -i 's/^#Include.*httpd-ssl¥.conf/Include conf¥/extra¥/httpd-ssl.conf/' httpd.conf
# openssl req -new -x509 -out server.crt -keyout server.key
# openssl rsa -in server.key -out server_nopass.key    ※パスフレーズを省略する場合
# mv server_nopass.key server.key                      ※パスフレーズを省略する場合

あと、trac が http://www.example.com:8000/trac で見えるようになっているものとすると、httpd.conf に追加する設定は次の通り。

<IfModule mod_proxy.c>
    ProxyPass /trac http://www.example.com:8000/trac
    ProxyPassReverse /trac http://www.example.com:8000/trac
</IfModule>

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteLog "logs/rewrite_log"
    RewriteLogLevel 0
    RewriteRule ^/trac/(.*)?$ https://%{HTTP_HOST}/trac/$1 [R]
    RewriteRule ^/trac(.*)?$ https://%{HTTP_HOST}/trac/$1 [L,R]
</IfModule>

これで https://www.example.com/trac にアクセスがあると http://www.example.com:8000/trac に転送してくれる。
ただし、注意しないといけない点がある。
1台のサーバで trac と Apache の両方を動かすと、trac がリッスンしているポートへのアクセスがスルーされてしまうことだ。
上の例でいうと、http://www.example.com:8000/trac といった 8000 番ポートへのアクセスは Apache では制御できない。
こんなことを書いてるのはもちろん、1台のサーバで環境を作って、モロにこの問題でハマったからだ。
わざわざ HTTPS でアクセスさせようとしているのに、これでは正面玄関を全開にしているようなもの。
仕方がないので、iptables で 8000 番ポートをブロックして回避した。
別のサーバに分けた方がいいね。
時すでに遅し。
もうひとつ、ログイン/ログアウトがあるページでは動きが変になることがあるようだ。
trac ではログアウトがうまくいかなかった。
Cookie の問題かと思って、ProxyPassReverseCookieDomain とか ProxyPassReverseCookiePath の組み合わせをあれこれ試してみたけど変わらず。
mod_proxy も mod_rewrite も使いこなしているわけじゃないから、きっと設定の問題なんだろうな。
まぁ、ログインはできるのでとりあえず放置ということで・・・。

ディレクトリを再帰的に下りてファイル内の文字列を一括置換

ディレクトリを再帰的に下りていって、ファイルの中の特定の文字列を一気に置換しなければならなくなった。
漠然と、find でパスを作って、perl に渡してインライン編集すればいいかと思っていた。
ところが、最近は sed もインライン編集の機能を持っているらしい。
ということで

find . -type f | xargs sed -i 's/hoge/fuga/g'

これでいけた。
シンプルでいいね。
特定のファイルを処理対象から外すときは grep でフィルタするのが簡単。

find . -type f | grep -v '¥.tmp$' | xargs sed -i 's/hoge/fuga/g'

それにしても、近頃は sed をまったく使ってなかったなぁ。
perl より処理が軽いだろうから、もっと活用しよう。
ついでにもうひとつおまけ。
find の -exec は書き方にクセがあるのでほとんど使ってないんだけど、こっちを使えば xargs は不要だ。

find . -type f -exec sed -i 's/hoge/fuga/g' {} ¥;
find . -type f -ok sed -i 's/hoge/fuga/g' {} ¥;    #コマンド実行前に問い合わせる

xargs と同じように引数を一度に渡すこともできる。

find . -type f -exec sed -i 's/hoge/fuga/g' {} +

これが最速かな。