2009年12月28日月曜日

Syslogの内容をモールス信号でブザーから発音させる

まだ書いてなかったようなので一応。
サーバマシンには普通ディスプレイなどの出力装置はついていないことが多い。したがって、何かあればメールやついったーなどで知らせるのが当たり前だが(?)、私のサーバの場合、普段隣で動いているので、いちいちインターネットを経由するのは無駄であると言っていい。
そこで、唯一ついている出力装置であるブザーを使ってsyslogの内容を通知しようと思った。ただ単音では面白くないので、モールス信号で全てを読み上げさせる。

モールス信号を発音
今回のために、モールス信号を発音するためのシェルスクリプトを作った。標準入力から得られた英数字と記号をモールス信号で発音する。私のWebページにて配布している。
$ echo 'sos' | ./morse -h 120 -l 80

Syslogの設定
Debian lennyの場合、syslogではなくrsyslogが採用されている。したがって、/etc/rsyslog.confに以下の設定を追加する。
*.notice -/tmp/morse.tmp

FIFOを使えばよかったのだが、今回はとりあえずファイルでやってみる。

そして、以下のようなワンライナーを実行しておく。
$ tail -fn 0 /tmp/morse.fifo | perl -ne 'open(PIPE, "| morse -h 250 -l 40"); print;print PIPE; close(PIPE);sleep(3);'

これで、noticeレベル以上のログが記録されたタイミングで、モールス信号が発音されるようになった。

感想
ここまでやっておいて言うのもどうかと思うが、私は全くモールス信号がわからない。しかし、サーバから時々モールス信号が発せられていると、映画に出てくるマシンのようで非常に格好良い。贅沢を言うならタコメータがあればなお雰囲気はよくなるが、そこまで技量が無いので今回は残念だが見送った。
なお、今回はモールス信号が鳴っている様子を動画に収めた。300円もあれば購入できる出力装置なので、Linuxマシンが有るなら検討してみても良いのではないだろうか。

2009年12月26日土曜日

Computer Humanoid Interface

Computer Humanoid Interfaceというソフトを10月くらいから開発を始め、25日にリリースができた。マシンの監視のためのジョブを簡単に追加できて、出力はついったーに流せるので、「その時間に何が起こったか」を確実に残すことができる。
自然言語を理解したりするが、そのあたりの一切の処理はコアがやるので、ちょっとした管理スクリプトを組みたいだけなのにI/O関連の処理で時間をとられることがない。人間に指示を出すように簡単に機能を追加できるようにしたかったため、コンピュータの人間用インターフェイスとした。
これからブログには、CHIの機能をつらつらと書いていこうと思う。今回は、今後の展望を書く。

まず、プラグインで拡張できるので、逆に言えば簡単に取り外せる。プラグインは全てplugin/の中に入っていて、このうち絶対に必要なのはplugin.rbとmother.rbだ。あとは消してしまって構わない。
そうすると、何も監視しない、かつ何も出力しないCHIができあがる。一体こんなものになんの意味があるのか、と思われるかも知れないが、逆に言えば、ここからいかなるBOTでも創ることが出来てしまうのだ。
例えば、「〜食べたい」「〜たべる」などというポストがTL上に現れたら「〜おいしいよね」と返答するBOTを作りたいと思った場合、仮想コードだがだいたい以下のようになる。(なお、以下は次回実装予定の、フレンドタイムラインが更新されたときに1ポストごとに呼ばれる「onfriendtl」を使っている)


require 'utils'
require 'plugin/plugin'

module Plugin
class WannaEat < Plugin

def onfriendtl(watch, message)
if(message.body =~ /([^ 、。 ]*?)[食た]べ/){
return message.post(Message.new("$1っておいしいよね!", :tags => [self.name]))
}
end
end

end

# プラグインの登録
Plugin::Ring.push Plugin::WannaEat.new,[:friendtl]


以上のように、ついったーにつぶやく部分や、取ってくる部分はそもそも書く必要すら無い。しかも、onfriendtlのようなイベントハンドラが用意されているため(次回リリースからだけど)定期的に確認に言ったりする処理も書かなくて良いのだ。CHI付属プラグインは、このあたりにコンピュータの管理ロジックを書いており、必要なコマンドが無い場合は、プラグインの登録をしないようにしている(自動的にOFFになる)。

ここから考えられるのは、TwitterのBOTのフレームワークになりうる、ということ(というか、もうすでになってる)。つまりBOTが量産できる。
さらには、GUIフロントエンドをつけてしまえば、Twitterクライアントまで創ることが可能になる。これはなかなか面白い試みだと思っている。

ほかにも、設定ファイルへの簡単なアクセス(各プラグインの@configに、設定ファイルの内容が最初から入っている)、簡単なkey-valueデータベースの提供(at(:key)で取り出し、store(:key,val)で書き込みができ、再起動後も値が維持される)、画像投稿への対応(画像を含むMessageオブジェクトを渡されると、twitpicにアップするようになっている)など、BOTを創るにあたって必要そうな機能をだいたい持っているし、これからも短縮URLなどに対応する予定になっている。

2009年12月19日土曜日

Debian LennyにALSA入れて音を鳴らす

Bluetoothのスピーカーがあれば、そのスピーカーだけを持ち運ぶことができるので、端末から離れた状態でも音楽を聞くことができる。また、RubyなどでWeb上からmplayerなどを操作することができるようにしておけば、モバイル端末で曲の再生・停止ができる。これは、傍から見れば、宛らiPhoneでスピーカのWebサーバ(?)にアクセスして、スピーカ内の音楽を(w)再生しているように見えるのではないか。

しかし、GUIすら入っていないサーバでは、普段なら手動でやらない設定をいくつかしなければいけなかったので、それをここに書いておく。

環境
今回は、GUI及びサウンド関係のパッケージやソフトウェアが一切入っていないDebian lennyを使用する。
また、
$ lspci | grep Audio
00:1b.0 Audio device: Intel Corporation 82801G (ICH7 Family) High Definition Audio Controller (rev 01)

である。

パッケージ
今回は、ALSAを用いて音を出力するため、aptにて主要パッケージを入れる。また、サウンド再生ソフトとしてはmadplayを選択した。これは、コマンドライン上からmp3ファイルを再生するのに特化したソフトで、軽量で依存パッケージも少ない。
# aptitude install madplay alsa-base alsa-utils


ALSAの設定
この段階では、ALSAがサウンドインターフェイスに対する適切なドライバを選択できないのだが、それは自動設定に任せる。本来ならlspciの結果から適切なドライバをコンパイルするところだが、Debianとこのハードウェアなら必要ないらしい。
# alsaconf


カーネルモジュールの有効化
このままでは、私の環境では/dev/dspが見えなかったので、心当たりのあるカーネルモジュールの有効化をしてみる。
# modprobe snd-pcm-oss
# modprobe snd-pcm
# modprobe soundcore


鳴らしてみる
ここまでやって、以下のようにmp3ファイルをパラメータに渡してやると、見事サウンドが鳴った。
$ madplay packaged.mp3

なお、これでならない場合は、上記コマンドをrootユーザで実行するか、実行するユーザがsoundグループに入っている必要がある。

