ラベル linux の投稿を表示しています。 すべての投稿を表示
ラベル linux の投稿を表示しています。 すべての投稿を表示

2013/05/05

RaspberryPiでLVS+keepalivedを使ってHA構成にしてみた

RaspberryPiは手軽なLinux実行環境ですが、定格で5V/700mAが必要です。 古いPCやUSBハブに接続した場合には、うまく動かない可能性があります。

iPadやタブレットで充電に1000mA(==1A)が必要な状況なので、それほどUSBの電源周りも余裕のある設計になっているものも多くあるはずです。

とはいえ、USB2の定格は5V/500mAなので古めのPCや電源付きUSBハブにいろいろな機器を接続した場合には動作が不安定になる可能性があります。

またカーネルに3.6-trunk-rpiを選択した時には、2013年5月5日時点では、ファイルシステムに負荷をかけるようなタイミングでBUG: scheduling while atomic: swapper/...のエラーが出てまともに動きませんでした。

対応linuxカーネルの有効化

基本的な環境はarmelhfアーキテクチャのRaspbian "wheezy" をインストールした状態です。

Raspbianのカーネルは3.6.11#371版ですが、ip_vsモジュールなどは導入されていません。

このためパッケージからip_vsモジュールの含まれているイメージを導入します。

$ sudo apt-get install linux-image-3.2.0-4-rpi
起動時のカーネルイメージの変更

linux-image-*パッケージを導入しただけでは、再起動をしても引き続きRaspbianの付属カーネルが使われます。 ポイントは次のとおりです。

  • zImageを/boot/kernel.imgのファイル名でコピーする
  • initrdイメージがある場合は/boot/config.txtに記入する
/boot/kernel.imgファイルの置き換え

既存のkernel.imgファイルは退避して、vmlinuz-3.6-trunk-rpiファイルをコピーします。

$ cd /boot
$ sudo mv kernel.img kernel.3.6.11#371.img
$ sudo cp vmlinuz-3.2.0-4-rpi kernel.img

ちなみに/bootはvfatなので、ハードリンクなどを使う事はできません。 基本的にはcopyで対応することになります。

/boot/config.txtファイルの書き換え

initrdを使用している場合には、対象のファイル名をconfig.txtに書き換えます。

...
ramfsfile=initrd.img-3.2.0-4-rpi
ramfsaddr=0x00a00000
initramfs initrd.img-3.2.0-4-rpi 0x00a00000
...

ちゃんと確認していませんが、/bootにあるものとしてファイル名だけを記述しています。

再起動でカーネルの確認

とりあえず再起動して動作を確認します。

うまく行かない場合には別のPCに接続して編集内容を確認します。 /boot以下はVFAT領域なので、問題なく扱えるはずです。

ramfsaddrなどを指定しないと、initrdのイメージが展開されない事になります。 うまくいけばdmesgに次のようなメッセージが表示されます。

$ dmesg | grep init
...
[    1.049760] Unpacking initramfs...
[    1.710015] Freeing initrd memory: 4476K
...

パッケージの導入

ipvsadmとkeepalivedを使いますが、ipvsadmはkeepalivedの導入時に自動的にインストールされます。

keepalivedの導入

パッケージを導入します。

$ sudo apt-get install keepalived

設定

パッケージを導入しても設定ファイルは一切導入されないので、過去のログをみながら設定ファイルを構成します。

/etc/keepalived/keepalived.confの編集

今回はWebサーバではなくて、ESXi上に構成しているLDAPサーバに対してHA構成を取っています。

振り先の設定

LDAPサーバ側にいくつか設定が必要です。

/etc/sysctl.confの編集

対象サーバが1台しかない場合には、問題になりませんが、複数のslave LDAPサーバに処理を分散させるような場合にはサービス(仮想)IPとMACアドレスが強力に結びついてしまうと、ルータからダウンしたLDAPサーバに常に処理が振られてしまうのでARPリクエストに反応しないように変更する必要があります。

/etc/sysctl.confへの追加内容

net.ipv4.conf.eth0.arp_ignore=1
net.ipv4.conf.eth0.arp_announce=2

設定を反映させます。

$ sudo sysctl -p

sysctlコマンド実行後の画面出力

net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.eth0.arp_announce = 2
サービス(仮想)IPの設定

IPレベルではリクエストは2台のRaspberryPiで共有されるサービス用の(仮想)IP宛てのパケットがLDAPサーバに到着します。

自分宛てのパケットだと認識しないといけないので、loopback(lo)にIPを設定します。 まだ未使用のlo:0デバイスを使います。他に使用している場合には、lo:1,lo:2など適当な番号に変更してください。

/etc/network/interfacesファイルへの追加内容

auto lo:0
iface lo:0 inet static
  address 192.168.1.182
  netmask 255.255.255.255

さいごに

RaspberryPiを入手して、いろいろ試していますが、電源の品質とカーネルの安定性が一番の問題でした。

電源はUSBハブから取っていますが、マウス、キーボードなどは本体に直接つないで他の機器はつないでいません。

PCなどに接続する場合には、2つ口の片側に接続する事で500mA 2つ分の1000mAまで電流が取れるものが多いようです。 最近ではiPadやタブレットに対応した急速充電可能なタイプであれば、1000mAまで取れるので問題ないでしょう。

SDカードはTranscendのClass10 UHS-I対応16GBと、PanasonicのClass 10 SDHC 8GBのカードを使っています。 他のARM系ボードでも使っていますが、これまでのところ問題は起きていません。

この他にも$ sudo raspi-configで変更できるパラメータは少し変更していて、安定して動くようになってから900MHzへのオーバークロックやVRAMを16Mに変更したり、

tail -5 /boot/config.txtの実行結果

# for more options see http://elinux.org/RPi_config.txt
gpu_mem=16
core_freq=250
sdram_freq=450
over_voltage=2

この記事で取り上げた品々

2013/02/06

OpenLDAPを導入したので、各OSでの設定方法をまとめてみる

UbuntuにOpenLDAPを導入して、ldap-account-manager (LAM)で管理しています。

VirtualBOXを使った時のOSへのログインユーザーの管理や、ミドルウェアを稼働させるユーザーの管理をOpenLDAPに一元化したいと思ったので、VMとして使っている主なOSでのldap設定をまとめました。

前提知識

LDAPの設定は様々なミドルウェアで行なえますが、微妙に設定できる名称や設定方法が異なります。

共通部分としてはサーバー名、ポート番号の他にバインドDN(とそのパスワード)、BaseDNなどがあります。

製品によってはユーザー名を構成するサブディレクトリ(ou=People等)の指定ができるものがあります。

また階層を辿るために、base,one,subなどのスコープを設定できるものもあります。 何も設定されていないOpenLDAPは自由に階層を辿る事ができるため、全部のディレクトリ情報を表示する事も可能な事が多く、サンプルもそのように構成されている場合があります。

しかし実際には、ディレクトリ全体を辿られてしまうと社員名とID,e-Mailアドレスとの紐付けなどをごっそり持っていかれる可能性があるため、自分自身のディレクトリ情報以外は編集ができず、それ以外の情報はDNで直に指定しないと閲覧できないように設定されている場合もあるでしょう。

LDAPについての設定方法は標準的な部分と、非標準的な暗黙知によって構成されています。 ActiveDirectoryを前提にしていると、Netscapeに由来するようなDirectory構成

ldapserverldapbasednに指定するサーバー名やBaseDN名は適宜変更してください。

CentOSなど(RedHat系)でのldapログイン設定

以前のブログでも書いていますが、コマンドラインから設定する事が可能です。

 $ sudo authconfig --enableldap --enableldapauth --ldapserver=openldap.example.org --ldapbasedn="ou=accounts,dc=example,dc=org" --updateall

これはCentOS 5.4で試した設定方法ですが、CentOS 6.3でも同様に使えます。

Ubuntuでのldapログイン設定

UbuntuではガイドのLDAPClientAuthenticationにあるように2つのコマンドを実行することでLDAPを設定する事になっています。

 $ sudo apt-get install ldap-auth-client nscd
$ sudo auth-client-config -t nss -p lac_ldap

Ubuntu 12.04 LTSで確認したところ次のようなログインできない問題が発生しました。

  • ログインできず、/var/log/auth.logに次のようなメッセージが表示される pam_ldap: could not open secret file /etc/ldap.secret (No such file or directory)
  • $ getent passwdではUserが表示されるのに、ログインできない
存在しない/etc/ldap.secretの問題

前者の/etc/ldap.secretを要求するのは、/etc/ldap.confでrootbinddnを有効にしているからです。

auth-client-configの設定画面で、クライアントからのパスワード変更を許していないので適当なrootbinddnと空のパスワードを入力したのが原因でした。

/etc/ldap.confからrootbinddn行の先頭に#をつけてコメントにする事で解決しました。

user名は認識されるのにログインできない

単純にnscdがリスタートされていないだけでした。

プロセスを再起動:$ sudo /etc/init.d/nscd restart して、無事にログイン($ ssh user1@example.org)する事ができました。

Debian 6.0.3でのldapログイン設定

DebianにはUbuntuにあったldap-auth-clientパッケージが存在しません。 そのためlibpam-ldap, libnss-ldapを手動で導入します。

$ sudo apt-get install libpam-ldap libnss-ldap
/etc/libnss-ldap.conf, /etc/pam_ldap.confファイルの確認

それぞれアンダースコア'_'やハイフン'-'が入っていてまぎらわしですが、この2つのファイルの内容を念のため確認します。

Ubuntuでの経験を活かして、rootbinddnやパスワードへは空文字列を入力してみましたが、libnss-ldap.confではrootbinddnが何も指定されないまま有効になっていました。

パスワード変更にはOSの機能を使わない事にしているので、今回もrootbinddn行はコメントアウトします。

面倒であれば、apt-getの実行時にadminのDNとパスワードを入力する事で、編集なしで良くなるはずです。

最後に/etc/nsswitch.confを有効にする

nsswitch.confなんて昔のBSD系やLinux OSにはなかったんですけどね…。Solaris 2.2か2.4ぐらいを触った時の衝撃といったらありませんでした…。

他のOSと同様にnsswitch.confのpasswd, group行のcompatfiles ldapに変更すれば完了です。

nscdのリスタート

ここまでで、LDAPに登録したIDにsu -の実行やログインができない場合には、nscdをリスタートしてみてください。

$ sudo /etc/init.d/nscd restart

基本的にはこれで完了するはずです。

FreeBSD 9.1でのldapログイン設定

基本的な流れはガイドのLDAP Authenticationの中にあります。 導入が必要なPortsは以下の通りです。

  • net/nss_ldap
  • security/pam_ldap

自動的に両方のPortsが依存しているnet/openldap24-clientも導入されます。

