Bash, Perl, Ruby, Pythonで正規表現置換

前回のC++/boost.NETに加え、各種インタプリタ言語でも同じ動作をするスクリプトを書いてみました。

シェルスクリプト(bash)

シェルスクリプトはそもそもグルー言語ですので、他のコマンドを呼び出して処理をすることが一般的です。下のサンプルではsedコマンドで置換処理をしています。bashだと正規表現マッチングは可能なので、ガリガリとスクリプトを書けばsedを使わずに実現できるかもしれません。

[bash]

!/usr/bin/env bash

[ $# -ne 2 ] && exit 1
cat | sed -e "s/$1/$2/g"
exit 0
[/bash]

リプレイスメント置換文字は、sedの書式になります。グループ指示子はダラー($)ではなくバックスラッシュ(\)を用いています。

Perl

Perlの場合、正規表現による文字列操作は、関数でもクラスでもなく構文として組み込まれています。その為、コマンドライン引数から渡された「$1」のようなリプレイスメントの展開方法に、若干の工夫が必要です。

[perl]

!/usr/bin/env perl

exit 1 if ($#ARGV != 1);
for (<stdin>) {
eval "s/$ARGV[0]/$ARGV[1]/g" && print;

s/$ARGV[0]/$ARGV[1]/gee && print; # これではダメ

}
exit 0;
[/perl]

リプレイスメントが格納されている$ARGV[1]は展開されると、例えば「$1$2」という文字列になります。この展開後の文字列をリプレイスメントとして正規表現置換の処理に投げたいのですが、正規表現置換処理を行なった後に変数展開されるようでリプレイスメントのグループ指示子としての$nが正規表現置換処理に伝わりません。そこで、正規表現置換処理を行う前に$ARGV[1]を展開させるべく、eval関数に投げています。これにより、正規表現置換処理が評価される時点でリプレイスメントは「$ARGV[1]」ではなく「$1$2」という文字列として解釈され、指示子が正しく伝わるようです。
検索パターンに加え、リプレイスメント文字列も変数で持つという処理は多々あるはずなので、もっとスマートな方法が準備されているのかもしれませんが、性質さえ知っていれば公式を知らずとも期待する処理が可能である、まさに”TMTOWTDI / There’s More Than One Way To Do It(やり方はひとつじゃない)”という設計思想を持つPerlらしい実装です。理に適った挙動は見ていて気持ちがいいです。

Python

Pythonでは、シェルスクリプトやPerlと違って正規表現機能はクラス(re)として提供されています。下のサンプルではreの静的関数を叩いていますが、プリコンパイルしたオブジェクトとしても利用できたと思います。

[python]

!/usr/bin/env python

import sys
import re
v = sys.argv
if len(v) != 3: quit(1)
for line in sys.stdin:
print re.sub(v[1], v[2], line),
quit(0)
[/python]

リプレイスメントのグループ指示子は、sedと同じくバックスラッシュです。Cやシェルライクなエスケープ文字という捉え方をするなら、バックスラッシュがしっくり来ますね。(といっても、ダラーの場合でも同じく「シェルライク」ですけど :D )

ちなみに、len() がオブジェクトのメソッドではなく独立した関数になっているのは、評価対象(上の例の場合は v )が null オブジェクトでも、null チェックなしで利用できるようにする為だとどこかで読みました。Python の場合は空文字列(len=0)は null オブジェクトになるんですね。

Ruby

Rubyの場合は、シェルスクリプトを除いた他のどの言語よりもマニアックな感じがしますが、よく見てみると一番「ナチュラル」に理解し易い構文です。これだけの構文で比較するのはアレかもしれませんが、これだけの構文だけでここまで革新的な要素をたくさん見てとれるのは、rubyだからこそと言った感じでしょうか。ファイルディスクリプタまでオブジェクトであり、イテレータをせおっているあたり、カワイイです。

[ruby]

!/usr/bin/env ruby

if ARGV.size != 2 then exit 1 end
STDIN.each_line do |line|
puts line.gsub(/#{ARGV[0]}/, ARGV[1])
end
exit 0
[/ruby]

Rubyの何十倍もPythonのコードは書いていますが、Pythonは「VB.NETよりも使いものになる、綺麗なVB.NET的な何か」というイメージが拭えません。いいところ、悪いところの両方を知った上で使いこなせていけたらいいなあ、と思いました。

See also

.NETで正規表現ライブラリを使う

前回のboostの正規表現ライブラリのサンプルに引き続き、C#とC++/CLI、VB.NETでも同じサンプルを書いてみました。全て.NET FrameworkのSystem.Text.RegularExpressions.Regexを用いています。

なんてことはありませんね。

C#版

こちらはMono 2.6.7環境のmcs/gmcsでビルドしてチェックしました。

[csharp]
using System;
using System.Text.RegularExpressions;

// usage: a.exe pattern replace-to

public class Program
{
static int Main(string[] v)
{
if (v.Length != 2) return 1;

Regex r = new Regex(v[0]); // 正規表現オブジェクト
string buf;                // 読み取り用のバッファ

while ((buf = Console.ReadLine()) != null)
  Console.WriteLine(r.Replace(buf, v[1]));

return 0;

}
}
[/csharp]

C++/CLI版

C++/CLIはオープンソースなコンパイラが存在しないため、Microsoft Visual Studio 2008 SP1を用いてビルド、チェックしました。

[cpp]
using namespace System;
using namespace System::Text::RegularExpressions;

// usage: a.exe pattern replace-to

int main(array<System::String ^> ^v)
{
if (v->Length != 2) return 1;

Regex^ r = gcnew Regex(v[0]); // 正規表現オブジェクト
String^ buf;                  // 読み取り用のバッファ

while ((buf = Console::ReadLine()) != nullptr)
    Console::WriteLine(r-&gt;Replace(buf, v[1]));

return 0;

}
[/cpp]

VB.NET版

ついでにVB.NET版も。これもMonoのvbncでテストしました。

[vb]
Imports System
Imports System.Text.RegularExpressions

Module Program

Public Sub Main(ByVal v() As String)

If v.Length &lt;&gt; 2 Then Exit Sub

Dim r As New Regex(v(0)) ' 正規表現オブジェクト
Dim buf As String        ' 読み取り用のバッファ
buf = Console.ReadLine() ' 代入結合判定できないので
                         ' 予め内容を詰めておく。

While buf &lt;&gt; Nothing
  Console.WriteLine(r.Replace(buf, v(1)))
  buf = Console.ReadLine()
End While

End Sub

End Module
[/vb]

1979年のOS『Version 7 UNIX』を使う

Version 7 UNIXとは、DECのPDP-11で動いていたUNIXです。AT&Tベル研究所製の初期のUNIXシリーズの直系のバージョンで、1979年にリリースされました。

V7は現在、フリーソフトウェアとして公開されており、こちらからブートイメージを入手することができます。また、x86への移植活動もあり、VM用のディスクイメージが公開されていたりします。

古いUNIXを触ってみたくなったので、古いハードウェアをシミュレートしてくれるエミュレータ simh を導入して遊んでみることにしました。

下準備

まずは必要なものを揃えます。simh は、dpkg系のパッケージ管理システムを採用しているディストリビューション上で次のようにしてインストールします。

$ sudo aptitude install simh

次に、V7のイメージをダウンロードし、解凍しておきます。

$ mkdir /tmp/v7
$ cd /tmp/v7
$ wget http://ftp.fibranet.cat/UnixArchive/PDP-11/Boot_Images/v7_rl02_1145.gz
$ gunzip v7_r102_1145.gz
$ ls
v7_rl02_1145
$

設定

V7用の設定ファイルを書きます。

$ cat > uv7
set cpu 11/45
set rl0 RL02
att rl0 v7_rl02_1145
set rl1 RL02
att rl1 rl1.dsk
att tm0 tm0.tap
boot rl0
$

4行目の最後のカラムに書いている「v7_r102_1145」は、ダウンロードして解凍したV7のディスクイメージです。

実行

さっそく実行してみます。ホスト側とゲスト側を区別する為、ホスト側には「host$」プロンプトを用います。

host$ pdp11 uv7

PDP-11 simulator V3.8-1
Disabling XQ
Overwrite last track? [N]
@

最後のトラックを上書きするか?と聞かれましたが、とりあえず標準の「N」と答えておきました。この「@」プロンプトの場面はきっとPDP-11の組込みブートローダなんでしょう。ブートします。

@boot
New Boot, known devices are hp ht rk rl rp tm vt
:

ブートデバイスを聞いてきますので、次のように入力します。

rl(0,0)rl2unix
mem = 177856
#

プロンプトが「#」に変更され、シングルユーザモードでV7が使えるようになりました。ここで、C-dをタイプしてマルチユーザモードに移行します。

Restricted rights: Use, duplication, or disclosure
is subject to restrictions stated in your contract with
Western Electric Company, Inc.
Thu Sep 22 05:50:55 EDT 1988

login:

見慣れたログイン画面が登場しました。とりあえずrootでログインします。パスワードは「root」です。

login: root
Password:
You have mail.
#

無事、ログインすることができました。

シェルの使い方

stty
speed 300 baud
erase = ‘#’; kill = ‘@’
even odd -nl echo -tabs

sttyコマンドを実行してみると、古いUNIX入門の本にあるように、訂正は「#」記号、破棄は「@」記号にバインドされているようです。
バックスペースなどはかなり基本的な画面制御文字だと思うんですが、テレタイプ端末も現役で動いていた当時の事情を考えると、ビデオ表示端末のような書き換え可能な表示媒体をもつデバイスにしかできない「バックスペース」ではなく、より多くのデバイスに可能な「#」による訂正の方が都合が良かったんでしょう。
実際にタイプした文字を訂正するには、以下のようにします。

la#s

これは「ls」を間違って「la」とタイプしてしまったので、「#」で直前の1文字を訂正して、正しい「s」をタイプしたところです。「la#s」でシェルには「ls」と解釈されます。また、

pqd##wd

「pwd」を「pqd」とタイポした場合、「##」で2文字訂正して、正しい「wd」をタイプすることにより、「pwd」と解釈されています。

現在の入力を全て破棄するには、

asdf@

のように、「@」記号を用いれば破棄されて新しいプロンプトに移ります。

終了

haltもshutdownコマンドも入っていない為、simh側から終了させます。ファイルシステムに変更を加えた場合、デバイスとの同期をとるためにsyncコマンドを打ちます。

sync;sync;sync

# 次に、C-eをタイプしてsimhのコンソールに移行します。

Simulation stopped, PC: 002306 (MOV (SP)+,177776)
sim> exit
Goodbye
host$

ここで、「exit」とタイプすると終了することができます。

man pageを見れるようにする

初期状態では/tmpが存在しない為、manページを表示しようとすると次のように怒られます。

man sh
Cannot create temp file.

そこで、/tmpを作成しておきましょう。

mkdir /tmp
chmod 777 /tmp
man sh

これでmanページが見れるようになりますが、ページャが入っていません。やはりビデオ表示端末向けのツールは、まだ充実していないようですね。

ユーザの追加

初期状態では、ユーザ情報は次のとおりになっています。

cat /etc/passwd
root:VwL97VCAx1Qhs:0:1::/:
daemon:x:1:1::/:
sys::2:2::/usr/sys:
bin::3:3::/bin:
uucp::4:4::/usr/lib/uucp:/usr/lib/uucico
dmr::7:3::/usr/dmr:

シャドウ・パスワードが登場する前なので、/etc/passwdに素直に(ハッシュ化された)パスワードが記載されていますね。7行目の「dmr」というユーザ名は、先日逝去されたUNIXの開発者デニス・リッチー博士の愛称です。実際に運用されていた頃からデフォルトで入っていたのかもしれませんが、そうでなくとも、フリーソフトとして公開される際に、彼に敬意を称して追加されたのかもしれません。

`echo dyama::8:3::/usr/dyama: >> /etc/passwd`

畏れ大くも、dmr博士の次にアカウントを追加してみました。さらにホームディレクトリも設定します。

cd /usr
mkdir dyama
chown dyama dyama
ls -l
total 11
drwxrwxr-x 3 bin 128 Sep 22 05:45 dict
drwxrwxr-x 2 dyama 32 Sep 22 06:18 dyama
drwxrwxr-x 5 bin 416 Sep 22 05:46 games
drwxrwxr-x 3 sys 496 Sep 22 05:42 include
drwxrwxr-x10 bin 528 Sep 22 05:43 lib
drwxrwxr-x11 bin 176 Sep 22 05:45 man
drwxrwxr-x 3 bin 208 Sep 22 05:46 mdec
drwxrwxr-x 2 bin 80 Sep 22 05:46 pub
drwxrwxr-x 6 root 96 Sep 22 05:45 spool
drwxrwxr-x13 root 208 Sep 22 05:42 src
#

当時のファイルシステム階層では、ユーザのホームディレクトリは/homeではなく、名前のとおり/usrに格納されていたと古い本で読みました。慣例に習って設置しました。

一度、C-dをタイプしてログアウトします。

#
login: dyama
$

「login:」と出てきたので、先ほど追加したユーザ名「dyama」をタイプします。パスワードを設定していない為、聞かれることなく一般ユーザプロンプト「$」が表示されました。
エミュレータ上のアカウントなのでこのままでもいいんですが、とりあえずパスワードを設定します。

$ passwd
Changing password for dyama
New password:
Retype new password:`

これでパスワードが変更されたはずです。試しに「hogehoge」と入力しています。

$ su
Password:
cat /etc/passwd | grep dyama
dyama:7N.C0KCSdg3aI:8:3::/usr/dyama:
#

パスワードカラムに、ハッシュ化されたパスワード文字列が追加されたことが分かります。

Cプログラムを書いてみる

ccが入っていますので、C言語でプログラムを組むこともできます。ビジュアル・エディターが入っていない為、catコマンドで標準入力からダイレクトにファイルを書いていきたいと思います。

先に述べましたとおり「#」記号が訂正にバインドされているので、まずは#を正しく入力できるように設定を変更してあげます。

$ stty erase ?
$ stty
speed 300 baud
erase = ‘?’; kill = ‘@’
even odd -nl echo -tabs
$

sttyコマンドで訂正を「#」から「?」に変更しました。続いてコーディングです。

$ cat > test.c
#include
int main()
{
printf(“hello, world\n”);
return 0;
}
$ cat test.c
#include
int main()
{
printf(“hello, world\n”);
return 0;
}
[/bash]

コーディングができたら、catで確認してみてください。訂正が「?」になっていれば、プリプロセッサの「#include」は正しく入力できているはずです。

$ stty erase #
$ stty
speed 300 baud
erase = ‘#’; kill = ‘@’
even odd -nl echo -tabs

忘れないうちに訂正を「#」に戻しておきます。
あとは、ccコマンドでコンパイルを行なって出力されたファイルを実行します。

$ cc test.c
$ ls
a.out
test.c
$ ./a.out
hello, world
$

上記のように「hello, world」が表示されたら成功です。

boostの正規表現ライブラリを使う

boostの正規表現ライブラリ boost::regex を使ったサンプルです。
boost::regex は以下のコマンドでインストールすることができます。

[bash]
$ sudo aptitude install libboost-regex-dev
[/bash]

サンプル regextest.cpp を準備します。これは正規表現リプレイサです。

[cpp]

include <iostream>

include <string>

include <boost/regex.hpp>

// usage: a.out pattern replace-to

using namespace std;

int main(int c, char** v)
{
if (c != 3) return 1;

boost::regex ex(v[1]); // 正規表現オブジェクト
char buf[256];         // 読み取り用のバッファ

while (cin.getline(buf, sizeof(buf)))
cout << boost::regex_replace(string(buf), ex, v[2]) << endl;

return 0;
}
[/cpp]

ビルドします。

[bash]
$ g++ -lboost_regex regextest.cpp
[/bash]

実行します。

[bash]

先頭の二文字を入れ替える

$ ls / | ./a.out ‘^(.)(.)’ ‘$2$1’
ibn
obot
edv
tec
ohme
niitrd.img
ilb
olst+found
nmt
pot
rpoc
orot
bsin
eslinux
rsv
yss
mtp
sur
avr
mvlinuz
[/bash]

簡単ですね。

タバコ用に空気清浄機を購入

部屋でタバコを吸う時は、基本的に窓を開けて吸っているのですが、ここのところ涼しくなってきたのもあり、思いきって空気清浄機を購入しようと思いました。冬になってくると、どうしても換気が悪くなってきて、室内でタバコを吸っていると煙たくて仕方ありません。自分が不快にならない程度でも、ディスプレイやキーボード、壁やカーテンなどがヤニに侵されていきます。ヤニは嫌だけど、タバコをやめるには時間がかかる…ということで、決心に至りました。マトモな空気清浄機を購入するのは今回が初めてです。

さて、さまざまな通販サイトで確認してみるも、いわゆる「タバコ専用」を謳ったものってなかなか少ないようですね。喫煙人口がまだまだ多い日本だと、需要もありそうなんですが、煙ほど濃い「悪い空気」はガッツリした機械じゃないと清浄できないんでしょうか。まあ、何十万円もする業務用の大型のものなら、タバコ専用のようなものもあるようですが、そこまでお金は出せません。

ということで、一般向けの低価格な空気清浄機で代用することになりました。マイナスイオンが出る、とか保湿機能がある、とか静音タイプだとか、いろんな機能を備えたものがありますが、「タバコの煙をガンガン吸うよ!パワフル!」というものはやっぱりありません。

どこかのレビューで「前面の全面に吸い込み口があるもの、急速清浄モードがあるものがタバコ用には良い」という情報があったのでそれを基に、AmazonでZOJIRUSHIの空気清浄機 PA-HA16-WBを購入してみました。据置き型の空気清浄機にしては安い価格帯のものだと思います。

自分はよくベッドの上でゴロゴロしながらラップトップを扱い、タバコを吸うので、枕元に設置してみました。ちょうど良い高さで吸引してくれます。空気清浄機の前面から20~30センチメートルまでタバコを近づけないと吸引してくれませんが、自宅に居る時の半分は空気清浄機の前だし、なかなか効果がありそうです。口から吐く煙も、意図的に空気清浄機に向けて拡散してしまわないように心掛けて使っています。また、空気の汚れ具合をセンサーで検知するモードがありますので、タバコを吸い始めたら自動的に急速清浄モードになってぐんぐん吸い込んでくれて結構助かります。

数万円台の空気清浄機でも、部屋ひとつ清浄するのに30分とか1時間とかかかるのが普通みたいなので、この値段でこれだけの働きをしてくれるっていうのは、個人的に満足でした。

茶の間用にもう一台購入するかもしれません。

日本通信 IDEOS 200日パッケージを購入

Amazon.co.jpで「IDEOS+U300の200日パッケージ」を購入しました。
日本通信(b-mobile)が提供しているIDEOSというAndroid端末とU300というモバイルデータ通信用SIMカードのセットです。送料無料で17,998円でした。

ちょっとばっかしレビュー、というか感想を書いておきます。

コストについて

200日使えるU300のSIMカードが同梱されているパッケージなのですが、日本通信の公式サイトで、そのSIMカードが365日使えるというキャンペーンをやっていました。
丸1年使えるということは、月あたりのランニングコストは約18,000円÷12ヶ月=1500円。Yahoo!オークションでのIDEOSの相場は現在、5,000円前後ですので、内訳は通信費1083円・端末代417円といったところでしょうか。日本通信が出していた旧パッケージ品だと、今でも20,000円以上するものも流通しています(計算にならない)。
通信速度は理論値300kbpsと貧弱なものの、メールとちょっとした調べもの用途では不自由しません。やはり月1000円ちょっとでモバイルデータ通信が使い放題というのは、かなり魅力的です。

U300のSIMでは、電話回線を用いた音声通話はできない為、auのガラケー(W63CA)を電話専用機として運用しています。こちらの契約もデータ通信関連のプランを全て解約している為、基本料金・月1200円程度で運用できています。私はあまり通話発信をしない為、毎月ついてくる無料通話分の範囲内に収まっているようで、今年になってから月1200円以上請求されたことがありません。

端末の2台運用となりますが、電話代1200円+データ通信費1500円(端末代込み)=月2700円にまで抑えて運用できるようになりました。年間の費用に換算すると32,400円です。
auと電話もデータ通信も契約していた頃は、月に7500円(端末のローンを入れると毎月1万円以上)ほど支払っていたので、年間だと90,000円という計算になります。
差は60,000円弱で、なかなか大きいですね…。

端末について

中国の通信機器メーカー華為技術有限公司(Huawei)製です。Android2.2、現在の他社のスマートフォンの性能に比べると低スペックな部類に入りますが、なかなかコンパクトであり、筐体も安物っぽさはありません。
コンパクトなAndroid端末というのは、手にしてみて実感したのですが、かなり使い易いです。私の場合、スマートフォンが主力のネットワーク・デバイスとはなり得ないので、IDEOSに動画の表示性能やウェブブラウジングの快適さを求めていません。もちろん、何でも快適にできるにこしたことはありませんが、スマートフォンの環境を快適にする為に大きなお金をつぎ込むくらいだったら、極端に安いコストで割り切って使う方が魅力的に感じました。「動画?それならスマホじゃなくて、パソコンでフルHDで見るわ」的な考え方ですよね。費用対効果に加え、片手で操作できるコンパクトな筐体っていうのは思いがけない嬉しさでした。

回線について

U300のSIMカードは、通信速度を最大300kbpsに制限しています。ドコモのFOMA回線を利用しています。回線自体はもっと太いから、実ハードウェアの理論値300kbpsに比べたら効率いいのかな、と素人予想。

普段のライフスタイルにも大きく影響するところですが、私の場合、自宅も職場もインターネットに接続されたWiFi環境が整っています。WiFiとWiFiの切れ間だけ、データ通信回線が利用できれば十分ですし、そのタイミングで大量の通信が発生するような利用の仕方はありません。300kbpsという貧弱な回線でもメールならば十分です。

SkypeやLINEといったデータ通信回線を使った音声通話も一般化して久しいですが、果たして月1200円で維持しているauの電話回線と比べていかがなものか、と考えてしまいました。同じ値段を支払ってデータ通信回線速度を増強しても、つながりやすさとか品質、万が一の時に使えるかどうか、などいろいろ疑問点が残ります。
こういう書き方をすると疑っているように見えますが、単に知識がないだけですので、機会があれば検証してみたいなあ、と思うところです。

その他、メリット

IDEOSはSIMロックフリー、テザリングが一般化する前から公式サポートしていた数少ない機種の一つでもありました。これで、出先でラップトップや他のモバイル端末からインターネットに接続したり、自宅サーバにログインすることができます。

OpenCASCADEで曲線同士の交点計算

Open Cascadeを用いて三次元曲線同士の交点を求めるには、GeomAPIのExtremaCurveCurveを利用します。このエクストリーマクラスは、交点を求める為のクラスではなく、曲線同士の、それぞれ相手との最寄りの点を求める為のクラスです。お互いの最寄りの点が同一点であれば、そこが交点として扱うことができます。

ソースコード

[c]

include <stdio.h>

include <TopoDS_Edge.hxx>

include <BRep_Tool.hxx>

// TKBinL … 明示的にリンクしてやる

include <BRepBuilderAPI_MakeEdge.hxx>

// TKGeomAlgo

include <GeomAPI_ExtremaCurveCurve.hxx>

int main(void)
{
// カーブパラメータの受け取り用
Standard_Real _first, _last;

// エッジ(線分)からカーブを作成
TopoDS_Edge e1 = BRepBuilderAPI_MakeEdge(
gp_Pnt(0, 0, 0), gp_Pnt(10, 0, 0));
Handle(Geom_Curve) c1 = BRep_Tool::Curve(e1, _first, _last);

// もう一つ作成
TopoDS_Edge e2 = BRepBuilderAPI_MakeEdge(
gp_Pnt(4, -5, 0), gp_Pnt(6, 5, 0));
Handle(Geom_Curve) c2 = BRep_Tool::Curve(e2, _first, _last);

// エクストリーマに2つのカーブを入れる
GeomAPI_ExtremaCurveCurve ecc;
ecc.Init(c1, c2);

// 各々の最寄り点を得る
gp_Pnt p1;
gp_Pnt p2;
ecc.NearestPoints(p1, p2); // アドレス参照で受け取り

// 得た点が同一点なら、そこが交点。第2引数はトレランス値。
if (p1.IsEqual(p2, 0.001))
printf("p=(%f, %f, %f)\n", p1.X(), p1.Y(), p1.Z());

return 0;
}
[/c]

ビルド

ビルドオプションは次のとおり。これらのライブラリ以外にもリンクしますが、下記のオプション指定だけで適当に解決してくれます。

[bash]
g++ -g -o hoge -I/usr/include/opencascade \
-lTKernel -lTKMath -lTKBinL hoge.cpp
[/bash]

実行すると、次のように交点の座標を印字します。

[bash]
$ ./hoge
p=(5.000000, 0.000000, 0.000000)
[/bash]

  • 延長線上の交点について
  • 交点が複数ある場合

mumble VoIP サーバをインストール

mumbleとはBSDライセンスで提供されているVoIPクライアント・サーバアプリケーションです。VoIPクライアントとしては、米マイクロソフト社が昨年買収した『Skype』、韓国NHN社の日本法人NHN Japanが提供している『LINE』などが国内では有名ですが、mumbleはこれらサービスとは違ったアプローチのもと提供されています。

オンラインゲーム、特にリアルタイム性が求められるFPS(銃を打ち合って戦争するゲーム)使用中に利用することを想定としている為、重点を置いているところが違います。

  1. 常駐させても負荷が少なく、軽い。
  2. 音質をそこそこ維持しつつ、遅延が少なくするように設計されている。
  3. 連絡を取り合うことに特化されていて、余計な機能がない。
  4. 帯域や通信速度自体が制限されたナローバンドでも使える(らしい)。

VoIPクライアントの本質は「IPネットワーク網を利用した音声通信」ですので、正直なところ、他の機能は要りません。また、上記に挙げたVoIPクライアントとしてのメリットの他に

  1. オープンソースであり、特定企業の商売戦略上の都合に巻き込まれなくてすむ。
  2. サーバさえも自分で用意することができ、その気になれば何十年でも同じ環境が使える。
  3. クライアントはLinux、Windows、Androidなどで使用でき、サーバはLinux、Windowsで実行できる。

これらはmumbleに限らずオープンソースプロジェクト全体に言える話ですが、こういう通信手段このその利点が大きいんじゃないかなって思います。IRCもそうですが、コミュニケーションツールはライフラインの一つにも挙げられる時代ですから、自前で面倒が見られるようにしておきたいものです。また、自分だけで利用するシステムではないので、Linuxはもちろん、Windowsやスマートフォンから利用ができる点も大きなメリットです。

サーバのインストール

dpkg系のパッケージ管理システムを採用しているディストリビューションでは、例のごとく、APTにてインストールすることができます。私のDebian環境では、通常のリポジトリ内で見つけることができました。

[bash]$ sudo aptitude search mumble
p mumble – Low latency VoIP client
p mumble-11x – Low latency VoIP client (1.1.x)
p mumble-dbg – Low latency VoIP client (debugging symbols)
p mumble-django – A Mumble-Server web interface
p mumble-server – Low latency VoIP server
p mumble-server-web – Web scripts for mumble-server
p python-django-mumble – A Mumble-Server config application for Django
[/bash]

サーバにはクライアントをインストールする必要はないので、「mumble-server」だけをインストールします。

[bash]
$ sudo aptitude install mumble-server
[/bash]

何もエラーが発生しなかったら、mumbleサーバのインストールは正常に終わったということです。

サーバの実行

インストール時に自動実行されないので、手動で実行します。

[bash]$ sudo /etc/init.d/mumble-server start
$ sudo lsof -i TCP | grep murmurd[/bash]

2行目を実行してみて、murmurd(mumble-server)が出てきたら動いてます。
さて、早速クライアントから接続してみます。クライアントの設定はLinux/Windows/Androidとそれぞれちょっとずつ違うので、ここでは触れません。
mumble-serverの標準リスンポートは64738ですので、それを参考に設定してみてください。

[bash]
$ sudo tail -f /var/log/mumble-server/mumble-server.log
[/bash]

NEC LaVie LightのUbuntuをアンインストール

先日、実家に帰った際、妹がパソコンを欲しいと言ってきたので、それならばと以前メインで使っていたネットブックをお下がりすることにしました。

ネットブックは NEC LaVie Light BL330。タブレットPCが流行する前の、各社が競ってネットブックを出していた頃の機種です。当時の Microsoft の OS 提供ライセンスの関係に基づいてハードウェア仕様に制限をかけてあるらしいので、当時としてもあまり高いスペックではありません。(逆に言うと、その頃に登場した主力メーカーのネットブックはほぼ Windows XP を搭載していたので、どのメーカーのものでも軒並、似たようなスペックでしたが…)

低スペックとは言えど、ちゃんとチューニングをしてあげれば、メールやインターネットは難なく行えると思います。妹は我が家でも一番コンピュータ関連に疎いライトユーザなので、このくらいのスペックでも問題ないでしょう。

今年の5月に、マウスコンピューター製の 4 万円ほどのラップトップを購入して、3万5000円で購入した LaVie Light から移行したのですが、新しい環境は

  • 画面がちょっと広い
  • スペックがちょっと高い

以外は、ほとんど魅力を感じませんでした。LaVie Light の方が、筐体がしっかりしているし、コンパクトで持ち運びにも便利。マウスコンピューター製のラップトップは、筐体の底に手をあてがって普通に持つと、底のプラスチックが自重で歪むのか、中のファンが筐体に擦れる音がなります。どんだけ筐体薄いんだよ、と思いました。筐体が全ての箇所において安っぽいのはさておき、画面がめちゃくちゃ悪く(素人目で分かるほど発色が違い、他のディスプレイで判別できる色の差がこのラップトップで表示すると判別できない、薄い色は飛び、暗い色は潰れる…など。カラープロファイルとかソフトウェア的な調整をしてみたけれど変わらず。)、絵を描いたり、画像処理をする用途にはまったく向いていませんでした。ここは、かなり凹んだと同時に、なんだかんだ言いつつ、結局日本製が安心だなと思いました。

ともあれ、メイン環境は既にマウスコンピューターのラップトップに移行済みでしたので、LaVie Light は寝室の枕元で本と一緒に並んでいました。LaVie Light には Ubuntu を入れて使っていたので、プリインストールされていた WindowsXP に戻したいと思います。

ディスク構成

LaVie Light を購入した直後は、以下のようになっていたと思います。

基本領域1Cドライブ(NTFS) 論理領域1Dドライブ(NTFS) 基本領域2リカバリ領域(FAT32)
拡張領域

物理ディスクは内蔵のSATA一つだけ。MBRにはNTローダが鎮座しており、初期値で基本パーティション1のCドライブを起動するようにしてありました。基本パーティション2のリカバリ領域は、リカバリCD-ROMが付属していない為、ハードディスクにその領域を確保してあるようで、リカバリイメージのほか、リカバリ・ウィザード表示の為の簡易Windows(MiniNT、Windows PE みたいなものらしい)一式とシマンテックのGhostが入っていました。

Ubuntuをインストールした際、リカバリCD-ROMもないと言うことで、リカバリ領域だけは残して、次の構成でインストールしました。

基本領域1swap 基本領域2/boot (ext2) 基本領域3/ (ext3) 基本領域4リカバリ領域(FAT32)

余談ですが、最初はUSB CDドライブを接続してDebian GNU/Linuxをインストールしたのですが、カーネルモジュール(ドライバ)周りを整えるのに心が折れてしまったので、オールインワンなUbuntuにしてしまいました。MBRにはgrub2、ブートエントリには/bootに入ってるカーネルと、自動認識されて追加されたリカバリ領域の2種類がありました。

さあ、この状態からWindows XPに戻します。

修復ウィザードを実行

LaVie Lightの電源を入れ、grubが起動したらリカバリ領域から起動させます。すると、MiniNTが起動して、GUIな修復ウィザードが起動します。ウィザードに従ってハードディスクをフォーマット後、リカバリするようにしました。元通りにしたいので、以下のような構成ですね。(ドライブを細分化する必要もないので、Dドライブは基本パーティションに格上げしました)

基本領域1Cドライブ(NTFS) 基本領域2Dドライブ(NTFS) 基本領域3リカバリ領域(FAT32)

ハードディスクのフォーマットを終えると、一旦再起動するように促されます。手順に従い、再起動させました。

すると、BIOS画面を過ぎた後、ブートローダが起動すべき場所で

[bash]Grub Error (22)[/bash]

と出てOSを起動することができません。半ば予想はしていたのですが、それでも淡い期待をしつつ修復ウィザードに任せた自分がバカでした。

リカバリ領域の修復ウィザードは、MBRまで修復(fixmbr)してくれないみたいです。

grubよ、そりゃあ/boot/grub/grub.cfgが消えてるんだからエラー吐くよね。お前は悪くない。自分のようにカスタマイズして使わない場合でも、マイクロソフトの回復コンソール(とfixmbr/fixbootなど)が起動するCD-ROMはないのだから、MBRが壊れたらマズいんじゃないの…。リカバリ領域を起動できた→つまり、MBRは修復しなくても大丈夫なんだろ?という発想なのかもしれません。

Trisquel GNU/Linuxで起動

さて、どうしたものかと思ったものの、とにかく起動できないのでは手の施しようもないので、ちょうど手元にあったフリーソフトウェア財団のカード型USB KeyをLaVie Lightに差して起動しました。中にはTrisquel GNU/Linuxがプリインストールされています。手元にこういうツールがあったら本当に便利ですね。コイツには何度も助けられています。

USBブートしたTrisquel上で、

[bash]sudo grub-install /dev/sda[/bash]

しても、まあナンセンスだろうと思い、マニュアルで色々するよりは、Trisquelをハードディスクにインストールして、その際に他のパーティションにあるWindows領域のブートエントリまで拵えてくれるくれる方が確実だろう、と、インストールを実行することにしました。

基本領域1Cドライブ(NTFS) 基本領域2Cドライブ(NTFS) 論理領域1/ (ext3) 論理領域2swap 基本領域3リカバリ領域(FAT32)
拡張領域

基本パーティション2を縮めて、空いた領域に論理パーティションを作成、その中に / と swap を確保しました。インストール後、再起動すると見事にgrubが復活してくれました。

基本パーティション1のCドライブのブートエントリも入ってるかなーと、またも淡い期待をしていましたが、論理パーティション1のTrisquelと基本パーティション3のリカバリ領域のエントリしかありませんでした。

というのも、Trisquel側から基本パーティション1をマウントして分かったのですが、Cドライブの中には設定ファイルが一つ入っているだけで、ほぼ空の状態でした。修復ウィザードがMBRを修復することなくハードディスクをフォーマットして再起動した時点では、まだリカバリイメージの展開が行われていなかったことをここで知りました。

リカバリ処理の続きを再開

それならブートエントリが自動的に追加されていなくて然り、この続きの手順が分からないままでしたが、とりあえずgrubが復活してリカバリ領域を起動できるようになったので、起動してみました。すると、今度は修復ウィザードではなくシマンテックのGhostが起動し、ユーザの入力を待たずしてインジケータバーを動かし始めました。あ、ようやくリカバリイメージの展開を始めたな。10分ほど待つとCドライブへの書き込みが終わったようで、自動的に再起動しました。

ここで、MBRも書き換えてくれたかなあ、と半ば諦め気味に起動画面を見ていたのですが、やはりgrubのままでした。ブートエントリはもちろん変わらず。Cドライブのリカバリイメージだけだから、ブートレコードはリカバリイメージに含まれていても、マスターブートレコードまではリカバリの対象外なんでしょうね。

さて、確実にリカバリイメージの転送は終わっているので、Cドライブは起動可能な状態になっているはずです。残るはMBRを戻したいのですが、まずはCドライブから起動できないと話しにならないので、起動してみることにしました。

Grubの設定

Trisquelでインストールされるgrubは、初期設定でパスワードが設定されていました。grubのブートエントリ選択画面でeキーを押しても、起動コマンドの編集の前にユーザ名とパスワードを求められ、編集することができません。

一旦、Trisquelを起動して

[bash]sudo less /boot/grub/grub.cfg[/bash]

してみると、ユーザ名「grub」、パスワード「12953」と設定されていることが分かりました。再起動して、grub画面でこれらの情報を入力すると、コマンドの編集画面に辿りつきました。Windowsのブートコマンドの書き方は知らないので、リカバリ領域に入ったMiniNTのものを変更して用いることにしました。

[bash]insmod fat
set root='(hd0,3)’
search –no-floppy –fs-uuid –set d8fe-92a4
drivemap -s (hd0) ${root}
chainloader +1
[/bash]

1行目はFATじゃなくてNTFSに変更、(hd0,3)はマスターに接続されたディスクの3つめのパーションってことだろうから、(hd0,1)に変更。searchの行は、ディスクを探されるとかえって面倒なので削除して、次のようにしました。

[bash]insmod ntfs
set root='(hd0,1)’
drivemap -s (hd0) ${root}
chainloader +1
[/bash]

C-xを押して起動してみると、ようやくCドライブを起動することができました。WindowsXPの初期設定画面が出てきます。その後、Windowsの初期設定→NECのプリインストールされているソフトの本当にどうでもいい初期設定で4回ほど再起動しやがりました。その度にgrub起動時のパスワード入力からエントリの書き換えまでやりました。Cドライブの起動コマンドをブートエントリに登録しとけばよかったんですが、「1回再起動したらWindowsの初期設定も終わるし、すぐにfixmbrできるだろう」と思ったのが間違いでした。ハードは最高なのにソフトがダメっていう典型的な日本企業のアレですね。本当にどうでもいい初期設定を繰替えしました。

fixmbrはどこ?

WindowsXPに戻せたとは言え、MBRがgrubのままなのでNTローダに差し替える必要があります。回復コンソールが起動できるようなリカバリCD-ROMはないし、リカバリされたWindowsXPにも、もちろんfixmbr.exeは入っていません。Microsoftの公式配布も起動用フロッピーやCDイメージばかりで、あまりこのご時世に合ったサポートは得られそうにありませんでした。そもそもこんな基本的なツールも同梱してないとは…と閉口しつつも、太陽が昇り始めていたので本日の作業はここまでということにしました。

NTローダを諦めれば、Trisquelをもう一度立ち上げて、grubのブートエントリにCドライブのみにして、自動起動までの時間を短くしておけばいいかなあ、と思っています。