ビープ音を有効にする(2009/12/19追記)
以上の方法でスピーカを使えるようにすると、システムビープを鳴らす方のスピーカ(以下、スピーカ(笑))が鳴らなくなった。これは困るので、以下のように実行してpcspkrを有効にしておく。これで、サウンドボードの方からも、スピーカ(笑)でも発音が可能になる。
# modprobe pcspkr


感想
冷静に考えれば、音を鳴らすような基本的なことはGUIをインストールすれば難なく出来ているわけだから、逆に言えば最初から収録されているパッケージだけでできないはずがない。しかし、今回はステレオミニプラグでの接続だったため問題が簡単だったに過ぎない。次回は、これをbluetooth上で実行する。

おまけ
今回の設定中に、ALSAの設定を抜かしていたところ、なんとスピーカ(笑)で無理やり曲を再生し始めた。今にも壊れそうな音で、なんとか再生している様が不気味だった。


2009年12月1日火曜日

ラックマウントサーバーをつくってみた

サーバといえばかっこいい筐体。しかし現実はいかのとおりであった・・・。これはいけない。無駄にでかいことは写真からは伝わらないと思うが、それを抜きにしても謎の穴!じつはこれ、この間までここから電源装置が見えていた。しかし、1TBのハードディスクを増設した時に、電源装置のコードがそれにとどかず、やむを得ず場所を移動。その結果が
おわかりいただけるだろうか。中に居るのだ。このような構造のため、中吸気中排気という、自作PC'erがきいたらぞっとするような構造となっていた。CPUがAtomであるため、そちらは50℃弱だが(しかしAtomにしては高すぎる)、中の空気が恐らく30℃前後になっており、相当過酷な状況だった。
さらに、今回プリンタを購入したがこれの距離が少し離れており、できればサーバを近づけたかったけれど、残念ながら筐体が大きすぎてプリンタ周辺に配置する事が難しいという背景もあり、新しいPCケースをつくることにした。
しかし、時は師走。財布が出費を許さないので、捻出できる経費は2,000円。これでいかに格好いいマシンをつくるか。しかも、名前的にラックにしたいという兼ねてからの願望もあった。

設計
まず、マザーボードをどこに設置するかが問題である。ケーブルの長さで電源の場所が左右されるほど短いので、これが全てを決定するといっていい。
ここはありえない。

複合機でなければ可能ではあった。

ここがいい。机の横なので、少し目線を動かしただけでサーバが見える。物理的に見える必要は必ずしもないが、やはりかっこいいサーバにするなら見えていないと面白くない。


施工
とりあえず、2000円という予算なので、ダイソーにて以下の品を買ってきた。


鉄製のラックのパーツ。案外ダイソーでもこういった本格的なものが売っていて、わりとしっかりしている。今回はこれだけで、ラックマウントサーバを作成することにした。なお、25センチポールは、黒が七本しかなかったため、一つをとりあえず銀で代用している。また、この中にあるフォトフレーム(今回唯一の200円商品)は、スペースの関係上、サーバに使用することはできなかった。


ひとまずラックを組み立てた図。上、中、下段の3段に分かれている。サイズは奥行15cm、幅30cm、高さは25*2 + 47 = 97cmと、相当な高さになった。上下の高低差が激しいので、下のほうの段は単なる収納として作った。
ここでわがサーバ、limeの構成について書いておく。

マザボ:Atom 330
 CPU 1.6GHz (Dual Core)
 100base LAN x1
メモリ: DDR2 512MB
ストレージ:
 SATA HDD 1TB
 IDE HDD 120GB
 IDE HDD 80GB
電源装置:
 一切不明(2001年に、近所のPC屋さんが組んだ安いPCを買ったが、それについていた)
 推定年齢7〜8歳

基本的にリモートアクセスするだけなので、入出力装置は普段は一切ついていない(ただ、今回はプリンタをつけるので出力装置は増える)。早速、これらのパーツをラックにマウントしてみる。

このようになる。ケーブルはまだほとんど接続していない。マザーボードは、上部の47cmのポールを補強するためのパーツに、結束バンドでマウントした。電源装置の関係で、やはりすべてのパーツが上に集中、中段と下段がぽっかり開いてしまった。
これにすべてのケーブルを適切に接続すると、以下のようになった。
できるだけスマートに収めたかったが、ケーブルの硬さと短さがネックになりハードディスクを立てざるを得なかったなど、いろいろと問題が起こってしまった。しかしながら、インテリアとしても優れた、今流行の「スリム型」「タワー型」PCよりもスリムでタワーなラックマウントサーバができたと思う。

おまけ

先日Mac Book Proを購入したが、付属のソフトをあまりつかいこなせていない。そこで今回は、動画や写真をiPhoneで撮影し、iMovieを用いて一本の動画にまとめて、Youtube(Youtubeで見る)やニコニコ動画(ニコ動で見る)にアップロードしてみた。上の繰り返しになるが、3分ほどの動画なので時間があればぜひ。

2009年11月2日月曜日

gnome-openが適切な関連付けを忘れてしまった件

なぜか、gnomeの「場所」からディレクトリを選ぶと、RhythmBoxが起動してしまう。しかしデスクトップなどでディレクトリをダブルクリックすると正常にディレクトリは開くことができ、そこから別のディレクトリにいくこともできる。
また、端末からnautilusを起動すると正常に起動できた。すなわち、gnome-openが諸悪の根源となっているらしい。というわけで、

gnome-open ~/Documents/

RhythmBoxが立ち上がった。どうやら関連付けが間違っているらしいので、今回は修正方法を調べた。
参考:Ubuntu 8.04でgnome-openの関連付けを変更する
ここに書いてあることがすべてだが、私の場合なぜか
.local/share/applications/mimeapps.list
というファイルに
inode/directory=rhythmbox.desktop
という設定が書いてあったのでこれを削除することで解決した。
このユーザは私のものではなかったので、きっと本人の誤操作でこういった関連付けの破壊が起こったのだろうと思うが、こういうことがあるにつけ、バックアップはとっておかないとな、と思うのであった。

2009年10月28日水曜日

【LVM】1TBのHDD増設レポ

LVM(Logical Volume Manager)は、パーティションの前後関係やディスク容量を気にすること無く、望むなら二つ以上のディスクに渡ったり別のボリュームを飛び越えてでもボリュームを作ることが出来るツールで、このブログでは一度も言及していないが私はいつもお世話になっている。

今回は、右図のように、1TBのHDD(SATA2)を組み入れる。もともと、ボロボロの80GBのHDD(以下、sdc)がバックアップ用、OSを含むマスターファイルが120GBのボロボロのHDD(以下、sdb)に割り当てられていた。それぞれ、backup、storageというVGを割り当てて管理していたが、今回バックアップが溢れそうになったこと、サーバにデータを置いてnfsで管理する方法を採ることにしたことなどが原因で、新品の1TB(以下、sda)のHDDを購入した。既存の2つはIDEであるうえ、どちらもたいした容量がないため、二つ合わせてbackupとする※。また、アクセス速度と容量を兼ね備えた新品のHDDには、storageの役割をになわせるのが最適だ。つまり
  1. sdaをLVMでフォーマットし、
  2. sdbのデータをsdaに移行し、
  3. sdbをbackupに参加させる
という作業が必要となってくる。自宅サーバであること、当日疲れていたことなどがあり、あまり止めても要られないので、サーバの停止時間は1時間程度に収めたいが、LVMを使用していればOSの再インストールなしでこれらの一連の作業ができた。