Portsのインストール(# make install)が完了したら、以下のように3つのファイルを編集するとLDAP認証が有効になります。

/usr/local/etc/nss_ldap.confの設定

基本的にはurlかhost,それにbaseを設定すれば動きますが、使っているLDAPサーバーのディレクトリ構成やサーバー自体の設定によっては必要な追加設定があるかもしれません。

/etc/pam.d/loginの編集

sshd経由でのログインも行なうのであれば、/etc/pam.d/sshdの設定も変更する必要があるはずです。

サンプルはガイドにあるので詳細は省きますが、auth sufficient /usr/local/lib/pam_ldap.so no_warnの設定を入れれば完了です。

/etc/nsswitch.confの編集

ここまでの設定が完了していて、/etc/nsswitch.confファイルのgroup行とpasswd行をcompatからfiles ldapに変更すればログインにldapが使われるようになります。

さいごに

LDAP認証ではBindDNやらAdminDNやらRootBindDNやら、似たようなものや、実質同じものが名前をかえて登場します。

LDAPサーバーの動きをちゃんと捉えるのは面倒ですが、いまならLPI-Japanが無償で配布している高信頼システム構築標準教科書やLPIC Level 3の教本なんかが、良いとっかかりになるはずです。

動きから抑えるのが良いのですが、普段はシステムの裏側にいて、簡単にldapsearchが試せる本番環境というのもあまりありません。

ネットワーク屋さんがルーター管理にRADIUSを動かしても特権用の共有IDなんかをファイルベースで作って終りだったり、本来はLDAPを使うべき場面なのに、他の方法で代用されている場合もあるかもしれないですね。

会社や学校でLDAPサーバーがあっても、それがLDAPサーバーだと気がつかない場合があるかもしれませんし、アクセス制御が厳密でなかなか挙動をリバースエンジニアリングするのは難しい場合もあるかもしれません。

なんにしてもLDAPサーバーを試す環境はいまのところ自分で動かすしかないので、単純にサーバーと管理ツールを入れて終りにしないで、高可用性を保つために何が必要か、よりセキュアな環境にするためには何ができるのか、考えてみると良いでしょう。

2012/08/16

さようならPS3 Linux。

いろいろ思うところがあったけれど、Playstaion 3のファームウェアを3.15から最新版の4.21にする事にしました。

まぁ普通の人なら当然するだけの事をしたんですが、これでHDDの中で10GBほどの領域を占有しているLinux領域にアクセスできなくなるわけです。

ときどき使っていたけれど、本気で使っていたわけじゃありません。 これからCellのプログラミングをする事もないだろうから、Other OSのサポートがなくなるのはしかたがなく受け入れる事にしました。

べつにこれで何か経済的に損失があるというわけでもないですし、ダウングレードしないといろいろできないのは納得したわけじゃないけれど、得られるメリットとのトレードオフなわけで、いま頃になってようやく分岐点を越えて決断に至った次第です。

まぁ自分に非がないのに当時の社長御自身がセールスポイントとしていた機能が削られた分のお金は返金して欲しいなぁとは思います。

2012/06/23

Ubuntu 12.04 LTSマルチディスプレイ環境下での不具合?

数年前に新品パネルに交換した事もあって、いまだに17インチディスプレイ(Nanao FlexScan L567)を使っています。 これを2枚並べてマルチディスプレイ環境にしているのですが、拡大表示時の課題などもあってディスプレイを仮想的に接続せずにDISPLAY環境変数でいうところの:0.0と:0.1として使っています。

このディスプレイが接続されているマシンはUbuntu 12.04 LTS専用機で、Androidアプリの開発やらメール書きやらのメインマシンとして使っています。

タイトルに?をつけてスポーツ新聞の見出しみたいですが、今回はいままで気がついたものの、コード上でまだ原因が特定できていない、おそらくマルチディスプレイ環境が原因と思われる症状をメモしておきます。

環境について

OSよりもWindowManagerの影響は大きいと思われて、その他のGNOME, KDEなどでは現象が発生しないかもしれません。

  • OS: Ubuntu 12.04 LTS x86_64版
  • WindowManager: xfwm4 (デスクトップ環境はXFCE)

考慮点

ここでまとめた内容は、まだコード上でマルチディスプレイが原因と特定できていない現象を含んでいます。 そのため現象としては正しいが、原因はマルチディスプレイ環境にないものも含まれている可能性があるのでご注意下さい。

なおアプリケーションをDIPSLAY=:0.0設定下で稼働した場合には不具合は起っていません。

其の壱:Android AVD(qemu)が終了しない

EclipseからAVD(qemuによるandroid emulator)を起動して、デバッグが終ったところでウィンドウを閉じて終了しようとしても、AVDプロセスが終了しません。

KILLHUPシグナルは受け付けないので、この場合の対処法はkill -9で該当プロセスを強制終了させるのみです。

其の弐:Firefoxのプルダウンメニューが開かない

住所欄の都道府県などはFormのプルダウンメニューで選択可能になっている場合があります。 このプルダウンをクリックしても選択肢が表示されません。下矢印キーで選択はできるので実用上は致命的とまではいえません。

其の参:PiTiViビデオエディタで動画のExport処理が完了しない

最終的に完成した動画をExportするわけですが、この処理が永遠に終わりません。

この他にも動画関連の不具合はあって、ffmpegやmpeg2enc辺りが怪しいんですが、追求していません。

其の肆:gtk-recordmydesktopが撮影を終了することができなくなる

やっぱり動画周りの不具合ですが、これは通知エリアを利用するアプリケーションで、DISPLAY=:0.0に通知ウィンドウがある場合に、DISPLAY=:0.1で動かしたgtk-recordmydesktopが隠れたまま、操作不可になってしまう事が原因です。

この場合、gtk-recordmydesktopを端末から起動していてC-cで終了する事はできますが、recordmydesktopプロセスは残ってしまいます。手動でKILLHUPを送信すれば停止しますが、注意が必要です。

当然、gtk-recordmydesktopを使わず端末からrecordmydesktopを直接動かせば何の問題もありません。

まとめ

これからKDE,GNOMEで動かしてみて、どんなになるか確認してみます。 とはいえ作業中なので環境全体をシャットダウンして試すことはすぐにはできないんですよね。

最近は1920x1200を越えるディスプレイも簡単に購入できて、27インチで2560x1440ともなれば、1280x1024の2枚(2560x1024)よりも下に広くなります。でもこのFlexScan L567の発色は良くて満足しています。 Mac/Windows用に安い1920x1080なIPS液晶ディスプレイもあるんですが、表面処理が荒くてオブラートみたいな薄い膜が一枚あるみたいなのが残念です。

IPSが高級品だった時代は過ぎさってしまったので、次に購入する時は実物も眺めつつ決めたいと思います。

2012/05/07

Ubuntu 12.04 LTS 64bit版で、JACKとflashplayerを動かしてみた

カーネルをPREEMPTに変更したタイミングで音楽の再生にjackdを使ってみました。

立ち上げ時の初期設定が少々面倒ですが、一日のほとんどの時間でUbuntu 12.04 LTSを使う現状では、 入力ソースをコントロールできるJACK Mixer等は本当に便利です。

便利なのですが、JACKを使う事で、それまで特に設定していなかったfirefoxやgoogle-chrome上の flashplayerからの音が出なくなってしまいました。

それだけなら我慢できたのですが、音声出力がブロックされるためか動画の再生もうまくできなくなり、 flashplayerに引きずられる形でブラウザ全体が不安定になってしまいました。

JACKを動かしながらflashplayerからの出力もできるようにするために、 ALSA/PulseAudioからjackdに接続するための方法を探ったところ、Ubuntu Japanese Team Wikiに JACKとPulseAudioを併用するための方法がまとまっているのを見つけました。

Japanese Teamの文書に従えば問題ないですが、つまづいたところだけ補完しておきます。

基本的な考え方

Linux上で音声を扱うAPIはいくつかありますが、普段は特に意識することなく使っていると思います。

普段意識せずに使っているもの(ALSA/PulseAudio)をJACKというもので置き換えるわけで、 普通にしていれば使えたものが突然使えなくなる原因を生むわけです。

世の中にはJACKよりも、デフォルトでサポートされる事の多いALSA/PulseAudioに対応しているアプリケーションが当然多いので、そういうアプリケーションの音声出力をJACKに流す方法を取る事にします。

うまく行かなかった方法

まず、ALSAからJACKに音声出力を流す方法はうまく行きませんでした。 これはPulseAudioを使う事にして解決しました。

次にlibflashsupport-jackをコンパイルする方法も見つかりましたが、少し古いソースコードだった点と、 64bit環境でflashplayer用に共有ライブラリを作るのは良いアイデアに思えなかったので試しませんでした。

Linuxで音を扱う方法は複雑

そもそもLinuxで音声出力を行なうにはカーネルレベルではOSS/ALSAが存在していて、各種デバイス(スピーカー)を制御しています。

そこに各アプリケーションから直接音を出してもいいけれど、抽象化したり高度なミキサー機能など、いろいろな付加機能を付け加えるためにPulseAudioやJACKなどが存在します。

今回問題になったのは単純にJACKを動かしている環境では、ALSAをサポートするアプリケーションはそのままでは動かないという点です。

ALSAからJACKに出力するために、~/.asoundrcを作成する方法もあるはずなのですが、今回はこれがうまく動かなかったので、PulseAudioを使う事にしました。

設定手順どおりに行かなかったところ

ほとんどの環境ではUbuntu Japanese Team Wikiにある JACKとPulseAudioを併用するための方法で対応できると思います。

ただ昔からアップグレードしてきたシステムなので、~/.asoundrcが悪さをして音が出力されませんでした。

ファイルを削除する $ rm ~/.asoundrc だけでうまく行きました。 ただpavucontroを起動するだけではうまく行かずに、手順にある画像のようにJack sinkを明示的に選択する必要がありました。

JACKを扱う場合にはQJackCtlでのConnections設定が不可欠で、起動しただけでは音が出ないのは普通のことだと思って、頑張って下さい。Patchbayを使って設定を保存できるようになると手間がだんだん省けて、手に馴染んでいくでしょう。

Patchbayで、OutputとInputを接続してもsystemにもパッチされてしまう場合には、output側の設定でExclusiveにチェックを入れておくとsystemには接続されないようになります。

まとめ

最終的に環境が動きだすと、firefoxやgoogle-chrome, chromiumなどのブラウザでflashplayerを使う場合に、各flashplayer毎にpavucontroに項目が増えます。

これをミキサーにして扱う事で、JACKプラグインを設定しなくても音が出るようになり、アプリケーションが安定的に稼働するようになりました。

大抵はJACKプラグインがある場合には、直接JACKに接続した方が良いと思っています。 しかしUbuntu 12.04 LTSのVLCの出力にはJACKプラグインもありますが、音が断続的に出力されるようになります。 VLCではALSA出力に切り替えてPulseAudio経由で出力するようにしたところ問題なく聞こえるようになりました。

VLCのJACKプラグインがうまく動かない理由は不明ですが、そういう例もあるという事でJACKとPulseAudioが動く事で選択肢が広くなって便利になったと思います。

2012/05/02

さくらVPSのDebian wheezyにCouchDB 1.2.0をインストールしてみた

少し時間ができたのでCouchDB 1.0の環境を1.2にアップグレードする事にしました。

手製ツールの稼働検証やら、DTIのVPSに作った郵便番号検索の仕組みを更新するとか、1.0から1.2への変化をキャッチアップするだけで、何だかぐったりするような作業で腰が重かったのですが、この機会に(現実逃避を兼ねて)とりかかることにしました。

私のcouchdbの使い方はバックエンドサーバーとして使うものなので、フロントエンドにcouchdbを使おうとする普通の使い方をする方はSSLなどのセキュリティ設定にもっと注力する必要がある事に

進め方の方針

アップグレードとはいっても現状の環境は止めるわけにいかないので、さくらのVPSに構築したtestingステータスのDebian wheezy上に新規にEarlang, CouchDB、その他の自前ツール等々をインストールをして、切り替えることにしました。

最終的にはCNAMEで設定しているwww.yadiary.netのレコードを書き換える事で対応する予定です。

対象の環境

現行のDTIのプランは490円のCPU: shared 1core, Memory: 256MB (max. 1GB)の構成で、 スペックをみる限りはリッチですが、このアプリケーションの性能にはほとんど変化ないだろうと考えています。

さくらVPSに構築しようとしている環境は次の通りです。

  • VPSプラン: さくらのVPS 2G (CPU: shared 3core, Memory: 2GB)
  • OS: Debian wheezy (次期stable、現testing), 64bit (x86_64)
  • Earlang: OTP-R15B01
  • CouchDB: 1.2.0

ちなみにDTIにある現行機は、Debian squeezeで、Earlang/OTP-R14B, CouchDB-1.0.2という構成です。

CouchDB 1.0系と1.2系の違いについて

1.1での変更も含めた完全なリストは apache-couchdb-1.2.0.tar.gz に含まれるCHANGESファイルにあります。

Native SSLサポートが含まれていたり、細かい点ではセキュリティ上の改善点もいくつか含まれています。

インストール手順

基本的な進め方はCouchDB: 1.0.1から1.0.2のリリースアップ手順 (xstow対応版)に従って進めていきます。

バージョンアップする時には/usr/local/etc以下に配置してある設定ファイルを退避して、新しいバージョンの設定ファイルをコピー、編集する事になりますが、1.2.0でも進め方に違いはありませんでした。

今回もxstowを使って/usr/local以下にインストールするため、/usr/local/stow以下にインストールしたcouchdb-1.2.0の直下からvarディレクトリは/usr/local/var以下に移動しています。 さらにスクリプトファイルから/usr/local/stow/couchdb-1.2.0/varを参照している個所を修正します。

確認するべき対象は次のコマンドで確認しました。

$ find . -type f | while read file ; do grep 1.2.0/var $file > /dev/null 2>&1 && echo $file ;  done

以前はetcファイルも/usr/local/etcに直接展開していましたが、今回は止めました。 バージョンアップの頻度は思ったよりも多くはなくて、その度にlocal.iniをコピーしても手間ではなさそうですから。

VPSサーバでの稼働検証

普通にサーバーを立ち上げるとIPv4のloopbackアドレス(127.0.0.1)にバインドします。 手元にないサーバーへ接続する場合に、グローバルアドレスにいきなりバインドすると外部に対して無防備になってしまいます。

一般的にサービス前のサーバーに接続するために、いくつかの方法が考えられます。

稼働確認という意味では、sshが一番簡単だろうと思います。 サービスイン後も使い続けるのであれば、stunnelがお勧めです。

ただWebサーバーのVirtualHostや、SSLポートのように、アクセス時に指定するサーバー名も重要な要素となる場合には、そうも簡単にはいきません。 今後のためにはiptablesを使った方法も、見当しておく必要があります。

というわけで、今回はiptables/ip6tablesを使ってグローバルアドレスにバインドさせてみる事にします。

iptablesを使った接続制御

iptables/ip6tablesを使う場合には、既にあるルールを汚染せずに追加、削除を行なう必要があります。 ここではポート番号を5985にして、このポート番号に対する制御は事前にされていない前提で作業を行ないます。

local.iniファイルの編集

IPv6アドレスを使っていますが、IPv4アドレスを使う場合には、アドレスの他にip6tablesをiptablesに読み替えてください。

/usr/local/etc/couchdb/local.iniファイルの編集個所

port = 5985
bind_address = 2001:xxxx:31d5:87d3::1
サーバー起動前:iptablesへのルール追加

デフォルトのINPUTルールが、ACCEPTでなければ2行目は不要ですが、明示的に1行目で指定した以外のIPv6アドレスからの接続を拒否しています。

 $ sudo ip6tables -A INPUT -p tcp --dport 5985 -s 2001:3e0:a32:xxxx:8d45:678a:2fe8:xxxx -j ACCEPT
 $ sudo ip6tables -A INPUT -p tcp --dport 5985 -j DROP 

稼働確認

サーバー上の設定が反映されている事を確認します。

 $ sudo ip6tables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp      2001:3e0:a31:1:7d44:6780:2fd9:ca43/128  anywhere             tcp dpt:5985
DROP       tcp      anywhere             anywhere             tcp dpt:5985

設定が反映されていれば、サーバーを起動します。

 $ sudo /usr/local/etc/init.d/couchdb start

これでWebサーバからアクセスする事ができます。 IPv6アドレスを使う場合にはURLが http://[2001:3e0:a32:xxxx:8d45:678a:2fe8:xxxx]:5985/_utils/のように[]で囲む点に注意が必要です。

で、いろいろ作業が終ったらサーバを停止しておきます。

 $ sudo /usr/local/etc/init.d/couchdb stop
サーバー停止後:iptablesルールの削除

偶然サーバーが起動してしまう可能性もありますが、将来的にこの方法を使う事はないので、ip6tablesルールを削除しておきます。

 $ sudo ip6tables -D INPUT -p tcp --dport 5985 -s 2001:3e0:a32:xxxx:8d45:678a:2fe8:xxxx -j ACCEPT
 $ sudo ip6tables -D INPUT -p tcp --dport 5985 -j DROP

作業が終ったところで、 $ sudo ip6tables -L で追加したルールが残っていない事を確認します。

まとめ

とりあえず、これで動くところまでは確認できました。 ここからはいままで作ってきたパッチを1.2に対応させていきます。

参考文献

CouchDBについては公式Webサイトは宣伝要素が強いので、CouchDB Wikiがより実践的で、役に立つと思います。

2012/04/28

Ubuntu 12.04 LTSでlowlatencyカーネルを導入してみる

Ubuntu 12.04 LTSにアップグレード必要があるかどうかは、おそらく多くの人にとって様子をみるべきかなと感じている今日このごろです。

とはいえ、新規にインストールするなら、2013年04月までサポートされるDesktop版Ubuntu 10.04 LTSをインストールする理由はもはやないでしょう。

WindowsというよりもMacのように、バージョンの違いは劇的な変化はもたらしませんが、確実にいくつかの気がつきにくい利点はあると思います。

今回はlowlatencyカーネルを導入してみることにしました。 NVIDIAのGPU用にnvidia-currentを導入しているため、それとの組み合せでおこった問題についてまとめています。

apt-getからのカーネルの導入

lowlatancyカーネルの導入自体は、簡単に終ります。 $ apt-cache search lowlatencyで導入するべきパッケージの候補がいくつか出てきますが、 バージョンアップを適宜行なうためには具体的なバージョンが書かれていないパッケージを導入しましょう。

バージョン番号を現す3.2.0-23等の数字付きパッケージを省くと、導入する候補は次のようになりました。

  • linux-image-lowlatency - lowlatency Linux kernel image
  • linux-lowlatency - Complete lowlatency Linux kernel
  • linux-image-lowlatency-pae - lowlatency Linux kernel image
  • linux-lowlatency-pae - Complete lowlatency Linux kernel

PAEパッケージはx86_64環境では使えないので、実質的にlinux-image-lowlatencyかlinux-lowlatencyかのいずれかです。

カーネルモジュールなどをコンパイルするために/usr/src以下にヘッダーファイルも必要なので、linux-image-lowlatencyとlinux-headers-lowlatencyの両方を導入するのかと思いきや、linux-lowlatencyパッケージがあるので、これを導入しましょう。

 $ sudo apt-get install linux-lowlatency 

導入自体は、これで終りですが、手元の環境ではリブートしてもlowlatencyカーネルでは起動してくれませんでした。

GRUBのカーネル起動順序の変更

リブートの起動時に10秒ほど待ち時間があるはずなので、GRUBの画面を表示させてlowlatencyカーネルを選択して問題なく起動することを確認しましょう。

ここでNVIDIAのGPUカード周りで問題があったのですが、それは後で説明する事にして、先にGRUBの設定変更についてまとめておきます。

GRUB2が導入されている場合には、/etc/default/grubを変更した後に $ sudo update-grub コマンドで、/boot/grub以下の設定ファイル(grub.cfg)に反映させます。

ここで変更したのは、GRUB_DEFAULTの行です。

/etc/default/grubファイルの先頭部分

GRUB_DEFAULT=2
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=10
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="rootfstype=ext4 rootflags=data=writeback,relatime quiet splash"
GRUB_CMDLINE_LINUX=""

手元の環境では最新のカーネルは3.2.0-24で、lowlatencyカーネルのバージョンは3.2.0-23でした。

このため後から導入したにも関わらず、/boot/grub/grub.cfgの先頭に設定されているのは3.2.0-24カーネルの方で、lowlatencyは上から3番目に設定が書かれています。

GRUB_DEFAULTのパラメータは0から始まるので、3番目の設定で自動的に起動するために=2を設定しました。

この状態でgrub.cfgを再作成すると、自動的にlowlatencyカーネルで起動するようになります。

 $ sudo update-grub 

NVIDIAのビデオカードが認識されない問題

起動時にはデフォルトのVGAデバイスでlightdmが起動してしまったので気がつかなかったのですが、後からlowlatencyカーネルを導入した時にはカーネルモジュールの再作成はされませんでした。

一度lowlatencyパッケージで起動した後で、次のようにnvidia-currentパッケージを再構成すると良いでしょう。

 $ sudo dpkg-reconfigure nvidia-current 

これでlightdmを再起動( $ sudo /etc/init.d/lightdm restart)するか、再起動すれば動き始めるはずです。

まとめ

lowlatencyパッケージは、動画、音声関連のアプリケーションパッケージをまとめているUbuntu Studioグループが作成しています。

はたしてlowlatencyパッケージが必要なのかどうかは、疑問に思うところもあるのですが、とりあえず使わないと善し悪しが分からないので、しばらく使ってみる事にしました。

アプリケーション内部でnice値を適切に設定しないと、適切なリアルタイム性が得られないという指摘があります。 通常のデスクトップアプリケーションで果してレスポンスが良くなるか、lowlatencyカネールを使えば良いという考え方ではまずいかもしれない事は認識しておくべきだと思います。

Ubuntu 10.04 LTSで使われていた2.6.32パッケージから3.2の間で多くの変更がカーネルに行なわれています。

2.6.37前後ではext4,xfsファイルシステムに関連した修正が多く行なわれていますし、SMP環境ではいまいちだったreiserfsにもワークアラウンドが実装されています。

プロセスの応答性については常にスケジューラーの見直しが行なわれているところでもあるので、普通に便利に使えれば良いという方々にはノーマルなカーネルをまずはお勧めします。

個人的にはUbuntu 10.04 LTSを使っている方は、アップグレード作業の懸念さえなければ、12.04 LTSに以降した方が幸せになれるだろうと思います。 ああ、Gnome周りはログイン時にXfceを選択するとか、別のWindowManagerを選択するとか、ちょっとした事はあるかもしれませんが、使い勝手に大きな変化はなく、最新のパッケージが使える事でいろいろ便利になるでしょう。

2012/04/15

pubimg: 画像ファイルを外部に公開するためのユーティリティ

このブログのコンテンツ自身はテキストファイルで、独自にXMLスキーマをRelaxNGを使って定義して、Emacsのnxmlモードでバリデーションしながら書いています。

外部参照用のURLは外部のXML定義ファイルにまとめていて、コアの機能は固まっていますが、ラベル一覧やURL一覧に効率良くアクセスする手段は模索中だったりします。

ブログだけでなく外部に公開する画像ファイルを対象に、効率良くアップロードするためのユーティティを作成しました。

pubimg本体の動き

外部に画像ファイルを公開する時に必要な作業の流れは次のようになっています。

  • サイズなどを整えた画像ファイルを作成
  • 手元のPCのあるディレクトリにファイルをコピー
  • Apache AntのFtpTaskでバッチ的にファイルをアップロード

この時にブログなどの記事を書く方では、最終的なURLの形式が必要になるので、ファイルを登録するとURLを表示するようにしています。 ここら辺はホームディレクトリの~/.pubimg.confプロパティファイルを参照して、コピー先やURLのprefixの情報等をApache AntとRubyの両方で共有しています。

このプログラムで実行している様子は次の通りです。

端末でpubimgを実行した様子

pubimgスクリプトの特徴

このスクリプトは単純ですが、次のような機能を持っています。

  • コピー先のファイル名を別に指定
  • 日付情報をprefixに付与
  • ファイルサフィックス(いわゆる拡張子)をコピー元から自動的に判別
  • sha256チェックサムで同じファイルが存在した場合には、コピーせずに既にアップロードされているURLを表示

たとえば gnome-screenshot を使った場合は、ファイル名が "Screenshot-1.png"のような名前がデフォルトになります。公開用に作成した分けではない画像ファイルであれば、オリジナルから名前を変更することが必要になります。

そこでpubimgは、第2引数にコピー先のファイル名を指定して、次のような使い方ができます。

$ pubimg Screenshot-4.png terminal_exec_pubimg
http://www.yasundial.org/images/pubimg/20120415.0.terminal_exec_pubimg.png

内容が異なるファイルを既にあるURLにコピーしようとした場合は、日付後のindexがインクリメントします。

$ pubimg Screenshot-5.png terminal_exec_pubimg
http://www.yasundial.org/images/pubimg/20120415.1.terminal_exec_pubimg.png

うっかりヒストリにあるコマンドを実行したり、別の名前で登録しようとしても、重複して登録される事はありません。

$ pubimg Screenshot-4.png hogehgoe
http://www.yasundial.org/images/pubimg/20120415.0.terminal_exec_pubimg.png

プロパティファイル

Apache antとRubyで共有しているプロパティファイルの内容は次のようになります。

プロパティファイル

local.dir = ${user.home}/.pubimg/files
remote.dir = /images/pubimg/.

ant.home = ${user.home}/java/tools/ant
java.home = /usr/java/1.6.0

url.prefix = www.yasundial.org/images/pubimg/

Apache AntのFtpTask用の設定ファイルは別の場所にあり、プロパティで指定する事もできるようになっています。

もし複数のftpアップロード先が必要になれば、読み込むプロパティファイルを切り替える仕組みをpubimg側に入れるだけです。

さいごに

これだけだとライブラリ管理はできていないので、ファイルのリストや削除は別のアプリケーションを作成する事にします。また将来的にはWindowsからファイルをアップロードしたいので、pubimgの機能はRESTアプリケーションとしても動く事になるでしょう。

pubimg自身は複数の小さいrubyクラスから出来ているのでREST側からその機能を呼ぶのは難しくないはずです。どちらかというと権限管理とか、RESTサーバーアプリからファイルを直接コピーさせるわけにもいかないので、そういう手間が増えそうな予感はします。

自宅用のアプリだし、セキュリティの懸念を考慮しなくていいならすぐに動くかな…。

Ruby 1.9.3でfirebirdクライアントを使ってみた

FireBirdはファイルベースで扱えるのでFast-CGIなどで組む場合には非常に便利です。 SQLite3の機能では型が不足していたり、ストアドプロシージャーを使いたい場合などには良い代替案になると思います。

xstowで管理しているrubyのバージョンを1.9.3-p125に更新してから、firebirdに接続するためにfbパッケージをgemから導入しようとしたところエラーが発生しました。

Gitから最新版を入手しましたが、1.9.2で非推奨となっていたSTR2CSTRが本格的に使えなくなったので、コードを書き換えたのでログを残しておきます。

Githubからのコードの取得

作業環境がUbuntu 10.04 LTSなので、gitコマンドを使って作業領域にfbディレクトリを作成します。

$ git clone https://github.com/wishdev/fb.git
$ cd fb
$ ruby extconf.rb
$ make

ここでとりあえずコンパイラは通りますが、make installをしてrubyからDBを作成しようとするとエラーが出て作業を続ける事ができなくなります。

ここはfb.cからSTR2CSTRマクロを使っている個所を一括置換で修正しました。 そうすると今度は沢山あったワーニングの中にエラーが1つ増えて、途中でコンパイルが終了してしまいます。

コンパイル時のエラー

Githubからfbの最新版を取得して、STR2CSTRをStringValuePtrに機械的に置き換えてコンパイルしましたが、次のようなエラーが表示されました。

STR2CSTRをStringValuePtrに書き換えた後のコンパイルエラー

fb.c:2185: error: lvalue required as unary ‘&’ operand

解決策

ここのコードは以前でもSafeStringValueを通すべきなんじゃないかなと思いましたが、 STR2CSTRの他に、以下のような修正を1個所で行なえばruby 1.9.3でfirebirdが使えるようになります。

エラー発生個所の変更前のコード


    sql = StringValuePtr(rb_ary_shift(args));

エラー発生個所の変更後のコード


    VALUE r_sql = rb_ary_shift(args);
    SafeStringValue(r_sql);
    sql = StringValuePtr(r_sql);

2012/04/14

Xfce + マルチディスプレイ環境の片側のディスプレイでフォントが極端に小さ くなる現象への対応

少し時間に余裕が出来る事になってメインデスクトップのUbuntu LTS環境を見直していました。 そろそろ2年振りのLTSアップデートが迫ってきていますしね。

Window ManagerにXfceを使っていますが、:0.0と:0.1のマルチディスプレイ環境にして、ウィンドウがディスプレイ内に留まって互いのデスクトップを移動しないようにしています。 nvidia-settingsでいうところのSeparate X screenという設定です。

気がついたらフォントの大きさがそれぞれのディスプレイXfce上で違った大きさになっていました。Xfceの設定パネルでは「外観」→「Font」で設定が変更できますが、ディスプレイ毎の説明はないので、不可解な動きに戸惑ってしまいました。

環境について

いまのメインデスクトップ環境は次のような環境になっています。

  • CPU: AMD Phenom(tm) II X4 905e (4 core, 2.5GHz)
  • Motherboard: ASUS M5A97 PRO
  • Memory: 16GB (4GBx4)
  • Video Card: NVIDIA GPU GeForce GTS 450
  • Monitor0: EIZO FlexScan L567 (17inch.)
  • Monitor1: EIZO FlexScan L567 (17inch.)

Xfceのフォント設定

設定は「Xfce4設定マネージャー」(xfce4-settings-manager)から変更する事ができます。 フォントは「外観」の「Fonts」タブから変更することができます。

xfce4 Settingsウィンドウ

ディスプレイ毎にフォント設定がおかしくなる現状の解決について

Gnomeではフォントがおかしくならないので、Xfceに原因があるのかなと最初は考えました。

実際Xfceのオプションで改善する事ができたのですが、xdpyinfoはScreen毎に違うDPI設定を返していて、これが原因と考えるのが妥当そうです。

xdpyinfo |grep -i -e resol -e '#' の出力結果


screen #0:
  resolution:    95x96 dots per inch
screen #1:
  resolution:    75x75 dots per inch
解決策

Xfceでは「Fonts」タグの中に「Custom DPI Setting」チェックボックスがあるので、これにチェックを入れて問題は解決しました。

Custom DPI Settingチェックボックス

原因について

DPIが極端に大きかったり、小さかったりした場合に調整する「Custom DPI Setting」が必要な状況がよく分からなかったので、少し調べてみました。

ログを除いてみると、原因は同じディスプレイを使ってMulti Displayにしている事だと分かりました。

grep -C 1 DPI /var/log/Xorg.0.log 出力結果


(II) Apr 12 18:10:15 NVIDIA(0): Virtual screen size determined to be 1280 x 1024
(--) Apr 12 18:10:15 NVIDIA(0): DPI set to (95, 96); computed from "UseEdidDpi" X config
(--) Apr 12 18:10:15 NVIDIA(0):     option
--
(WW) Apr 12 18:10:15 NVIDIA(1): Cannot find size of first mode for Eizo L567 (DFP-0); cannot
(WW) Apr 12 18:10:15 NVIDIA(1):     compute DPI from Eizo L567 (DFP-0)'s EDID.
(==) Apr 12 18:10:15 NVIDIA(1): DPI set to (75, 75); computed from built-in default
(--) Depth 24 pixmap format is 32 bpp

このcannot compute DPIをキーワードに検索してみると、いくつかドキュメントがみつかります。 IgnoreEDIDオプションはうまく動かなかったので、今回はDisplaySizeを指定する事にしました。

xdpyinfoではうまく調整できている方のディスプレイサイズがわかります。 dimensions: 1280x1024 pixels (342x271 millimeters)

/etc/X11/xorg.confのバックアップを取ってから、MonitorセクションにDisplaySizeを追加しました。

xorg.conf変更後のMonitor1用設定

Section "Monitor"
    Identifier     "Monitor1"
    VendorName     "Unknown"
    ModelName      "Eizo L567"
    HorizSync       31.0 - 64.0
    VertRefresh     59.0 - 61.0

    Option         "DPMS"
    DisplaySize 342 270
EndSection

最初は342 271と、そのままの数値を書いていたのですが、342x274と計算されてしまったので、1つ小さい数を指定したところうまく数字が合いました。 ここの挙動はまったく不明ですが、今回はここら辺で終りにしようと思います。

最後に

最終的にはCustom DPI Settingの機能は使わずに動いています。 ここまでやらなくても実用上は問題なかったのですが、xdpyinfoレベルで同じであればアプリケーションの挙動が両方のディスプレイで同じになる裏付けになるので安心できます。

解決後の xdpyinfo | grep -C1 resolution 出力結果

  dimensions:    1280x1024 pixels (342x271 millimeters)
  resolution:    95x96 dots per inch
  depths (7):    24, 1, 4, 8, 15, 16, 32
--
  dimensions:    1280x1024 pixels (342x271 millimeters)
  resolution:    95x96 dots per inch
  depths (7):    24, 1, 4, 8, 15, 16, 32

2011/01/19

StunnelのクライアントモードでCouchDBに接続する

CouchDB自体には通信を暗号化する機能が1.1系列からしか準備されていないので、stunnelを使っています。

普段は「CouchDB: Ruby CouchモジュールをDigest認証対応にする」ようにSSL接続に対応したクライアントを使っています。

とはいえCouchDB自体には、SSL接続に対応した機能がないので、CouchDB同士を接続する必要があるレプリケーション(Replication)を有効にするためにStunnelのクライアント機能を使ってみました。

実際にはCouchDBの間にはインターネットがありますが、おおまかなシステム構成図は次のとおりです。

Stunnel Client: System Overview

Stunnelサーバ設定の確認

CouchDBの起動時にdefault/couchdbファイルに書かれているstunnelを起動するコマンドラインは次のようになっています。

/usr/bin/stunnel -v 3 -a /usr/local/etc/couchdb/sslcerts -d :::6984 -r 127.0.0.1:5984

-aオプションに指定しているディレクトリの中は次のような感じです。

$ sudo ls -l /usr/local/etc/couchdb/sslcerts
lrwxrwxrwx 1 root couchdb   17 Dec  2 11:44 22f12cbd.0 -> demoCA.cacert.pem
lrwxrwxrwx 1 root couchdb   23 Dec  2 11:44 6b0ab199.0 -> stunnel.client.cert.pem
-rw-r----- 1 root root    3664 Dec  2 10:23 demoCA.cacert.pem
-rw-r--r-- 1 root couchdb 3494 Dec  2 11:34 stunnel.client.cert.pem

Stunnelクライアントの設定

サーバ側はSSLクライアント認証が有効なので、普通に接続しようとすると失敗します。

接続用Certificateファイルの作成

いつも通りにCA.plを使って、newcert.pem,newkey.pemファイルを作成します。

CA.plへのパスはUbuntu 10.04 LTSでのものです。環境毎に格納場所が違いますので、locate CA.plで探すか、手動でopensslを実行してください。

$ /usr/lib/ssl/misc/CA.pl -newreq
$ /usr/lib/ssl/misc/CA.pl -sign
$ rm newreq.pem
$ cp newcert.pem couchdb.client.cert.pem
$ cp newkey.pem  couchdb.client.key.pem
$ openssl rsa < couchdb.client.key.pem > couchdb.client.nokey.pem
$ cat couchdb.client.cert.pem couchdb.client.nokey.pem > couchdb.client.pem

最終的にはcouchdb.client.pemファイルを使い、stunnelをクライアント化します。

Stunnelサーバ側でのCertificateファイルの更新

最初のコマンドラインにあるようにStunnelサーバは接続に使うcertificateを/usr/local/etc/couchdb/sslcertsに保存しています。

今回作成したcouchdb.client.cert.pemファイルと"CA.pl -sign"の実行時に使ったCAのcacert.pemファイルをstunnelサーバ側に転送しておきます。

Stunnelサーバ側で次のような操作をしておきます。 cacert.pemが既に存在していて、内容が同じであれば省いてください。 内容が違う場合はファイル名を変更してコピーしておく必要があります。

$ sudo cp couchdb.client.cert.pem cacert.pem  /usr/local/etc/couchdb/sslcerts
$ sudo c_rehash  /usr/local/etc/couchdb/sslcerts
Stunnelクライアントモードでの起動

基本的には次のようなコマンドラインでStunnelサーバに接続します。

/usr/bin/stunnel -c -p /usr/local/etc/couchdb/sslcerts/couchdb.client.pem" -d 127.0.0.1:5985 -r 192.168.x.x:6984

ここでの192.168.x.xはStunnelサーバのIPアドレスです。

Stunnelクライアント側にはcouchdb.client.pemファイルをコピーしておき、やはり次のようなコマンドを実行します。

$ sudo cp couchdb.client.pem /usr/local/etc/couchdb/sslcerts/
$ sudo /usr/bin/stunnel -c -p /usr/local/etc/couchdb/sslcerts/couchdb.client.pem" -d 127.0.0.1:5985 -r 192.168.x.x:6984
$ curl -u admin:xxxxxx http://localhost/:5985/_all_dbs

サーバ側はBasic認証が有効になっているのでadmin:xxxxxsはID(admin)とパスワード(xxxxxx)を':'(コロン)で区切って指定しています。

セキュリティ上の考察

Stunnelクライアントからはログインできるユーザは全てサーバに到達する事が可能になります。

もちろんパスワードがわからなければ接続できませんが、curlコマンドラインを起動する場合にはps auxwwwの出力にはでないですが、bash等、使っているシェルのhistoryには記録されます。

それが気になることはあまりないとは思いますが、こういうところにも気を配る必要があるかないか、環境はちゃんと理解しておくことが必要です。

さいごに

とりあえず、ここまでで無事にレプリケーションを有効にする準備ができました。

やっぱりセキュリティ周りの作りはちょっと不安なんですよね。

2011/01/07

DTIのVPSサービスで、Default: DROPなiptablesの設定をしてみた

OpenVZを使っているDTIのVPSサービスでは、各VM内からはカーネルモジュールを動的に読み込む事ができません。

あらかじめ準備されたカーネルにはip6tablesが使うモジュールが設定されていないために、コマンドを実行することができない事に今日になって気がつきました。

IPv6対応を謳うサービスで、サーバ用インスタンスを提供しているのであれば、セキュリティを強化するための手段が一つない事になるので、少しがっかりしました。

さて気をとりなおして、IPv4用にiptablesの設定をしたので、その作業メモです。

IPv4用にiptablesを設定する

特別な設定はしませんが、INPUT/OUTPUT/FORWARDのデフォルトルールをDROPにした上でルールを設定しています。

iptablesのログをCouchDBに入れて郵便番号情報と似たようなインタフェースで検索できるようにしていますが、サンプルで動かしている自宅の自作ブロードバンドルータのログをいろいろみていると22番ポート(ssh)と445番ポート(microsoft-ds/CIFS)へのアクセスが非常に多いのがわかります。

あとはDDoSのためにIPアドレスを詐称したパケットが捏造されているのか、ICMPパケットもありましたし、いきなりACK,SYNが送られてきているケースもあるようでした。

いくらポートを閉じているとはいえ、いろいろ迷惑をかけるのもあれなので、VPSサーバでもiptablesを設定して、積極的にDROPするようにしています。

iptables設定用スクリプト全体

#!/bin/bash

umask 022
PATH=/usr/sbin:/sbin:$PATH

## reset all settings
iptables -F
iptables -Z
iptables -X

## default rule is DROP, but all unexpected connection will be logged later.
iptables -P FORWARD DROP
iptables -P INPUT DROP
iptables -P OUTPUT DROP

## define logging rules
iptables -N loaccept
iptables -A loaccept -m limit --limit 30/minute -j LOG --log-prefix "fw local accept "
iptables -A loaccept -j ACCEPT
iptables -N fwaccept
iptables -A fwaccept -m limit --limit 30/minute -j LOG --log-prefix "fw forward accept "
iptables -A fwaccept -j ACCEPT
iptables -N fwdrop
iptables -A fwdrop -m limit --limit 30/minute -j LOG --log-prefix "fw forward drop "
iptables -A fwdrop -j DROP
iptables -N inaccept
iptables -A inaccept -m limit --limit 30/minute -j LOG --log-prefix "fw input accept "
iptables -A inaccept -j ACCEPT
iptables -N indrop
iptables -A indrop -m limit --limit 30/minute -j LOG --log-prefix "fw input drop "
iptables -A indrop -j DROP
iptables -N outaccept
iptables -A outaccept -m limit --limit 30/minute -j LOG --log-prefix "fw output accept "
iptables -A outaccept -j ACCEPT
iptables -N outdrop
iptables -A outdrop -m limit --limit 30/minute -j LOG --log-prefix "fw output drop "
iptables -A outdrop -j DROP

## allow all loopback connection
iptables -A INPUT  -i lo -j loaccept
iptables -A OUTPUT -o lo -j loaccept

## logging all connection
iptables -A INPUT -p icmp --icmp-type echo-request -j inaccept
iptables -A INPUT -p icmp --icmp-type redirect -j indrop
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state NEW -p tcp --dport 4949 -j inaccept  ## for munin
iptables -A INPUT -m state --state NEW -p tcp --dport 443 -j inaccept   ## for web
iptables -A INPUT -m state --state NEW -p tcp --dport 80 -j inaccept    ## for web
iptables -A INPUT -m state --state NEW -p tcp --dport 23 -j inaccept    ## for ssh
iptables -A INPUT -m state --state NEW -p tcp --dport 25 -j inaccept    ## for smtp
iptables -A INPUT -m state --state NEW -p tcp --dport 53 -j inaccept    ## for dns
iptables -A INPUT -m state --state NEW -p udp --dport 53 -j inaccept    ## for dns
iptables -A INPUT -j indrop
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state NEW -j outaccept
iptables -A OUTPUT -j outdrop
iptables -A FORWARD -j fwdrop

## uncomment this after checking above settings.
## iptables-save > /etc/network/iptables.restored

大抵の方はSSH用ポートが変更されているので、ここで"23"と設定しているSSH用のポート番号は3843番などに適宜変更する必要がありそうです。

一度スクリプトを実行して動作を確認してから問題がなければ、再起動後も適用されるように最後のコメントアウトを外すか、手動でiptables-saveを実行して、/etc/network/iptables.restoredファイルを更新しておきます。

そして、作成したファイルが起動時に読み込まれるように/etc/network/if-up.d/iptablesファイルを作成しておきます。

#!/bin/bash

BASEDIR="$(dirname $0)"
iptables-restore < "${BASEDIR}/../iptables.restored"

最後に実行権限を与えておきます。

$ sudo chmod 700 /etc/network/if-up.d/iptables

これでIPv4用の設定は以上で、ログの内容は /var/log/kern.log に書き出されます。

syslogの機能をフルに使うのであれば、 -j LOG行で--log-level debugなどの設定をポリシーに従って設定して、facilityを分けたり適切なメッセージを送信する事もできると思います。

2010/12/02

DTIのServersMan@VPSでdebianを選択して最初にやったこと

以前から気になっていたDTIのServersMan@VPSでdebianがOSとして選択できるようになってしばらく経ちましたが、Alixより少しパワーが欲しかったのと、Debian Squeezeのテスト環境を兼ねて使ってみることにしました。

Debian LennyをSqueezeにする手順はまとめている方がいらっしゃるのと、それほど難しくないので、それ以前にやった事のメモを残しておきます。

初回ログインの第一印象

ssh経由とはいえ、rootユーザでのログインはなんだか斬新な感じです。

世界中からパスワードが分かればログインできるというのも、なんとなく不安な感じです。

ゆくゆくは作業用の一般ユーザを作るとして、それ以前にやった方がいい事がいくつかあったのでまとめておきます。

localesの設定

apt-getなどPerlを呼び出す場面ではロケール関連のエラーが表示されます。

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = "ja_JP.UTF-8",
	LC_ALL = (unset),
	LANG = "ja_JP.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").

