2008-02-12

ファイルシステムフルの作り方

備忘。テストとか検証のために、ファイルシステムに空きが無いとかinodeを使い果たした状態を作りたいことがあるけど、LVM使えば簡単やないか。

  1. ファイルシステムに空きが無い状態
  2. colinux(0):~$ sudo lvcreate -L 4M -n lvfull vg01
    colinux(0):~$ sudo mkfs.ext3 /dev/vg01/lvfull
    colinux(0):~$ mkdir test
    colinux(0):~$ sudo mount -t ext3 -o rw /dev/vg01/lvfull test/
    colinux(0):~$ df test/
    Filesystem           1K-blocks      Used Available Use% Mounted on
    /dev/vg01/lvfull          3963      1043      2716  28% /home/lab/test
    colinux(0):~$ dd if=/dev/zero of=test/dummy bs=1K count=3963
    dd: writing `test/dummy': No space left on device
    2705+0 records in
    2704+0 records out
    2768896 bytes transferred in 0.061086 seconds (45327804 bytes/sec)
    
  3. inodeを使い果たした状態
  4. colinux(0):~$ sudo lvcreate -L 4M -n lvfull vg01
    colinux(0):~$ sudo mkfs.ext3 -N 1 /dev/vg01/lvfull
    colinux(0):~$ mkdir test
    colinux(0):~$ sudo mount -t ext3 -o rw /dev/vg01/lvfull test/
    colinux(0):~$ df -i test/
    Filesystem            Inodes   IUsed   IFree IUse% Mounted on
    /dev/vg01/lvfull          16      11       5   69% /home/lab/test
    
Posted at 01:57 in | WriteBacks (0) | Edit

2008-01-25

シェルスクリプト - テスト支援

今、シェルの開発をやっているんだけれども、テストが面倒くさい。で、楽できるようにテスト支援シェルみたいなのを作った。以外に役に立ったし気に入ったので、たまにメンテナンスしつつ使っていきたいなあとか思っていたけど、お馴染みのセキュリティ云々で持ち出すことが出来ない。せっかくだから何か残しておきたいと思うので、作るときのノウハウ的なものをメモ。ちなみにブラックボックス。

  1. テスト時の準備オペレーションを関数化
  2. 異常系のコードを走らせるために、シェルの実行環境とかをいじる必要があったりする。 そういう場合のオペレーションを全部関数化しておく。例えば以下のようなものとか。

    • 設定ファイルなどをリネームする。
    • DBに対してSQLを発行する。
    • DBに対して時間差でSQLを発行する。
    • 任意のディレクトリにごみファイルを作る。
    • 設定ファイルなどの内容を書き換える。
    • 共通系モジュールなどのリターンコードを任意の値に変更する。
    • ファイル・ディレクトリのパーミッションを設定する。
    • などなど。

    あと、これらの関数で変更した内容を元に戻すための仕組みも用意しておく。例えば、リネームだと

    UNIQUE_ID=`date +%Y%m%d%H%M%S`${$}  # どこかでユニークなIDを用意しておく。
    function rename {
      _ORIGINAL=${1}
      mv ${_ORIGINAL} ${_ORIGINAL}${UNIQUE_ID}
      RECOVER="${RECOVER}:mv ${_ORIGINAL}${UNIQUE_ID} ${_ORIGINAL}"
    }
    
    function recover {
      IFS=":"
      for COMMAND in ${RECOVER}; do
        eval ${COMMAND}
      done
      RECOVER=""
    }
    

    とか。(変更内容を戻したいときは、${RECOVER}に登録されたコマンドを実行する。)

    とにかく、準備オペレーションをうまいこと関数化しておき、簡単にあるケースに特化した試験環境を作れるようにしておく。ここでどれだけナイスな関数を作っておくかで試験の効率化具合が決まる。

  3. シェルの実行を関数でラップ
  4. ラッパーの中で、以下の機能を実現する。

    • 戻り値のチェック。
    • 準備オペレーションの内容を元に戻す。
    • テストケース毎に一時停止する。

    こんなかんじ。

    function exec_command {
      _COMMAND=${1}  # 実行コマンド
      _EXPECT=${2}   # 期待する戻り値
      echo ${_COMMAND}
      eval ${_COMMAND}
      _RC=${?}
      if [ ${_RC} -ne ${_EXPECT} ]; then
        echo "No good. Return code => ${_RC}"
        exit 1
      else
        echo "Good. Return code => ${_RC}"
      fi
      read
      recover
      clear
    }
    

    個人的に一番重要なのは、「テストケース毎に一時停止する。」。「テストシェルに通ったのでOKです!」で通じる相手なんてまれで、「シェルをコマンドラインから投入した実行結果のハードコピーが欲しい。」なんてことが多いので、準備オペレーションの内容を元に戻す前で一時停止させる。この仕組みを作っておけば、2個ターミナルを上げて、片方のターミナルでテストシェルを流し、もう片方でハードコピー取得用にコマンドラインからシェルを実行する。ということが楽に出来る。

で、最後に使い方のイメージをのせておくと、
#!/bin/bash

UNIQUE_ID=${$}`date +%Y%m%d`

#----------------------------------
# 試験環境準備オペレーション用関数
#----------------------------------
function rename {
  _ORIGINAL=${1}
  mv ${_ORIGINAL} ${_ORIGINAL}${UNIQUE_ID}
  RECOVER="${RECOVER}:mv ${_ORIGINAL}${UNIQUE_ID} ${_ORIGINAL}"
}

function recover {
  IFS=":"
  for COMMAND in ${RECOVER}; do
    eval ${COMMAND}
  done
  RECOVER=""
}

#------------------
# シェル実行用関数
#------------------
function exec_command {
  _COMMAND=${1}  # 実行コマンド
  _EXPECT=${2}   # 期待する戻り値
  echo ${_COMMAND}
  eval ${_COMMAND}
  _RC=${?}
  if [ ${_RC} -ne ${_EXPECT} ]; then
    echo "No good. Return code => ${_RC}"
    exit 1
  else
    echo "Good. Return code => ${_RC}"
  fi
  read
  recover
  clear
}

trap recover EXIT

# こっからテストを書く。
rename foo
exec_command "/home/foo/bin/test.sh -c hoge" 0

rename hoge
rename foo
exec_command "/home/foo/bin/test.sh -c hoge" 0

試験環境準備オペレーション用関数(ながい。)を別ファイルにまとめ、読み込んでから使うようにしてもいいし、他にも色々工夫できそう。どっかで使う機会があれば、使ってみよう。

Posted at 01:56 in | WriteBacks (2) | Edit

2007-12-27

JavaScriptで15パズル

を作ってみました。→ココ

flickrから「babe」ってタグの写真をとってきて、それをJavaScriptで擬似的に15分割して作成しています。運が良ければべっぴんな姉ちゃんが出てくるけど、その逆も然りでブラクラにもなりうるという感じになっております。機能的にどうとかというのはないので、使ってみれば操作はすぐわかると思います。

作成の動機はJavaScriptの勉強というところなのですが、そもそもはこちらの記事で紹介されていた「Googleの検索結果ページは画像を一つしか読み込んでいない」ってのが気になって、「へー、JavaScriptって画像切れるんや。」とかっていう風に勝手に思ってやりました(バカ)。実際は画像の複製と、画像の一部表示の併せ技で画像の切り取りを擬似的に実現しています(Googleも多分そうだと思うけれど、あのソースは読む気になれない。。。)。

まだリファクタリングしていない箇所もあって、冗長な箇所があったりするのですが、ひとまずは完成しています。 今後は、もし気が向けばアニメーションの勉強がてらのバージョンアップをしたいなあ。

Posted at 00:02 in | WriteBacks (3) | Edit

2007-12-11

Ma.gnoliaはブックマークした時点のスナップショットをとっといてくれる

これは便利。IBMの技術関連文章なんかはすぐページが変わったりするので困っているけど、これなら問題ない。乗り換えよっかなあ。。。
Posted at 02:51 in | WriteBacks (0) | Edit

2007-10-30

coLinuxでLVM

LVM使用までのまとめ。

  1. カーネルのコンパイル
  2. インストールしたときに入っているカーネルでは、LVMがサポートされていませんでした。なので、LVMのサポートを有効にして、カーネルのコンパイルをする必要がありました。カーネルのコンパイル自体は初めてでしたが、こちらのページの解説とおりにやることでコンパイルすることが出来ました。自分用の備忘も兼ねてということで手順は書いていますが、コンパイル自体の説明はこちらのページを参照されるのが良いと思います。

    ■ カーネルのソースを取得

    初めに、コンパイルするためのカーネルソースと、coLinux用のパッチを取得します。注意する点としては、coLinuxのパッチをlinuxカーネルのバージョンと合わせることぐらいです。
    #僕はカーネルの2.6.11を選びましたが、特に深い意味はありません。

    $ cd /usr/src/
    $ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.11.tar.gz
    $ wget http://downloads.sourceforge.net/colinux/coLinux-0.6.4-src.tar.gz?modtime=1151786092&
    $ tar xvzf linux-2.6.11.tar.gz
    $ tar xvzf coLinux-0.6.4-src.tar.gz
    
    ■ coLinux用のパッチをあてる
    $ cd /usr/src/linux-2.6.11
    $ patch -p1 < ../coLinux-0.6.4/patch/linux
    
    ■ 設定ファイルのコピー
    $ cd /usr/src/linux-2.6.11
    $ cp ../coLinux-0.6.4/conf/linux-config ./
    
    ■ LVMを有効にする
    $ make menuconfig
    

    上記コマンド発行後、組み込むモジュールなどを指定する画面が起動するので、「Load an Alternate Configuration File」でlinux-configを読み込み、「Device Drivers --->」→「Multi-device support (RAID and LVM) --->」の順に進み、「Multiple devices driver support (RAID and LVM)」と「Device mapper support」を有効にします。
    これで、LVMに必要なモジュールが取り込まれます。ここまできたら、コンパイルの準備完了です。

    ■ カーネルのコンパイル
    $ cd /usr/src/linux-2.6.11
    $ make-kpkg --revision=colinux-2.6.11-1 kernel_image kernel_headers
    $ make vmlinux
    $ mv /lib/modules/2.6.11-co-0.6.4/ /lib/modules/2.6.11-co-0.6.4.old
    $ cd /usr/src
    $ dpkg -i kernel-image-2.6.11_colinux-2.6.11-1_i386.deb
    

    で、作成された/usr/src/linux-2.6.11/vmlinuxをcoLinuxをインストールしたフォルダにあるそれと差し替えます。 coLinuxを再起動して問題なければ、カーネルの再構築は完了です。ちなみに、カーネルのコンパイルは30分くらいかかりました。

  3. LVMのインストール
  4. apt-getで必要なパッケージを取得します。

    $ apt-get install lvm2
    

    これでLVMが使えるようになっているはずです。

  5. イメージファイルの用意
  6. 記憶装置として使うためのイメージを必要なだけ作成 or 取得します。

    ■ イメージファイルの取得

    僕は、こちらのサイトが公開している2Gのイメージを2つ用意しました。自分で作りたいかたは、こちらを参考にすれば良いと思います。

    ■ 設定ファイルの編集

    新たに使用するイメージファイルをcoLinuxの設定ファイル(xmlファイル)に追加します。

    <!-- 既存の設定 -->
    <block_device index="0" alias="hda1" path="\DosDevices\c:\coLinux\root_fs" enabled="true" />
    <block_device index="1" alias="hda2" path="\DosDevices\c:\coLinux\swap_256Mb" enabled="true" />
    <!-- 既存の設定 -->
    
    <!-- ここを追加 -->
    <block_device index="2" alias="hda3" path="\DosDevices\c:\coLinux\hda3" enabled="true" />
    <block_device index="3" alias="hda4" path="\DosDevices\c:\coLinux\hda4" enabled="true" />
    <!-- ここを追加 -->
    

    編集が終わったら、coLinuxを再起動します。

  7. ファイルシステムの作成まで
  8. ■ 物理デバイス(PV)の登録

    LVMを使用するには、まず始めにパーティションを物理デバイス(Physical Volume)として登録しなければなりません。その場合、使用するパーティションのパーティションIDを「Linux LVM」に指定する必要があるのですが、coLinuxではその必要はないようです。この辺はたぶんcoLinuxのイメージファイルの扱いを知る必要があると思うのですが、それをいま追求してもあれなので、とりあえず気にしません。いきなりイメージファイルを物理デバイスとして登録します。

    $ pvcreate /dev/hda3 /dev/hda4
      Physical volume "/dev/hda3" successfully created
      Physical volume "/dev/hda4" successfully created
    
    ■ ボリュームグループ(VG)の作成

    ボリュームグループ(Volume Group)は仮想的なハードディスクみたいなものです。このあと、仮想的なパーティションをボリュームグループから切り出して、実際に使用するイメージです。ボリュームグループは1つ以上のPVから作成することができます。また、後からボリュームグループに物理ボリュームをを追加することも出来ます。

    $ vgcreate vg_test /dev/hda3 /dev/hda4
      Volume group "vg_test" successfully created
    
    ■ 論理ボリューム(LV)の作成

    ボリュームグループから、論理ボリューム(Logical Volume)を作成します。論理ボリュームは仮想的なパーティションです。この上にファイルシステムを作成したりします。ここでは、5MバイトのLVを作成してみます。

    $ lvcreate -L5M -ntest vg_test
      Rounding up size to full physical extent 8.00 MB
      Logical volume "test" created
    

    デフォルトのPhysicalExtentSize(LVMで扱うデータの最小構成で、ファイルシステムのブロックサイズのようなものです。VG作成時に指定することができます。)が4Mバイトとなっているので、8MバイトのLVが作成されています。

    ■ ファイルシステムの作成

    論理ボリューム(LV)上にファイルシステムを作成してみます。

    $ mkfs.ext3 /dev/vg_test/test
    mke2fs 1.27 (8-Mar-2002)
    Filesystem label=
    OS type: Linux
    Block size=1024 (log=0)
    Fragment size=1024 (log=0)
    2048 inodes, 8192 blocks
    409 blocks (4.99%) reserved for the super user
    First data block=1
    1 block group
    8192 blocks per group, 8192 fragments per group
    2048 inodes per group
    
    Writing inode tables: done
    Creating journal (1024 blocks): done
    Writing superblocks and filesystem accounting information: done
    
    This filesystem will be automatically checked every 34 mounts or
    180 days, whichever comes first.  Use tune2fs -c or -i to override.
    

    で、仕上げにこれを/root/lvm_testにマウントしてみます。

    $ mount -t ext3 -o noatime /dev/vg_test/test /root/lvm_test
    

    LVがマウントされていることを確認します。

    $ df
    Filesystem           1K-blocks      Used Available Use% Mounted on
    /dev/hda1              4127424   2547380   1370380  66% /
    cofs0                 52428092  33682664  18745428  65% /mnt
    /dev/vg_test/test         7931      1043      6479  14% /root/lvm_test
    

    ここまででLVMが問題なく使用できることを確認できました。LVM自体の話しだと、他にも設定ファイルの編集だとかでいろいろあるのですが、それは検索すればすぐ出てきますので、ひとまずはここまでをまとめておきました。

■ おまけ

カーネルのコンパイルは予想していたよりもあっさりいったのですが、coLinuxの起動時に以下のようなエラーが出て大変な目にあいました。

C:\coLinux>colinux-daemon.exe -c colinux.xml
Cooperative Linux Daemon, 0.6.4
Compiled on Mon May 29 22:19:09 2006

mapping cobd0 to \DosDevices\c:\coLinux\root_fs
mapping cobd1 to \DosDevices\c:\coLinux\swap_256Mb
mapping cobd2 to \DosDevices\c:\coLinux\fs_2048Mb
mapping cofs0 to \DosDevices\C:
colinux: error, expected gcc version 3.4.x, got 3.3.x
error initializing
daemon: exit code 88669c14
daemon: error - CO_RC_ERROR_COMPILER_MISMATCHED, line 423, file colinux/user/daemon.o (67)

こちらの日記によると、

colinux-daemon.exeが、自分自身をコンパイルしたgccのバージョンとvmlinuxのそれを比べ、違いがあるとエラーを表示して起動失敗となる模様。

ということらしいです。へー。
Posted at 02:37 in | WriteBacks (0) | Edit