※ pdumpfsで、一時ファイルや大きすぎるファイル(動画など)を除外してバックアップしているので、バックアップにはたいした容量は必要ない

1. sdaのフォーマット

このセクションは、新しいディスクをフォーマットしたりするだけなのでサービスを動かしたままで行えるが、運用中のディスクからコピーをとるので、CDブートが望ましい。
ただのフォーマットだが、これが案外ややこしい。sdbをバックアップに降格させるため、sdbのMBRと/bootパーティションをコピーすることが必要になる。
今回の場合は、sdbはsdb1(200MB,ext2)、sdb2(120GB,lvm)となっている。したがって、sda1とMBRだけあればいい。
ここで荒技なのだが、ddを使ってコピーをとる。
# dd if=/dev/sdb of=/dev/sda
これの欠点は、sdbの大きさ分、つまり120GBをすべてコピーしてしまうということ。当然意味が無いので、数秒で止める。すると、コピー速度が出てくるので、sdb1の大きさから、必要な部分がコピーし終わるまでの時間を計算して、その時間待つ。これで、狙った部分のみコピーできる。ちゃんと大きさを指定することもできるが、どうせフォーマット前のディスク、こっちのほうがはるかに速い。
あとは、fdiskでsda2を作成してやればできあがり。sda2はゴミが入っているので、pvcreateに-ff(force)オプションをつける。
# pvcreate -ff /dev/sda2
# vgextend storage /dev/sda2

ここまで終われば、現在VGstorageは現在1.12TBの大所帯になっている。これから、0.12TBを追い出すわけだが、ここからはオンラインではできないので、CDブートで残りの作業を進める。
# reboot


2. sdbからデータを追い出す

現在、storageはsda2とsdb2が使われているが、sdbは一度空にしなければならないので、sdbからデータを追い出す。そのためのコマンドが用意されている:pvmoveだ。
# pvmove -v /dev/sdb2

これで、すべてのLVがコピーされるまで待つ。ddとちがってLVだけをコピーするのでまだ速いが、結構時間がかかるので、-vオプションで暇つぶしをするのは必須。
そして、これが終わったら/dev/sdb2をstorageから脱退させる。
# vgreduce -v server /dev/sdb2

実際には、pvmove終了後からはサービスの稼働は可能と思われるが、念のためこのまま最後まで作業を進めた。

3. sdbをbackupにする

これで、sdb2は宙に浮いてしまった。これを今度はbackupに参加させる。また、backupの唯一のLV「backup01」を200GBまで拡大する。backup01はxfsなので、xfs_growfsコマンドを使えばマウントしたままリサイズすることができる。ひとつ注意点は、xfs_growfsは、デバイスファイルではなくマウントポイントを指定するということ。
# vgextend backup /dev/sdb2
# xfs_growfs /backup


まとめ

以上の行程を踏めば、pvmoveの時間に依存するが1時間かからずにすべての作業が完了する。割とクリティカルな端末でもLVMが効力を発揮できることが実証できたと思う。
ただ、今回のpvmoveは今回初めて使ったので、もしかしたら運用中に実行できたのかもしれない。これが可能ならば、システムを一切止めること無くディスクを増設することができるようになるかもしれない。

2009年10月17日土曜日

重複ファイルを表示「difflatten」

ファイル名などには意味がなく、内容だけに意味があるファイルの集合に、同じルールで適当に集められたファイルをマージする話。(製作動機は後述)

概要