ロケールが適切に設定されていない事が原因なので再設定します。

# dpkg-reconfigure locales

一覧からlocaleを選択しますが、おすすめは次の3つです。

  • en_US.UTF-8
  • ja_JP.EUC-JP
  • ja_JP.UTF-8

EUCは時代遅れですが、まだ古いrubyを使っていてEUCで動いているアプリケーションもあるので、念のため選択しています。

最終的に選択した3つのロケール

デフォルトロケールとしてen_US.UTF-8を選択しています。

パッケージ更新の前に/etc/apt/sources.listの調整

デフォルトの設定ではftp.debian.orgにアクセスしようとします。

日本国内にあるサーバから海外にアクセスするのは遅い上に無駄なので、これを修正します。

修正後の/etc/apt/sources.listファイル

deb http://ftp.jp.debian.org/debian/ lenny main
deb-src http://ftp.jp.debian.org/debian/ lenny main

deb http://ftp.riken.jp/Linux/debian/debian-security lenny/updates main
deb-src http://ftp.riken.jp/Linux/debian/debian-security lenny/updates main
#deb http://security.debian.org/ lenny/updates main
#deb-src http://security.debian.org/ lenny/updates main

deb http://ftp2.jp.debian.org/debian-volatile lenny/volatile main
deb-src http://ftp2.jp.debian.org/debian-volatile lenny/volatile main
#deb http://volatile.debian.org/debian-volatile lenny/volatile main
#deb-src http://volatile.debian.org/debian-volatile lenny/volatile main