普通、ファイルが同じかどうかはdiffコマンドで調べることができる。
$ diff a.jpg b.jpg
しかし、最初に述べたような状況の場合、diff a.jpg storage/などとはできない。私は「echo storage/* | xargs diff a.jpg」と考えたがこれはstorage以下にディレクトリがあるとうまくいかない。また、一気に多数のファイルの重複を確認しようとした場合、ちょっと頭をひねらなければならない。

そこで、「ディレクトリAとディレクトリBの中のファイルで同じものがあれば、そのファイル名を出力する」スクリプトを書いた。外出っぽいけどちょっと見つからなかったので。

うちのWebページ
で配布してます。

以下のように実行すると、「A = B」のような行が出てくる。これは、二つのファイルが同じであることを示している。

$ difflatten.rb src/ dst/
src/1880.jpg = dst/images/sky/sunset14.jpeg
src/994.jpg = dst/images/material/takuan.jpg


これを応用すれば、以下のようにするとdst/以下のファイルでsrc/以下にもあるファイルは(dst側から)すべて削除できる。

$ difflatten.rb src/ dst/ | awk -F' = ' '{print $2}' | xargs rm


仕組み

今回はRubyで実装し、ライブラリは標準のものしか使っていない。
まず、src以下を再帰的に走査して、すべてのファイルのサイズを取得し、dst以下を走査して、srcと同じサイズのものがあれば、ダイジェスト(SHA512)で二つを比較している。当初はダイジェストのみで比較していたが、srcに500個、dstに2000個程度のファイルを入れて試したところ37秒もかかってしまった。そこで、まずサイズを比較することで、ダイジェストの計算回数を最小限に抑え、実行時間を0.2秒にまで縮めることに成功した。実際には、dstに同じファイルが2つ無い限り、ダイジェストより直接比較した方が速いのだが、そこまで速度的に不利にはならないと思われる。

動機とか

最近、というかずっと画像収集をしているのだが、あまり時間も裂けないのでとりあえずzipで落としてきて、「うーん」と思った奴は適宜削除、というスタンスをとっていた。しかし結構同じ画像が入っていることが多かったので、自分のコレクションに入れる前に重複を確認するスクリプトを作って既に持っている画像を弾き出そうと考えた。
もちろん、加工されるとハッシュ値が変わるので、本当は画像の類似度などを考慮する必要があるが、補助的には使えると思う。
今回は「削除する」ではなく「重複を表示する」だけに止めたので、いろんな使い方ができるかもしれない。

ちなみに、動作にはruby(作者環境1.8)がインストールされていること、diffなのに同じ物を表示してるじゃん!とか言わないこと、引数を必ず2個与えることが要求されます。

2009年8月15日土曜日

postfixのインストール

月並みなタイトルだけど、Debian Lenny on Niftyな環境でのSMTPサーバであるpostfixのインストール記録。
今回は、自分のメールアドレス(foo@mail.comとする)に対して、サーバ内のroot及び自分のアカウントに届いたメールを転送する設定をする。したがって、POPやIMAPといったメール受信サービスは提供しない。

インストール
aptで済ます。ただし、exim4を削除して入れる場合にはmailutilsパッケージが削除されてしまうようだ。最小構成の場合にはそもそも入っていなかったようだったので、どちらにしても同時に入れておく必要がある。
# aptitude install postfix mailutils
postfixのインストール中に、用途を聞かれるので「インターネット」とする。

設定
/etc/postfix/main.cfを修正。
smtpd_banner = $myhostname ESMTP
(Postfixであることを隠す)
myhostname = toshia.dip.jp
(自分のサーバのFQDN)
mydestination = toshia.dip.jp, server, localhost.localdomain, , localhost
(このドメイン名宛のメールはこのマシンで受ける。myhostnameを追加しておく)
relayhost = smtp.nifty.com
(外向きメールはこのメールサーバを経由させる。上記はプロバイダがNiftyの場合には絶対必要)
mynetworks = 192.168.1.0/24 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
(リレーを許可するネットワーク。LAN内の全マシンがサーバ経由でエラーを通知できるようにしたいので設定した)
そして、/root/.forwardに自分のユーザ名、~/.forwardにfoo@mail.comと書いておけば、rootと自分のユーザに来たメールがfoo@mail.comに転送されるようになる。ただ、エイリアスファイルを作る方法もあり、それはrootでしか設定できないようになっているし、実在しないユーザ(postmasterとか)に対しても転送がかけられるので、そちらを使う方がベターだ。今回は割愛。

これで、rootで実行しているcronのジョブの結果も届くようになるし、その他何かあれば通知がくるようになる。SSHで誰かがログインする度にその旨をメールしてもいいかもしれない。
また、http://www.aconus.com/~oyaji/security/relay-mail.htmで紹介されているサービスを利用して、外部中継チェックを念のためにかけておく。今回はしなかったが、外部からのメール受信をすべて拒否して、メール送信専用にしてしまってもいいかもしれない。

2009年8月8日土曜日

サーバがまた死んだ

この間の豪雨の際、雷で三回ほど瞬間停電したのだが、どうやらこの間にサーバのデータが壊れていたようで、起動不能になった(起動中にエラーを吐いてランレベル6に移行するのだが、そっちでもエラーを吐いて止まる)。
ちょっと調べても原因がわからなかったので、(この間やったばかりなので覚えているということもあり)Debian Lennyを再設定することにした。

ApacheとSubversionのインストール( + ApacheのWebDAVを使ってSVNを動かす)
必要なパッケージのインストール

# aptitude install subversion libapache2-svn

libapache2-svnをインストールした時に、apacheのdavというモジュールが有効になる(apache2をパッケージで入れた場合、無効になっているだけで既に入っている)。

# mkdir /var/svn
# svnadmin create /var/svn
# chown -R www-data:www-data /var/svn

リポジトリを作成する。ただし、ここでリポジトリの所有者をapacheにしておかなければならない。

以下の内容を/etc/apache2/conf.d/以下に適当な名前(svnなど)で作る。

<Location /svn/miku>
DAV svn
SVNPath /var/svn/miku

Order Deny,Allow
Allow from 192.168.1.0/24
Deny from all

</Location>


Order ~ Deny from allまでは、192.168.1.*しか許可しないという意味になるので、外からのリポジトリへのアクセスを一切拒否している。外からアクセスしなければならない時はSSHでトンネルを張れば良いだけのことなのでこれで十分。なお、ローカルからもトンネル経由でないと許可しない、という設定にする場合は、Allowのところにlocalhostと書いてもいいかもしれない。いずれにしろ、SVNはソースコードなどの重要なデータがインターネット上を流れるので、SSH、VPN、SSL等で暗号化するのが望ましい。

ここまでの設定を確認。ローカル(別のPC。別に同じマシンでも可)にてチェックアウト。
本当はインポートとか使うんだろうけれど、普段やり慣れている方法でやってしまうよね(その方がミスが少ない・・・成長を妨げる要因だ)。

$ svn checkout http://server/svn
$ cp -ra /path/to/original svn/
$ svn add svn/*
$ svn commit

コミットできたら一応成功。

コミットしたら公開

こういうのを何て呼ぶのかは忘れたが、リポジトリのhook scriptを触れば実現できた。
/var/svn/hooks/post-commitに以下のように書く。

#! /bin/sh
/usr/bin/svn export --force file:///var/svn/ /var/www/

post-commitはコミットが成功した後に実行されるコマンドなので、この中にエクスポートするコマンドを書いておけばいいのだ。
これで、コミットの度にファイルが/var/wwwにエクスポートされるようになった。

eRubyを有効にする
RubyをPHPみたいに組み込みっぽく使いたいので(というか我がWebサイトで使っているので)eRubyを導入する。普通のHTMLのように書けるが、の間に書いた文章はRubyスクリプトとして実行される。
このインストール作業が意外と面倒。

# aptitude install euby eruby libapahe2-mod-ruby

まずは普通にインストール。
そして、/etc/apache2/mod-enable/ruby.loadに以下を追記(参考サイトからコピー)。

<IfModule mod_ruby.c>

RubySafeLevel 1

RubyRequire apache/ruby-run

RubyRequire apache/eruby-run

<Files *.rhtml>
SetHandler ruby-object
RubyHandler Apache::ERubyRun.instance
</Files>

</IfModule>

なお、私の場合はRuby Script内でファイルの最終更新日を調べているが、これはsafe levelが0でなければ動かないらしい。なんだか気味が悪いが、とりあえず0にした。

これだけでは、*.rhtmlをクリックしてもファイルダウンロード画面になってしまう。原因は、Live HTTP Header等で調べれば一目瞭然だが、MIME Typeが「application/x-httpd-eruby」というよくわからないものになっている(通常、text/htmlになっている)。これを正すために、/etc/mime.typesにちょっと手を加える。
以下のような行があるので、その行頭に # (コメント)をつける
application/x-httpd-eruby rhtml
これで完了。なんでも、eRubyがこういう風にmime typeを決め打ちされることを想定していないらしい。

これで私の環境復元は終了したのだが、6月、8月と二度も立て続けにクラッシュしたという事実をみすみす見逃してはいられない。あまりにもばかばかしいことだが、一応まとめると:
  • 停電対策(UPS)がまったくなされていない
  • バックアップサーバ自体のバックアップは取られていない
という問題があった(というか、ある)。
まず、UPSは雷の多い地域なので見当の余地はあるが、お金のかかることなのですぐには手は出ない。
問題は二つ目である。これは絶対にやっておくべき対策で、今すぐにでも手を打つべきだ。いままでやってなかった理由としては、「HDDの空き容量がないよ!」だったのだが、今やサーバにHDDを4台ほど積めるスペースがあり、バックアップ用HDDも搭載しているので、やろうとおもえばすぐにできる。

異常気象とはいえ、組んだばかりのサーバをあまり痛めつけてほしくないものだ。

2009年8月5日水曜日

Ultimate Boot CD


という、ダサすぎる名前のCDを発見した。

「究極の起動ディスク」

・・・実は今回、sda4に残しておいたWindows XPのリカバリパーティションを使おうと思ったのだが、なんとgrubで叩いても起動しない。そこで適当にぐぐっていたらこんなものを発見し、ダメ元で試したらいけたという話。

これを起動すると、

boot:

というプロンプトが表示されるのでエンター。するとメニューが出てくるので、Boot Manager → Smart BootManager 3.7.1と選択。そして、fat32のパーティションを指定すると、なぜか起動できた。理屈はよくわからないが・・・名前に恥じない究極のCDだ。

しかもこれ、パーティションを編集するツールとか、ハードウェアをテストするツールとか、いろいろ入っている。さしあたって必要がなくても、念のため普段からもっておけばいざと言うときに役に立ちそうだ。

※起動しない理由は、パーティションにアクティブフラグとかいうのがついているのが原因らしい。インストールしたらNTFSについてしまい、仕方なくこのCDで起動して使っているが、アクティブって何なのか未だに不明・・・。

VMPlayer + iTunesにご用心

そんな環境でつかっている人、あまりいないと思うけれど。
wineでiTunesがうまく機能しない。
というのは、起動するのだが、あろうことかiPodを認識しないのだ(私はiPhoneだが同じ)。

そこで、当然諦めてVMWare PlayerのWindows XPに逃げるのだが、こちらではあっさり同期もできるし、満足していた。


iPhone OSのアップデートが先日リリースされた。それで、「アップデートも余裕だぜ☆」と、VM上でやってみたのだが、こともあろうにエラーで止まる。しかも中途半端に書き込んだようで、見事に起動しない。何度やっても同じ。
オワタと思ったがこの記事を参照して、「あぁ、仮想マシンだったらダメなんだ」と納得。時々VMWareでもダメなことってあるものなのだ。

そして、紆余曲折を経てWindows XP HOMEをインストールし、iTunesをインストールしてiPhoneをつないだら動き始めた。

その次は仮想マシン(普段同期とかやってるマシン)から復元。見事に元の環境に戻った。

こんなことに7時間もかかった(窓のインストールが主な原因)。滅多にいないと思うが、同じような環境にいる方は気をつけてください。

2009年7月4日土曜日

ガラクタにDebianをインストール

8年頑張ってくれたサーバ機が壊れたので、最近(8年から見れば最近)何かと話題のAtomのマザーボードを買ってみた。

http://www1.pcdepot.co.jp/webshop/commerce/CSfEcLastGenGoodsPage_001.jsp?GOODS_NO=42471&IMG_ROOT=/webshop

型番で検索すると「誰がこんなもの買うんだ」みたいな批評も出てくるが、PCIが2枚、PCI Expressが1枚挿せるのでこれにした。100BASEケーブルにしか対応してないけれど、壁内を通しているケーブルが100BASEケーブルだから当面ギガビットは要らない。

すんなり行くだろうと思いきや、いろいろと問題が起こり、バッドノウハウが溜まったのでメモ。

DebianをUSBインストール
参考:公式サイトの「USB メモリでの起動用ファイルの準備
Ubuntu8.04でDebianのインストールUSBドライブを作成した。とはいっても、とくに難しいことはない。


# aptitude install selinux mtools
# syslinux /dev/sdc1 # USBメモリのデバイスファイル
# mount /dev/sdc1 /mnt
# cd /mnt
# echo "default vmlinuz" > syslinux.cfg
# echo "append initrd=initrd.gz" > syslinux.cfg


そして、ISOイメージをUSBメモリの中に放り込んで完成。作る側がDebianでもUbuntuでも何ら相違なかった。
これをマシンにさして、USBブートすればインストールできる。CDに焼くより早くできるので、余っているクリップドライブがあるならこれはかなり良い。


aptにISOイメージをCDとして認識させる
参考: Re:apt-cdrom on iso mount
これは厄介。USBインストールだとCDがないから、ISOイメージをCDとして認識させる必要がある。
(マシンにCDドライブが無く、ネットワークに接続できないため。でなければこんなもの不要かと思われる)
以下、インストールしたマシンで

# mount -o loop debian.iso /mnt
# nano /etc/fstab
上記マウントをfstabにも書き込む。
/home/toshi/debian.iso /mnt iso9660 loop,user 0 0
# nano /etc/apt/sources.list
以下の一行を追加
deb file:///mnt/ lenny main
利用しないリポジトリをすべてコメントアウト
# aptitude update


これでISOイメージをdebianパッケージの入ったCDとして利用できる。


組み込みLANインターフェイス「Realtek RTL8101EL」のドライバをDebian Lennyにインストール
参考:本家のドライバ - treffen - 自宅サーバ
これが一番厄介だった。R8101ELは、Linuxカーネルにこのドライバが組み込まれていない。そのため、Realtek本家のソースコードをコンパイルするわけだが、これがエラーを吐いてくるので若干の修正が必要なのだ。
まず、本家ドライバをUSBメモリなどで新PCに移動。
次に以下ようにパッケージをインストール

# aptitude install linux-headers-`uname -r` libgomp1


あとはマニュアルどおり

# lsmod | grep r8169
(元々入っているドライバが表示される)
# rmmod r8169
# lsmod | grep r8169
(表示されなくなる)


R8010用ドライバのディレクトリに移動して以下のパッチを適用。本当にやっつけなので、無保証です。
共通の下位ディレクトリー: src-orig/.svnとsrc/.svn
src/だけに発見: modules.order
diff -c src-orig/r8101.h src/r8101.h
*** src-orig/r8101.h 2008-01-04 18:48:42.000000000 +0900
--- src/r8101.h 2009-07-04 01:17:43.220310388 +0900
***************
*** 49,55 ****
--- 49,57 ----

#define NODE_ADDRESS_SIZE 6

+ /* temporary disable
#define CONFIG_R8101_NAPI 1
+ */