volatileやsecurityパッケージは国内のミラーサーバからだと失敗した経験があるので、コメントアウトしたものも残しておきます。必要に応じて切り替えてください。

サーバ名は volatileパッケージのミラーsecurityパッケージのミラー(ftp.riken.jpを参照)の情報を参照して変更することもできます。

パス名が変更になる場合もあるので動いている設定とリストの記述をよくみてください。

不要なパッケージの削除

自分の目的にはdbusやlprngは不要なので、まとめて削除しました。

# apt-get remove lprng dbus sasl2-bin libnss-ldap
apacheを起動しないように設定

開いているポートの確認はnetstat -naなどで行ないますが、apacheはしばらく使わないので止めておきます。

# update-rc.d -f apache2 remove

起動時や停止時にapache2を操作する/etc/init.d/apache2スクリプトへのシンボクックリンクを/etc/rc?.d/*apache2シンボリックリンクを削除してくれます。

SSH経由でのログインを制限する

できればLinuxなどのクライアントの方が良いですが、ssh-keygenを使ってVPSログイン用のSSHの公開鍵と秘密鍵のペアを作ってSSHのパスワードログインは使わないようにします。

# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): /root/id_rsa_vpslogin
Enter passphrase (empty for no passphrase): xxxxxxxxxx
Enter same passphrase again: xxxxxxxxxx
Your identification has been saved in /root/id_rsa_vpslogin.
Your public key has been saved in /root/id_rsa_vpslogin.pub.
The key fingerprint is:
c7:a1:a3:ac:61:9b:1d:d0:d8:26:32:fe:0e:d7:aa:2e root@dti-vps-srv02
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|          .      |
|     +   o .     |
|  o + + S o      |
| . o * . o       |
|  o + =          |
|E  = B .         |
| oooB .          |
+-----------------+

これで2つのファイルが手に入ります。

  • /root/id_rsa_vpslogin - 秘密鍵
  • /root/id_rsa_vpslogin.pub - 公開鍵
/root/id_rsa_vpslogin - 秘密鍵の取り扱い

VPSサーバでkeygenを実行した場合は、このファイルをクライアントマシンにコピーしてサーバからは削除します。

/root/id_rsa_vpslogin.pub - 公開鍵の取り扱い

このファイルは、VPSサーバ上の /root/.ssh/authorized_keys として配置します。

VPSサーバ上でkeygenを実行していればmvするだけです。

# mkdir -p /root/.ssh
# chmod 0700 /root/.ssh
# mv /root/id_rsa_vpslogin.pub /root/.ssh/authorized_keys
# chmod 600 /root/.ssh/authorized_keys
鍵ファイルを使ったログインテスト

クライアントマシンにある id_rsa_vpslogin ファイルを使って、VPSサーバにログインします。

$ ssh -i id_rsa_vpslogin root@127.x.x.x

パスワードを聞かれずにログインできれば終了です。

SSHでパスワードを使ったログインを禁止する前に

VPSの特徴として、リモートでログインできなくなったら終りというのがあります。

一般ユーザでログインして、sudoを使おうとした場合には、ホスト名とIPアドレスの変換が最低でも/etc/hostsを経由して行なえなければいけません。

DNSにも/etc/hostsにも記述のないホスト名を/etc/hostnameに記述すると、次回の再起動後にsudoが使えなくなります。

パスワードを使ったログインを禁止するのは簡単ですが、少なくともrootと一般ユーザの2つに別々のキーを作成しておき、ログインできるかどうかのテストを入念に行なう必要があります。

一般ユーザでログインできればsuコマンドでrootになれますが、いろいろ調子に乗って変更すると落とし穴にはまる可能性があるので注意が必要です。

最後にパスワードを使ったログインを禁止する

いろいろテストを入念にやった最後の最後にパスワードを使ったログインを禁止しておきます。

この作業は自信がなければ行なわずに、確信が持ててから行なう事が必要です。

ま、始めたばかりですから初期化すればいいんですけどね。

変更後の/etc/ssh/sshd_configファイル編集個所

# Change to no to disable tunnelled clear text passwords
PasswordAuthentication no

いろいろなオーケストレーションツールはrootでのログインとか、公開鍵を使ったssh経由でのログインを必要としますが、パスワードを設定できなかったりすると嫌ですね。

SSHを使えば安全というものでもないので、ssh-keygenで鍵を作成する時にはパスフレーズを必ず適当なフレーズで設定してあげてください。

さいごに

ServersMan@VPSでのdebianの選択は、経験というよりも責任を自分で取る覚悟がないと、お勧めできないですね。 パッケージの多さは魅力的なんですが、しばらくすると時代遅れになりますし、いざという時には自分の腕が頼りです。

自習目的ならいいですが、不用意にポートを開けて不幸を呼び込まないか心配な面もあります。

CentOSはパッケージの数が少ないですが、ビジネスユースならまずはRedHatベースのCentOSに慣れるべきだと思います。 まぁビジネスのためには「慣れるべき」とはいえ、CentOSを勧める理由は常に○×養成ギブス的な意味合いが強いのが、ちょっと悲しいところです。

ServersMan@VPSには、いろいろな変更を加えていますが、とりあえず最低限はこれぐらい必要でしょう。 できれば推測されにくい名前の一般ユーザでログインして、rootでのログインも禁止( PermitRootLogin yes on /etc/ssh/sshd_config)してください。

2010/09/23

beagleboard用にlinuxカーネルを新しくしてみた

手元のbeagleboardのスペックは次のようになっています。

  • Rev. C3
  • X-Loader 1.4.2 (Feb 19 2009 - 12:01:24)
  • U-Boot 2009.01-dirty (Feb 19 2009 - 12:22:31)

以前は http://rcn-ee.net/deb/kernel/beagle/lenny/にあったbeagleboard用のkernelの配布場所が、サーバはそのままにディレクトリが /deb/lenny/へ変更になっていました。

beagleboard用にカーネルを新しくしたので、そこを踏まえてメモを残しておきます。

導入するkernelバージョンを決める

最近はkernel.orgをみるとstableなカーネルのバージョンが、かなり多数あります。

ここはstableの安定板である2.6.35.5をターゲットに、beagleboard上で現在使っている2.6.32.11-x13を置き換えることにしました。

さっそく開始

http://rcn-ee.net/deb/lenny/の2.6.35.5-x4/install-me.shを使う事にします。

beagleboardはUSB経由でLANに接続しているので、作業は全てbeagleboard上で行なうことにしました。

作業はとっても簡単

以前と比べればinstall-me.shは安定した動きをするようで、./tempではなく/tmpを使うようにしたり、ディレクトリを作成する作業もsudo経由で行なわれるなど権限に関する問題はほぼなくなったようです。

$ cd
$ wget http://rcn-ee.net/deb/lenny/v2.6.35.5-x4/install-me.sh
$ /bin/bash install-me.sh

これだけで作業は完了しました。

気になっていたhdparmの結果を確認してみる

# /sbin/hdparm -t /dev/mmcblk0

hdparmの出力結果

/dev/mmcblk0:
 Timing buffered disk reads:   54 MB in  3.02 seconds =  17.89 MB/sec

作業前は約5MB/secでしたが、現在はSDカードのスペックをほぼフルに出せています。

これが一番の目的だったので、もうしばらく遊べそうです。 beagleboard-xMもdigikey日本版で扱いが始まりましたが、買う余裕もないし、しばらくは手を出さないつもりです。

2010/09/10

DRBDの不整合状態を修正してみた

DRBDをUbuntu 8.04でテストした時には、debian lennyとの間でocfs2がうまく動かなかったのですが、 Ubuntu 10.04になってからは問題なく動いていました。

ある時、vmwareが動かない事で/etc/rc2.d/以下のスクリプトの大半が実行されていない事に気がついたのですが、原因はDRBDでした。

drbdadmコマンドを使うだけで解決したのですが、単純に設定だけじゃなくてDRBDの裏の動きもある程度把握していないと複雑な状況に対応できないかなと感じました。

初期症状

いつの間にかDRBDのステータスが以下のようになっていまいました。

この結果、/etc/rc2.d/S06drbdが終了せずにいつまでも接続待ちのままプロセスが残り、後続の/etc/rc2.dにあるスクリプトが実行されない状態になってしまいました。

回復させるために手動で停止するか、/etc/rc2.d/S06drbd stopを実行して、処理を継続させる必要がありました。

主に参照する側の/etc/init.d/drbd status出力

drbd driver loaded OK; device status:
version: 8.3.7 (api:88/proto:86-91)
GIT-hash: ea9e28dbff98e331a62bcbcc63a6135808fe2917 build by root@athlon, 2010-08-04 17:46:47
m:res  cs            ro               ds                 p  mounted  fstype
0:r0   WFConnection  Primary/Unknown  UpToDate/DUnknown  C

主に書き込みが発生する側の/etc/init.d/drbd status出力

drbd driver loaded OK; device status:
version: 8.0.14 (api:86/proto:86)
GIT-hash: bb447522fc9a87d0069b7e14f0234911ebdab0f7 build by phil@fat-tyre, 2008-11-12 16:40:33
m:res  cs          st               ds                 p  mounted  fstype
0:r0   StandAlone  Primary/Unknown  UpToDate/DUnknown  -

対応方法

一方は単純に接続待ちになり、もう片方は StandAlone 状態になっていたので、StandAloneの方から手動で接続状態にすることにします。

もしどちらがPrimaryになるか自信がなければ、事前に不要な片側を初期化しておくのがベストでしょう。

$ sudo /sbin/drbdadm connect r0

この後でstatusを確認すると、無事に同期が始まっていました。

同期中の/etc/init.d/drbd status出力

drbd driver loaded OK; device status:
version: 8.3.7 (api:88/proto:86-91)
GIT-hash: ea9e28dbff98e331a62bcbcc63a6135808fe2917 build by root@athlon, 2010-08-04 17:46:47
m:res  cs          ro                 ds                     p  mounted  fstype
0:r0   SyncTarget  Secondary/Primary  Inconsistent/UpToDate  C
...    sync'ed:    46.9%              (1006128/1884328)K

ただ、ステータスが Primary/Secondary となっていたので、 WFConnection 状態だった側でPrimaryにしました。

$ sudo /sbin/drbdadm -- -o primary r0

最終的に復旧した状態

drbd driver loaded OK; device status:
version: 8.3.7 (api:88/proto:86-91)
GIT-hash: ea9e28dbff98e331a62bcbcc63a6135808fe2917 build by root@athlon, 2010-08-04 17:46:47
m:res  cs         ro               ds                 p  mounted  fstype
0:r0   Connected  Primary/Primary  UpToDate/UpToDate  C

2010/08/30

VirtualBoxでのCentOSインストールの自動化

Mac(Mac mini; MacOS X 10.6.4)で動いているVirtualBoxで、kickstartの仕組みを使ってCentOSのインストールを自動化しようとしてみました。

ただ手続きが多いので、基本的な動きを確認するためにVMを起動すると自動でCentOSのインストールが開始するところまでを確認しました。

全体の流れ

Kickstartを自動で開始するディスクの作成

mkisofsコマンドをmacportなどで導入すればMacでも可能そうでしたが、面倒なのでここだけはlinux(Ubuntu 10.04 LTS)で作業しています。

$ sudo mount -o loop CentOS-5.5-x86_64-netinstall.iso /mnt/iso
$ mkdir centos55netinst
$ cd  centos55netinst

/mnt/iso以下はread-onlyなので、作成したディレクトリにコピーを作成します。

$ rsync -av /mnt/iso/. .

自動的にKickstartを開始するようにisolinux.cfgファイルを編集します。

$ vi isolinux/isolinux.cfg

isolinux/isolinux.cfgファイル

default linux
prompt 1
timeout 10
display boot.msg
F1 boot.msg
F2 options.msg
F3 general.msg
F4 param.msg
F5 rescue.msg
label linux
  kernel vmlinuz
  append initrd=initrd.img ks=hd:fd0:/ks.cfg
label local
  localboot 1
label memtest86
  kernel memtest
  append -

isolinux.cfgだけを変更したISOイメージを ../centos55netinst.img に作成します。

$ sudo mkisofs -R -J -no-emul-boot -boot-load-size 4 -boot-info-table -o ../centos55netinst.img -c isolinux/boot.cat -b isolinux/isolinux.bin .

mkisofsのオプションは使い方によって、 -T , -p といったオプションを工夫しても良いかもしれません。

ks.cfgファイルの準備

一度は手動でCentOSを入れると配置される /root/anaconda-ks.cfg ファイルをベースにしました。

サーバにするために不要なものをいろいろ省くと次のようになります。

ks.cfgファイル

# Kickstart file automatically generated by anaconda.
install
url --url http://rsync.atworks.co.jp/centos/5.5/os/x86_64
lang en_US.UTF-8
keyboard us
network --device eth0 --bootproto dhcp --hostname centos.vb.localdomain
rootpw --iscrypted $1$./9drDbb$nWXlnh/h4517xgxRZBTsS/
firewall --enabled --port=22:tcp
authconfig --enableshadow --enablemd5
selinux --permissive
timezone --utc Asia/Tokyo
bootloader --location=mbr --driveorder=sda
text
halt
# The following is the partition information you requested
# Note that any partitions you deleted are not expressed
# here so unless you clear all partitions first, this is
# not guaranteed to work
clearpart --all --drives=sda --initlabel
part /boot --fstype ext3 --size=100 --ondisk=sda
part pv.2 --size=0 --grow --ondisk=sda
volgroup VolGroup00 --pesize=32768 pv.2
logvol / --fstype ext3 --name=LogVol00 --vgname=VolGroup00 --size=1024 --grow
logvol swap --fstype swap --name=LogVol01 --vgname=VolGroup00 --size=512 --grow --maxsize=1024

%packages
@base
@core
@network-server
@server-cfg
@text-internet
@web-server
keyutils
trousers
fipscheck
device-mapper-multipath
openssh-server

起動すると自動的にパーティションの削除から開始するため、意図せずにディスクの内容を削除してしまう可能性がそれなりにある点に注意してください。

フロッピーイメージの作成

Mac上でフロッピーイメージを作成するには、いくつかの方法がありましたが、今回は自動化するためにコマンドラインで出来る方法を採用しました。

カレントディレクトリにks.cfgがあると仮定して、floppy.imgを作成し、その中にks.cfgをコピーするところまでを試しています。

$ dd if=/dev/zero of=floppy.img bs=1024 count=1440
$ hdiutil attach -nomount floppy.img | while read dev
do
  newfs_msdos -f 1440 -v centos55 $dev
  hdiutil detach $dev 
done
$ hdiutil mount floppy.img | while read dev fs
do
  cp ks.cfg $fs
  hdiutil detach $dev
done

さいごに

作成したファイルを使って、VirtualBoxのインスタンスを起動すると自動的にインストールが完了しました。

とはいえ、インスタンスの設定ではいくつか必要な操作があります。

  • 起動順から「フロッピー」を削除
  • 「フロッピーコントローラ」の追加
  • 「フロッピーコントローラ」直下のks.cfgを含むfloppy.imgの追加

あとはVirtualBoxにインスタンスの構成を行なって、カスタマイズしたks.cfgを作成すれば自動的にインスタンスを増やす事は何とかなりそうです。

2010/07/19

PS3 linux (Fedra Core 9)にMARSライブラリを導入してみる

いまさらですが、 フィックスターズのWebサイトをみていてMARSライブラリを導入してみました。 fixstarsのサイトでは1.1.4までの情報が載っていますが、現時点での最新版は1.1.5のようです。

コンパイル済みのバイナリパッケージも配布されていましたが、自分の環境にフィットするか自信がなかったのでパッケージを作成することにしました。

今回の作業はFedra Core 9にCellSDK 3.1の環境で行なっています。

~/.rpmmacrosの準備とパッケージの作成

一般ユーザのHOMEディレクトリ以下で作業をするために~/.rpmmacrosファイルを準備します。 これがないと/usr/src/redhatにファイルが作成されるためrootユーザで作業をしなければいけませんが、そうする利点はないので、一般ユーザで作業を進めます。

$ echo %_topdir $HOME/rpm > ~/.rpmmacros

.rpmmacros ファイルで指定するディレクトリ名には ~/ などは使えないので、 ユーザ毎にフィアルを配布せずにskeltonファイルを準備したい場合には次のようにするのが良さそうです。

ディレクトリ名を決め打ちしない~/.rpmmacrosファイル

%_topdir %(echo $HOME)/rpm

.rpmmacrosファイルの準備ができたらパッケージを作成します。

$ sudo yum update
$ wget http://ftp.uk.linux.org/pub/linux/Sony-PS3/mars/latest/mars-1.1.5-1.src.rpm

ビルドに必要なディレクトリはあらかじめ作っておく必要があります。 簡単なのは決め打ちでディレクトリを作成しておく方法でしょう。

$ mkdir -p ~/rpm/{BUILD,RPMS/ppc64,SOURCES,SPECS}
$ rpm -ivh mars-1.1.5-1.src.rpm

これで~/rpm/SPECS/以下にmars.specファイルが作成されたので、rpmbuildコマンドでパッケージを作成します。


specファイルを編集する必要がなければ、"rpm -ivh"と"rpmbuild -bb"を合わせて次のコマンドでもパッケージを作成することができます。

$ rpmbuild --rebuild mars-1.1.5-1.src.rpm

いずれの方法でもrpmbuildを実行してエラーになります。

依存関係にある未インストールのパッケージを示すエラーメッセージ

error: Failed build dependencies:
	numactl-devel is needed by mars-1.1.5-1.ppc64

numactlパッケージもwww.bsc.esで配布されています。 apt-getでは入れられないので、やはりパッケージを作成しました。

$ wget http://www.bsc.es/projects/deepcomputing/linuxoncell/cellsimulator/sdk3.0/SRPMS/numactl-0.9.10-1.src.rpm
$ rpm -ivh numactl-0.9.10-1.src.rpm
$ cd ~/rpm/SPECS
$ rpmbuild -bb numactl.spec
$ sudo rpm -ivh ~/rpm/RPMS/ppc64/numactl-devel-0.9.10-1.ppc64.rpm
$ rpmbuild -bb mars.spec
$ sudo rpm -ivh ~/rpm/RPMS/ppc64/mars-*.rpm

ここまでで、一応パッケージは出きたのですが、spu版のzlib, opnessh-engineを試す際に32bit版ライブラリがないために問題がでました。

32bit版marsライブラリの作成

rpmbuildコマンドに --target ppc を渡すことで32bit版のパッケージを作成することができます。

$ mkdir ~/rpm/RPMS/ppc
$ cd ~/rpm/SPECS
$ rpmbuild -bb --target ppc numactl.spec
$ sudo rpm -ivh ../RPMS/ppc/numactl-devel-0.9.10-1.ppc.rpm
$ rpmbuild -bb --target ppc mars.spec
$ sudo rpm -ivh ../RPMS/ppc/mars-1.1.5-1.ppc.rpm

とりあえずこれでzlibやopenssh-enginesのコードをコンパイルする準備が出きました。

zlibからのmgzipの作成

srcパッケージを配布しているディレクトリにgzipの圧縮をspu対応にさせたサンプルが置かれています。

ただ対応しているバージョンのzlib-1.2.3は不具合がみつかり、zlib-1.2.5に置き換えられていて、現在はダウンロードができずにサンプルをコンパイルする事ができませんでした。

とりあえずMakefileを編集して、1.2.5をダウンロードするように修正しました。

zlib-mars/Makefileの編集個所

--- Makefile.orig	2010-07-18 09:44:32.482284357 +0900
+++ Makefile	2010-07-18 02:24:15.255286359 +0900
@@ -27,7 +27,7 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
-ZLIB=zlib-1.2.3
+ZLIB=zlib-1.2.5
 MGZIP=smp_mgzip_1.2c
 HOST_FLAG=-m32
 LIBS=-lspe2 -lmars_task -lmars_base

zlib-1.2.5_mars.patchファイルが作成できていないので、makeはエラーで停止します。 そこから手動で修正作業をして、最終的にzlib-1.2.5_mars.patchファイルを作成します。

$ cd zlib-1.2.5
$ patch -p1 < ../zlib-1.2.3_mars.patch

手動でzlib-1.2.5に対してzlib-1.2.3_mars.patchを当てた後は、*.rejファイルをみながら手で編集していきました。

zlib-1.2.3_mars.patch適用後の

diff -upNr zlib-1.2.5/zconf.h zlib-1.2.5.ported/zconf.h
--- zlib-1.2.5/zconf.h  2010-07-18 09:35:03.643539354 +0900
+++ zlib-1.2.5.ported/zconf.h   2010-07-18 09:18:52.314278202 +0900
@@ -356,7 +356,7 @@ typedef uLong FAR uLongf;
    typedef Byte       *voidp;
 #endif
 
-#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */
+#if 1    /* was set to #if 1 by ./configure */
 #  define Z_HAVE_UNISTD_H
 #endif
 