#ifdef CONFIG_R8101_NAPI
#define NAPI_SUFFIX "-NAPI"
***************
*** 988,990 ****
--- 990,1000 ----
#endif
unsigned wol_enabled : 1;
};
+
+ #ifndef SET_MODULE_OWNER
+ #define SET_MODULE_OWNER(dev) do { ; } while(0)
+ #endif
+
+ #ifndef SET_NETDEV_DEV
+ #define SET_NETDEV_DEV(net,pdev) ((net)->class_dev.dev = (pdev))
+ #endif
あとはマニュアルどおり。

# make clean modules (as root or with sudo)
# make install
# depmod -a
# insmod ./src/r8101.ko (or r8101.o for kernel 2.4.x)
確認用↓
# lsmod | grep r8101
# ifconfig -a
これで、晴れてネットワークにつながるようになった。
久しぶりにいろんなサイトを駆けずり回った。Linuxも易しくなったものだ・・・。
あとは、サーバを復旧するだけだ。

2009年3月22日日曜日

Xdmxを使ったマルチディスプレイ



Xdmxを使うと、別々のコンピュータに接続されているディスプレイ同士を繋いでマルチディスプレイが実現できる。
試しに、普段使っていないサーバのディスプレイを活用してマルチディスプレイを実現した。
今回は、laptopでUbuntu8.04(Gnome)を、serverでDebian lenny(CUI)を実行しているものとする。
serverとlaptopをまたいで設定しなければならないので、serverを赤、laptopの端末を青で表記する。

サーバの設定

サーバに、Xを起動するためにxinit、X起動後の端末としてxterm、xhostでlaptopからのアクセスを許可するためにx11-xserver-utils、そして、X Window Systemのサーバであるxserver-xorg-coreをインストールする。
server% sudo aptitude install xinit xterm x11-xserver-utils xserver-xorg-core

そして起動するが、このコマンドはSSHなどではなく、serverのコンソール上で実行する必要がある。
でないと、以下の(失敗例)ように怒られる。
server% xinit -display :0
(失敗例) X: user not authorized to run the X server, aborting.
(成功すると、グラフィカル(笑)な表示に切り替わり、xtermのウィンドウが開く)


laptopからX Serverにアクセスできるように権限を追加(毎回やる必要があるらしい)
server% DISPLAY=:0 xhost +laptop

なお、サーバには環境変数をつけているが、X Serverで動いているxterm上で実行できる場合は必要ない。
私はサーバに接続するマウスを持っていないので、このようにディスプレイを指定した。
(マウスをxterm上に持っていかなければ、コマンドが打てない)