diff -upNr zlib-1.2.5/zlib.h zlib-1.2.5.ported/zlib.h
--- zlib-1.2.5/zlib.h   2010-07-18 09:35:03.651543213 +0900
+++ zlib-1.2.5.ported/zlib.h    2010-07-18 02:53:42.232281033 +0900
@@ -179,6 +179,7 @@ typedef gz_header FAR *gz_headerp;
 #define Z_MEM_ERROR    (-4)
 #define Z_BUF_ERROR    (-5)
 #define Z_VERSION_ERROR (-6)
+#define Z_CELL_ERROR   (-7)
 /* Return codes for the compression/decompression functions. Negative values
  * are errors, positive values are used for special but normal events.
  */

Makefile.inはMakefile.in.rejファイルを見ながら手で修正しましたが、1.2.5では共有ライブラリも作成できるように1.2.3と比較して変更点が多いため、./configure --staticは通りますが、共有ライブラリも作成できる完全なMakefile.inはできていません。

それでもzlib-1.2.5_mars.patchを作成してみると、mgzipコマンドを手に入れることができました。

$ mv zlib-1.2.5 zlib-1.2.5.ported
$ tar xvzf zlib-1.2.5.tar.gz
$ diff -upNr zlib-1.2.5 zlib-1.2.5.ported > zlib-1.2.5_mars.patch
$ make HOST_FLAG=-m32

timeコマンドの出力は変な感じでしたが、実時間だけでみてもmgzipは2〜3倍程度の速度差があるようです。 これが自分でできるかというと時間がかかり過ぎる感じですが、なんとなく雰囲気は感じられたと思います。

marsサンプルのコンパイル

mars-samplesパッケージを導入すると/usr/share/mars-1.1.5/samples以下にサンプルが導入できます。 このコンパイルには32bit版のライブラリは必要ありませんでした。

そのままrootユーザ権限でmakeしても良いのですが、パッケージとして管理されている領域とは別の場所で行なうのがベストだと思います。

$ cp -r /usr/share/mars-1.1.5/samples .
$ cd samples
$ make

ここにあるhelloディレクトリやscheduleディレクトリにあるサンプルを眺めると、なんとなく概要は掴めると思います。

サンプルのコードを読んで気になったところ

host.cでexternされている変数の定義場所

ディレクトリに配置されている*.cファイルには定義されていない変数(mpu_task_prog)が唐突にexternされているように見えます。

MARSのドキュメントには何も書かれていませんが、makeの出力を確認するとppu-embedspuコマンドの引数にmpu_task_progが表われています。

このコマンドを引数なしに起動すると次のようなメッセージが表示され、symbol名が指定できることがわかりました。

Usage: embedspu [flags] symbol_name input_filename output_filename

        input_filename:  SPU ELF executable to be embedded
        output_filename: Resulting PowerPC object file
        symbol_name:     Name of program handle struct to be defined
        flags:           GCC flags defining PowerPC object file format
                         (e.g. -m32 or -m64)