laptopの設定
Xdmxを、ウィンドマネージャを実際に動かすほう(laptop)にインストールする。ただじ、なぜかUbuntu8.04ではXdmxがリポジトリから削除されているので、以下のサイトからパッケージをダウンロードしてくる。
laptop% wget http://launchpadlibrarian.net/9590666/xdmx_1.3.0.0.dfsg-12ubuntu8_i386.deb
laptop% sudo dpkg -i xdmx_1.3.0.0.dfsg-12ubuntu8_i386.deb

dbusの権限を緩める
何かの用途でdbusを使っているようだが、設定されている制限がきつすぎることがあるらしい。
gnome-session後、以下のようなエラーが大量に出る。
** (nm-applet:5716): WARNING **: nma_dbus_init(): could not acquire its service. dbus_bus_acquire_service() says: 'Connection ":1.30" is not allowed to own the service "org.freedesktop.NetworkManagerInfo" due to security policies in the configuration file'
そういう場合は、/etc/dbus-1/system.d/nm-applet.confのdefaultセクションの「org.freedesktop.NetworkManagerInfo」のdenyになっているところをallowに変更し、デーモンを再起動。
laptop% sudo nano /etc/dbus-1/system.d/nm-applet.conf
<policy context="default">
# <deny own="org.freedesktop.NetworkManagerInfo">

# <deny send_destination="org.freedesktop.NetworkManagerInfo">
# <deny send_interface="org.freedesktop.NetworkManagerInfo">
<allow own="org.freedesktop.NetworkManagerInfo">

<allow send_destination="org.freedesktop.NetworkManagerInfo">
<allow send_interface="org.freedesktop.NetworkManagerInfo">
</allow>
laptop% sudo /etc/init.d/dbus restart
これでほとんどのdbus関連のエラーは出なくなったのだが、dbusが使われている要所要所でエラーが起こっている。セキュリティの心配もあるので、要調査。
参考
http://lists.freedesktop.org/archives/dbus/2007-January/006874.html

Xを終了

開いているディスプレイ番号を振っていけばいいので、本来こんな設定は必要ないのだが、GNOMEの場合は多重起動ができないそうなので、勝手にgnomeが立ち上がらないようにする必要がある。
Xfceなどを新たにインストールするのも手だが、とりあえずうまく動くか試してからのほうがロールバックが楽なので、Xを単に終了する。
sysv-rc-confは、各ランレベルで何を起動するかを指定することができるコマンドラインツールだが、「-」キーを押すとそのサービスが一時的に終了するようになっているので、これを利用する。
laptop% sudo aptitude install sysv-rc-conf
laptop% sudo sysv-rc-conf

gdmと書いてある行で-キーを押せばxが終了し、コンソールのログイン画面に飛ぶ。

デュアルディスプレイでgnomeを起動
二つのディスプレイを使ったX Serverの起動
以下のように、serverからlaptopのX Serverにアクセスできるようにしてから実行する
laptop% xhost +server
laptop% Xdmx :1 -display laptop:0 -display server:0 +xinerama &

エラーが出た場合、大抵の場合「〜オプションをつけたら?」といったメッセージが出ているので、それをつけて再度実行。
ちなみに、私は「-ignorebadfontpaths」をつけた。
gnome-screenを実行することで、二つの画面に渡ってgnomeが起動する。
laptop% gnome-session

もちろん、serverにはgnomeが入っている必要はない。
ちなみに、Xdmxを実行した時点でxtermなどがまったく立ち上がらないため、私は以下のようにしてgnomeを立ち上げた。
laptop% xhost +192.168.0.2 && Xdmx :1 -display localhost:0 -display 192.168.0.2:0 +xinerama -ignorebadfontpaths & sleep 5; gnome-session
ほか、自動起動スクリプトなどを書くべきだろうが、とりあえずはこれでよしとする。


所有しているVAIOのモニタをラップトップで使用しようとしたところ、コネクタが独自規格で接続できなかった。諦めていたのだが、Xdmxを使えば他のマシンのXサーバを使ってマルチディスプレイ環境を実現できることを知り、今回挑戦してみた。
また、今回は一度仮想マシンで実験して、うまくいってから実機で試してみた。当然だがこちらのほうがミスも少ないし、ドキュメントもより正確な物が書ける。今度からこれでテストをしよう、と思う。
一見うまくいったようだが、実はウィンドウを動かしたりするとかなり動作がもたつく(特に、SCIMの動きが絶望的)。さらにDirectXを使用したアプリケーションが動かない。まだクリアすべき問題は残されている。

2009年3月18日水曜日

wineビルドスクリプト「mkwine.sh」

私はできるだけパッケージ管理ツールを使うように心がけているのだが、wineだけはいつもコンパイルしている。というのも、
  • 開発が早いため、あるソフトを動かすためにはバージョンx.y.zが必要、ということが間々ある
  • 自作や拾い物のパッチを当てたい
  • 何か一つくらいソースコードいじったりしているといざと言うときに自慢できる
  • そもそも、Wineの開発を追うのが趣味
といった事情があるからだ。しかし、バージョンアップのたびにいつも同じような作業をするのは面倒極まりない。そこでスクリプトを書いて便利に使っていたのだが、今回大幅に機能強化し、多少は汎用性が上がったと思うので、公開してみる。

#! /bin/sh
CONFIGURE_OPTS=""

while getopts c:ip OPT
do
case $OPT in
"c" ) CONFIGURE_OPTS=$OPTARG ;;
"i" ) INSTALL="true" ;;
"p" ) PATCH="true" ;;
esac
done

shift $(($OPTIND - 1))

WINEVER=$1
DOWNLOAD_TMP="/tmp/wine-"$WINEVER".tar.bz2"

abort () {
echo $1
exit 1
}