元々SPEプログラムを組込むための仕組みとして準備されているもののようで、作成されたファイルに定義されているsymbol名をnmコマンドで表示させると変化の様子がわかります。

$ nm mpu_task2.task_o
         U mars_task_get_kernel_id
         U mars_task_get_name
00000000 T mars_task_main
         U printf
$ nm mpu_task2.task_eo 
0000000000000000 D mpu_task2_prog

自分で少し試すだけならMakefileを流用して、同じようなネーミングルールでコードを作成するのが楽そうです。

2010/06/11

64bit Linux向けのflashplayerについて

正式版の10.1がリリースされたこともあって、Adobe LabsのWebサイトを確認したところ、残念ながら "The Flash Player 10.1 64-bit Linux beta is closed. "とのステートメントが掲載されていました。

次期バージョンのアルファ、ベータ版としてリリースして欲しいですが、いまのところ今後の予定などclosed以外の点については決まっていないとしか述べられていません。

nspluginwrapper経由で32bit版を動作させる事が悪いわけではないですが、ちょっと残念な気もします。

2010/05/25

beagleboardとUSBカメラとGPSを車に載せてみた

beagleboard自身は5V1A程度の電源が必要ですが、車のシガーソケットから携帯充電用のUSB端子を接続することで簡単に動かすことができます。

そこにUSB Video Class(UVC)に対応したUSBカメラとGPSを接続することで、走行場所の位置情報を埋め込んだ写真を取るようにしてみました。

助手席に子供の目線ぐらいに付けたカメラから写真を取るとこんな感じになります。

始めて車から取った写真

準備作業

電源の確保

近場のオートバックスでみつけたのがAXSの キューブチャージャー デュアルでした。

これは5V2000mAが取れてヒューズもついていて、USB経由でカメラ(+100mA?)やらGPS(+300mA?)やらをつけても安定して動いています。

GPSモジュール

今回は秋月電子通商の GPSモジュール GT-730F/Lを準備しました。 消費電力がわりと高めといわれていて心配でしたが、性能自体に問題はなさそうなので値段を考えて決めました。

USBカメラ

Video4Linux2で遊んだ前回はBUFFALOの BSW13K05Hを使いましたが、今回はELECOMの UCAM-DLX300Bを使ってみました。

UCAM-DLX300Bでテストしたところ、シャッタスピードの問題なのか、2048x1536だと明る過ぎてしまい、1280x720は640x480と画角が同じで引き伸ばしただけの絵だったので、結局640x480で使っています。

画像は安定していますが、この使い方だと130万画素のBSW13K05Hと比べて違いはそれほど大きくありません。 家の中で使うには良いでしょうね。

撮影した写真の加工

GPSのデータは/dev/ttyUSB0経由で取得することができますが、今回はgpsdとntpdを動かしています。 このgpsdにTCP/IPで接続する事でデータを取得しています。

とりあえずはexiv2コマンドで時刻を修正しています。

beagleboardでの時刻同期

ntpdを-xオプションで動かしたとしても、電池でバックアップされたRTCを持っていないbeagleboardでは、ある程度の時間を調整してあげる必要があります。

これは別のスクリプトでgpsdから時刻情報を取ってきて比較することで、時差が大きい場合にはdate --utc MMDDhhmmYYYYhwclock -wで時刻を合せています。

まとめ

まだしばらくはカメラの固定方法や取り付け位置の高さといった調整が必要そうです。

この記事で取り上げた品々

2010/05/21

cfengine3 free editionの限界

前回まででスタンドアローンでは展開が終って、複数サーバでの管理はどうするのかなとマニュアルを眺めていました。

cfengine2の時と同じように公開鍵を準備してサーバプロセスを起動して、クライアントからアクセスすればmasterfilesに置いたポリシーファイルが配られるのかなぁ、と考えていたのですが、どうやらcfengine3では商用のNovaでないとその機能は使えないようでした。

ポリシーファイルの同期が取れないのはcfengine2から後退している気もしますが、cf-runagent自体は動きました。 もっとも動くだけで、あまり使い勝手はないですけどね。

一般ユーザでもcfengineは動かせますが、とりあえずroot権限でcf-serverdやらcf-agentやらを実行することを考えています。

cf-runagentを動かしてみる

とりあえず2台のcfengine3が動いている環境を準備してから、cf-runagentで他のサーバのrunagentを起動しようと思います。

工夫すれば起動するスクリプトを変更することはできますが、普通はcf-agentをリモートで起動することができます。

クライアント側の設定

cf-runagentを実行する側の設定をします。 まずはkeyファイルを作成しておきます。

$ sudo cf-key

cf-keyによって作成されるファイル

/var/cfengine/ppkeys/localhost.priv
/var/cfengine/ppkeys/localhost.pub

次にpromises.cfファイルを編集します。

/var/cfengine/masterfiles/promises.cf

body runagent control
{
hosts => { "10.0.0.3" };
trustkey => "true";
}

trustkeyは設定しなくても、/var/cfengine/ppkeys/root-10.0.0.3.pubのようなcf-runagentを実行するユーザIDと接続先のIPアドレスを名前にして、相手方の/var/cfengine/ppkeys/localhost.pubを配置しておく事でも同じ結果になります。

trustkeyを"true"に設定しておくと、root-10.0.0.3.pubのようなファイルは自動的に作成されます。

またここで"hosts"に指定したサーバにcf-runagentは接続します。

サーバ側の設定

接続先のcf-serverdの設定を行ないます。 こちらでもkeyファイルを作成しておきます。

$ sudo cf-key

こちら側ではpromises.cfファイルとsite.cfファイルの2個所を編集します。

/var/cfengine/masterfiles/promises.cfファイルの編集個所

body server control
...
allowconnects         => { "127.0.0.1" , "::1", "10.0.0.0/16" };
allowallconnects      => { "127.0.0.1" , "::1", "10.0.0.0/16" };
trustkeysfrom         => { "127.0.0.1" , "::1", "10.0.0.0/16" };
...
}

/var/cfengine/masterfiles/site.cfファイルの編集個所

bundle server access_rules()
{
access:
...
  "/var/cfengine/bin/cf-agent"

    admit => { "127.0.0.1", "10.0.0.0/16" };
...
}

まぁ設定はしてみましたが、cf-runagentが動いても任意のcfengineスクリプトを実行できないようなので、cronから5分間隔でcf-agentが起動している現状では使いどころがなさそうです。

気がついたところ

cf-runagentでunit_*.cfを起動することができない

cf-runagentがcf-serverdに接続すると、body server controlの中でcfruncommandで指定されているプロセスが"--inform"オプション付きで起動されます。

このcfruncommandで指定するコマンドを自作のスクリプトなどに変更すれば、起動するプロセスをコントロールできます。

しかしcf-runagentでは$ sudo cf-runagent -o '-f unit_syslog.cf'といったオプションは受け付けてもらえません。 そのため任意のcfengineスクリプトを実行するといったことはできません。

設定ファイルの複雑化が気になる

cfengine3では body 構文を使って右辺値をグループ化することはできますが、ファイル数が増えていった時にパーミッションを管理したいといった場合には自動生成できると便利なのですが、そういう連携は少し難しそうに思えます。

cfengine3をスタンドアローンで使う場合には、それなりに便利に使う事はできそうです。 ただ統計情報はbdb形式で出力してくれますが、machine readableなログファイルを生成するといった機能は強くないため、他のツールとの連携にはカスタマイズしたログファイルパーサーなどが必要かもしれません。

問題があった場合に自動的に修復するっていうアプローチが正しいとは限らないんですよね…。 特に日本だと全部のインシデントをトラッキングしないといけない場面もあるように思えます。

問題の検出と修正を分けて管理しないといけないような場面ではよくないでしょうね。