if [ -e "wine-"$WINEVER ]
then
echo "Already wine-"$WINEVER" is exist. Compile start."
cd wine-$WINEVER || abort "error: move current directory to latest wine"
else
if [ -e $DOWNLOAD_TMP ]
then
echo "Already "$DOWNLOAD_TMP" is exist. Melt start."
else
echo "wine-"$WINEVER" isn't exist. Download start."
wget http://jaist.dl.sourceforge.net/sourceforge/wine/wine-$WINEVER.tar.bz2 -O $DOWNLOAD_TMP || abort "error: file download"
fi
echo "Start melt "$DOWNLOAD_TMP
tar jxf $DOWNLOAD_TMP || abort "error: decompress"
rm $DOWNLOAD_TMP
cd wine-$WINEVER || abort "error: move current directory to latest wine"
if [ $PATCH = 1 ]
then
for i in ../*.patch
do
patch -p 1 -R < $i || abort "error: patch " $i
done
fi
fi
./configure $CONFIGURE_OPTS || abort "error: executing ./configure $CONFIGURE_OPTS"
make depend || abort "error: make depend"
nice -n 19 make CC="ccache gcc" CXX="ccache g++" || abort "error: compiling"
echo "no errors, success to compile."
if [ $INSTALL = 1 ]
then
sudo make install || abort "install missing"
else
echo "please \`make install' for root to install wine for your system."
fi

(あまりシェルスクリプトは慣れていないので変な書き方になっているかもしれない)
例えばこれを書いている時点での最新版(1.1.17)をインストールしたいなら、
$ mkwine.sh 1.1.17
と実行すれば、
  1. wineの公式サイトから/tmp以下にwine-1.1.17.tar.bz2がダウンロードされ、
  2. カレントディレクトリに解凍、
  3. -pが指定されていればカレントディレクトリに置いてあるパッチを当てる
  4. ./configure; make depend; makeを実行
  5. -iが指定されていればmake installする
という、一通りの作業を自動化できる。最初はバージョンくらいしか指定できなかったのだが、だんだんパッチを当てるようになったりして大きくなってきた。パッチにバージョン番号を書いておいて当てる必要があるパッチを自動判別するとか、自動的に最新版を落としてくるとか。

# もうあったりして・・・?

2009年3月6日金曜日

pulseaudioでサウンドサーバ

うちのDebian lennyの入ったサーバにpulseaudioをインストールして、サーバに音を鳴らさせてみよう、と思った。最近じゃじゃ馬のpulseaudioを見事懐柔し、上機嫌になっていたのだが、サウンドの合成がやたらと重いことがあるので、ちょっと試しにやってみようと思ったのだ。どうせこのサーバ(toshia.dip.jp)、そんなにアクセスもないから、普段暇をしているし。
# aptitude install pulseaudio
aspell{a} aspell-en{a} avahi-daemon{a} bind9-host{a} dbus{a} dbus-x11{a}
dictionaries-common{a} fontconfig{a} fontconfig-config{a} gconf2{a}
gconf2-common{a} gnome-audio{a} gnome-icon-theme{a}
gstreamer0.10-pulseaudio{a} hal{a} hal-info{a} hicolor-icon-theme{a}
libasound2{a} libasound2-plugins{a} libaspell15{a} libasyncns0{a}
libatk1.0-0{a} libatk1.0-data{a} libavahi-client3{a}
libavahi-common-data{a} libavahi-common3{a} libavahi-core5{a}
libavc1394-0{a} libavcodec51{a} libavutil49{a} libbind9-40{a}
libcairo2{a} libcairomm-1.0-1{a} libcroco3{a} libcups2{a} libdaemon0{a}
libdatrie0{a} libdbus-1-3{a} libdbus-glib-1-2{a} libdirectfb-1.0-0{a}
libdirectfb-extra{a} libdns45{a} libenchant1c2a{a} libfaad0{a}
libflac8{a} libfontconfig1{a} libfreebob0{a} libgconf2-4{a}
libgconfmm-2.6-1c2{a} libglade2-0{a} libglademm-2.4-1c2a{a}
libglib2.0-0{a} libglib2.0-data{a} libglibmm-2.4-1c2a{a} libgsf-1-114{a}
libgsf-1-common{a} libgsm1{a} libgstreamer-plugins-base0.10-0{a}
libgstreamer0.10-0{a} libgtk2.0-0{a} libgtk2.0-bin{a} libgtk2.0-common{a}
libgtkmm-2.4-1c2a{a} libhal-storage1{a} libhal1{a} libhunspell-1.2-0{a}
libice6{a} libidl0{a} libiec61883-0{a} libisc45{a} libisccc40{a}
libisccfg40{a} libjack0{a} libjpeg62{a} libltdl3{a} liblwres40{a}
liblzo2-2{a} libmalaga7{a} libnotify1{a} libnss-mdns{a} libogg0{a}
liboil0.3{a} liborbit2{a} libpango1.0-0{a} libpango1.0-common{a}
libpci3{a} libpixman-1-0{a} libpng12-0{a} libpulse-browse0{a}
libpulse-mainloop-glib0{a} libpulse0{a} libpulsecore5{a} libraw1394-8{a}
librsvg2-2{a} librsvg2-common{a} libsamplerate0{a} libsexy2{a} libsm6{a}
libsmbios-bin{a} libsmbios2{a} libsndfile1{a} libsplashy1{a}
libstartup-notification0{a} libthai-data{a} libthai0{a} libtheora0{a}
libtiff4{a} libts-0.0-0{a} libvoikko1{a} libvorbis0a{a} libvorbisenc2{a}
libwnck-common{a} libwnck22{a} libx86-1{a} libxcb-render-util0{a}
libxcb-render0{a} libxcomposite1{a} libxcursor1{a} libxdamage1{a}
libxfixes3{a} libxft2{a} libxi6{a} libxinerama1{a} libxrandr2{a}
libxrender1{a} libxres1{a} myspell-en-us{a} notification-daemon{a}
padevchooser{a} paman{a} paprefs{a} pavucontrol{a} pavumeter{a}
pciutils{a} pm-utils{a} powermgmt-base{a} psmisc{a} pulseaudio
pulseaudio-esound-compat{a} pulseaudio-module-gconf{a}
pulseaudio-module-hal{a} pulseaudio-module-x11{a}
pulseaudio-module-zeroconf{a} pulseaudio-utils{a} radeontool{a}
ttf-dejavu{a} ttf-dejavu-core{a} ttf-dejavu-extra{a} ucf{a} uswsusp{a}
vbetool{a} x-ttcidfont-conf{a}
なんてことだ。一瞬Xでもインストールされるのかと思ったが、それだったら152個では済まない。一応確認してインストール。
そして、/etc/pulse/default.paの編集。
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.0.0/24
上記の一行を入れる(実際の追加は太字のみ)。LAN内からのアクセスを許可。
自分のユーザの準備
# usermod -G pulse,pulse-access,pluse-rt toshi
-- 再ログイン --
$ pulseaudio -D
なぜか起動しない。
いろんな文献を漁っていると、どうやらpulseaudioを使っている人はalsaも入れている。とりあえず入れてみた。
# aptitude install alsa-base alsa-utils alsaplayer alsa-conf
この後、なぜかサウンドカードが3つ(!?)検出されたり、/dev/dspが無くなって大変だった。
現在の状況は、なんとか/dev/dspが復活し、echo mikumiku > /dev/dspとかすると音が鳴るようになった。だけど、alsaplayerやpulseaudioを立ち上げると、その瞬間固まる。サーバにキーボードを直接つないでも反応はなく、サービスももちろん反応しない(Webサーバなんだけどな、一応)。でもなぜかalsamixerで音量変えたりは出来る。軽く乗ってるノイズの音量も変わってるし、/dev/dspに直接書き込んだら音鳴ってるし。
解決方法が分かったら書きます・・・。

↓今開いてるタブ

http://d.hatena.ne.jp/kakurasan/20081212/p2
http://d.hatena.ne.jp/kakurasan/20080905/p1
http://mlog.euqset.org/archives/debian-users/43288.html
http://pulseaudio.org/wiki/CLI
http://hide-t.vox.com/library/post/colinx%E3%81%A7pulseaudio.html
http://www1.tcnet.ne.jp/fmurata/linux/alsa.html

2009年3月3日火曜日

動画からMP3を抜き出す

よくやることだけど、形式によってやりかたがまちまちで困る。そこで、こんなスクリプトを書いた。
#! /usr/bin/perl

if($ARGV[0] =~ /\.swf$/){
system("swfextract -m $ARGV[0] -o $ARGV[0].mp3");
}
elsif($ARGV[0] =~ /\.(flv|mp4)$/){
system("ffmpeg -i $ARGV[0] -acodec copy $ARGV[0].mp3");
}
else{
print "なにこれぇ?"
}
これをnautilus-scriptsのディレクトリ(~/.gnome2/nautilus-scripts)に保存すると、右クリックで抜き出せる。swf, flv, mp4に対応している。
動画の整理はnautilusでサムネイルを見ながらやるから、それだったら抜きだしもnautilusからやったほうが直感的で楽なのでは、と思って作った。意外と、形式を気にせずに抜き出せるので重宝している。
ちなみに、正常に動かすためには
# aptitude install ffmpeg swftools
と実行して、必要なコマンドをインストールする必要がある(Ubuntu)。

2009年2月27日金曜日

Emacs22の文字コード判別の頭が悪い

Emacs22から文字コードの判別にmule-ucsを使わなくなり起動が早くなったらしいが、そのせいで時々文字コードを間違えるようになったみたいだ。
写真は、二行目に「初音ミク」と書いてutf-8で保存されたものを開いた時のスクリーンショット。ステータス行を見ると、Shift-jisと誤認していることがわかる。こういう時は、C-x RET c utf-8-unix RET C-x C-v RETとタイプすればUTF-8で開き直せるが、あまりにも長すぎる。
以下のような行を入れておくことで、そのファイルの文字コードを指定できる。
# -*- coding:utf-8 -*-
(#はコメント。言語に合わせてセミコロンなどでも良)
これがファイル内にあれば、utf-8でファイルを読み込んでくれるようになるのだが、いちいち全部のファイルにこれを書くわけにはいかないし、何より読み込んでからでは遅い。

coding-category-listという変数の中に、文字コードの優先順位が書いてあり、先頭のほうが優先順位が高い。
coding-category-list
=> (coding-category-iso-8-2 coding-category-iso-7-tight coding-category-sjis coding-category-iso-7-else coding-category-iso-8-1 coding-category-utf-8 coding-category-utf-16-be coding-category-utf-16-le coding-category-iso-7 coding-category-iso-8-else coding-category-emacs-mule coding-category-raw-text ...)
確かに、coding-category-utf-8より前にcoding-category-sjisがある。
この優先順位を上げてやるといいらしい。以下の式を評価してから、問題のテキストファイルを開く。
(prefer-coding-system 'utf-8-unix)
=> (mule-utf-8 . mule-utf-8)
図のように、無事にutf-8と認識するようになったので、これを~/.emacs.my.elに追記しておく。
どうやら、coding-category-listを最初から順番に試していって、最初にファイル内全てを文字として表現できたものを問答無用で使うようになっているらしい。

# しかし、初音ミクで化けるとは・・・。

2009年2月25日水曜日

横道に逸れるのが常

最近、Webページをリニューアルしようとしているのだが、フレームワーク癖がついてしまったのか、知らないうちに、ViewとかControllerなどというクラスを作ってしまっている。どうせだから、Modelも作って本当にフレームワークもどきにしてもいいかもしれない。

頭の中を整理するために、今のところの仕様を書く。

Model
  • クラス名: Model::NameOfModel(単語の先頭大文字)
  • スーパクラス: Model::Base
  • ソースディレクトリ: /model/name-of-model.rb
  • データベースには、KirbyBaseを使おうかと考えている。

View
  • クラス: View
  • ソースディレクトリ: /view/name-of-controller/name-of-view.rhtml
  • ERubyを使って実装。
  • 結果はStringで変数content_for_layoutに代入され、レイアウトに渡される。

Controller
  • クラス名: Controller::NameOfController(単語の先頭大文字)
  • スーパクラス: Controller::Base
  • ソースディレクトリ: /controller/name-of-controller.rb

あんまり本格的にRubyのクラスとか叩いたことがなかったので、「Stringに代入されているクラス名からクラスのインスタンスを作る」とか「ハッシュに含まれるキーを変数名、値を変数の値としてもったBindingオブジェクトを生成する」といった、普段やらないような、知ってるとちょっと役に立ちそうなことがいろいろわかってよかった。
もうやめたけど、一瞬ArrayをスーパクラスとしてController::Baseを定義していたのは内緒。

※それにしても、ひどいサイト名だな

2009年2月23日月曜日

VMWareでVMNet2とかを使う

仮想マシンにDebian etchを入れて、Webページのテストなどに使っているのだが、VMWareが提供するネットワークインタフェイスvmnetXが無くなった。うまく対処する方法はあったかもしれないが、以前インストールしたときのファイルが残っていたので、再インストールした。
#./install.pl
関係ないけどこれ、対話型なのがなんだか気にくわない。GUIになってるなら話は分かるけどCUIだし。
エンターを連打していたらVMNet8のネットワークアドレスが変わってしまった。設定を無理やり書き換えてもうまく行かなかったので、今回は今後のことも考えて別のインタフェイス、vmnet2を作っておく。

# /usr/bin/vmware_config.pl

これも対話型なのですぐにクリア。
しかし、このままだとVMnet8で通信して、VMNet2を使ってくれない。

そこで、仮想マシンの設定ファイル、拡張子が.vmxのファイルを編集する。
ethernet1.present = "TRUE"
ethernet1.connectionType = "custom"
ethernet1.vnet = "vmnet2"
ethernet1.addressType = "generated"
上記4行を追加する。これで、VMNet2がゲストOSではeth1として認識される。

こうやって別のネットワークにしておけば、セキュリティ対策にもいいかもしれない。

2009年2月19日木曜日

IEのCSSバグ回避

今日やたらとIEのいい加減なCSS対応に苦しめられたので、回避法をメモ。

参考 : http://journal.mycom.co.jp/special/2007/ie7/015.html

*html body a{ IE6以下(バグ利用) }

IE5以下に対応しなければならないことは最近減ったので、実質6のみで使ってる。
6はまともにCSSを読めないので、このハックはかなり使ってる。

*:first-child+html a{ IE7のみ(セレクタバグ利用) }

IE7はマトモになったけど、まだバグが拭いきれていないので、時々。

html > body a{ IE6以外 }

あんまり使いどころがないけれど・・・。
*html bodyの論理否定版とでもいおうか。IEで開発してFxに合わせるとかいう開発スタイルの人にはいいかも。そんな人いるのかなぁ。

html[xmlns]>/**/body a{ IE以外 }

上記と似たようなかんじ。いろいろ試行錯誤してると、これをつかった方法に落ち着くことが前はあった。
最近なれてきてしまってこういうの使わない。

今、IEのみに適応できるスマートな方法を探してるんだけど、ないのだろうか・・・。
あと、すごく単純な作業なので、CSSパーサを書けば、勝手にIE対応にしてくれるジェネレータとか作れそう。IEが生きてるうちに作れたら面白そうだけど・・・。

2009年2月18日水曜日

screen便利かもしれん


gnu screenっていうのは便利だね。
なぜ今まで知らなかったのか。

screenのショートカット

^z c - 新規ウィンドウ
^z SPC - 次のウィンドウ
^z NUM - NUM番のウィンドウ
^z S - 分割
^z TAB - 切り替え

ステータスラインにウィンドウリストを表示する
~/.screenrc (追加)
hardstatus alwayslastline "[%02c]%`%-w%{=b bw}%n%t%{-}%+w"
参考サイト http://d.hatena.ne.jp/zenpou/20080117/1200539192

ウィンドウ名を最後に実行したコマンドにする(zsh)
~/.zshrc (追加)
function preexec(){
if [ $TERM = "screen" ]; then
1="$1 " # deprecated.
echo -ne "\ek${${(s: :)1}[0]}\e\\"
fi
}
参考サイト http://d.hatena.ne.jp/zenpou/20080117/1200539192