いますぐ実践! Linuxシステム管理

[バックナンバーのトップへ] [Linux システム管理のトップへ]


いますぐ実践! Linux システム管理 / Vol.187 / 読者数:1613名

こんばんは、うすだです。

先日、自分の写っている写真を見て、己の劣化具合に愕然としました。
童顔なひとは急に老けると言いますが、まさにその通りな感じでした。
写真に撮られると魂が抜かれる、の意味がようやくわかった気がします。

ところで、万人がすなる Twitter ですが、 認証方式が OAuth なるものに変わったためか、 Linux の Firefox で Echofon が使えなくなりました。
(他のエクステンションでもダメなので、Echofon の問題ではないかも…)

とはいえ、Twitter を使いこなす、 と言うにはほど遠い使い方しかできていませんでしたので、 フォローしているひとのつぶやきが見られない程度の支障しか生じていません。

ですので、これを機会に、 Twitter で費やされていた時間をもっと有意義なことに使おう、と思うことにします。

いろいろ間違ってる気もしますが、今回もはりきってまいりましょう。

今回のお題 - 複数のディレクトリを束ねてマウントする

CD やファイルシステムイメージのファイルをマウントして、 ちょこっと書き換えたいということが、たまに発生することがあります。

あるいは、ディスクレスなLinuxマシンが複数台あり、 それらがルートのファイルシステムを共有している場合、 読み込み専用で使うことになると思います。
そんなとき、ルートファイルシステムに書き込むことができて、 変更内容が別で記録できると、便利ではないかと思います。

あるいは、バージョンアップなどを試してみたいけど、動かなくなる可能性があるので、 バージョンアップに失敗してももとに戻せると、安心して試すことができます。

…などなど、読み込み専用のディレクトリに対して擬似的に書き込むことができると、 便利なケースがいくつか考えられます。

そして、Linux には、それを実現する機能があります。
そこで今回は、複数のファイルを束ねてマウントする機能を使って、 読み込み専用のディレクトリを擬似的に書き込めるようにする方法を、 淡々とご紹介したいと思います。

今回ご紹介する内容は、以下の3本です。
興味のあるモノだけをご覧いただければと思いますが、 前提条件が最初に書いてありますので、そちらはさらっと眺めた方がよいかもしれません。

unionfs-fuse の場合

Debian系の場合、unionfs-fuse というコマンドを用いることで、 上記が実現できます。
同名のパッケージがありますので、 以下のように apt-get などを用いてインストールしてください。

  # apt-get install unionfs-fuse

unionfs-fuse コマンドの簡単な書式は、以下のようになります。

  # unionfs-fuse ブランチ1:ブランチ2:... マウントポイント

「ブランチ」には、束ねる元のディレクトリと、 そのディレクトリが読み込み専用(RO)か書き込み可能(RW)かどうかを指定します。
ちなみに、先に指定したブランチが優先されます。詳しくは後述します。

「マウントポイント」には、束ねたものをアクセスする先のディレクトリを指定します。

 

それでは、早速試してみましょう。

以降では、例として、読み込み専用の /media/cdrom と、 書き込み可能な /tmp/unionfs を束ねて参照したいと思います。

以下のように、/media/cdrom には dir1 と dir2 というディレクトリがあり、 それぞれいくつかのファイルがあるとします。

  dir1/
    +----- test1_1.txt
    +----- test1_2.txt
  dir2/
    +----- test2.txt

また、/tmp/unionfs には dir1 と dir3 というディレクトリがあって、 こちらもそれぞれいくつかのファイルがあるとします。

  dir1/
    +----- test1_1.txt
    +----- test1_3.txt
  dir3/
    +----- test3.txt

 

これらを束ねて /mnt にマウントするには、以下のように実行します。

  # unionfs-fuse /media/cdrom=RO:/tmp/unionfs=RW /mnt

すると、/mnt 直下には、いずれにもある dir1 と、 どちらか一方にのみある dir2 および dir3 が現れます。

  # ls /mnt
  dir1/  dir2/  dir3/

dir1 以下には、双方のファイルが合わさって出現します。
dir2, dir3 以下には、それぞれのファイルがそのまま出現します。

  # ls /mnt/dir1
  test1_1.txt  test1_2.txt  test1_3.txt
  # ls /mnt/dir2
  test2.txt
  # ls /mnt/dir3
  test3.txt

ここで、dir1/test1_1.txt というファイルはどちらにも存在しますが、 先に指定したブランチが優先されますので、 /media/cdrom のファイルにのみアクセスできます。

  # cat /media/cdrom/dir1/test1_1.txt
  This is a file of /media/cdrom.
  # cat /tmp/unionfs/dir1/test1_1.txt
  This is a file of /tmp/unionfs.
  # cat /mnt/dir1/test1_1.txt
  This is a file of /media/cdrom.

ファイルの作成や削除、内容の変更など、書き込みができるかどうかは、 元のディレクトリが書き込み可能かどうかで決まります。
たとえば、dir3 は、書き込み可能な /tmp/unionfs が元ですので、 dir3 以下を変更することができます。

  # touch /mnt/dir3/dummy
  # mv /mnt/dir3/test3.txt /mnt/dir3/test3_new.txt
  # ls /mnt/dir3
  dummy  test3_new.txt

ですが、/media/cdrom が元である dir2 以下は、 読み込み専用ですので変更することはできません。

  # touch /mnt/dir2/dummy
  touch: `/mnt/dir2/dummy'にtouchできませんでした: Permission denied

さらに、/mnt 直下や /mnt/dir1 は双方にありますが、 /media/cdrom の方が優先されますので、やはり変更できません。

  # touch /mnt/dummy
  touch: `/mnt/dummy'にtouchできませんでした: Permission denied
  # touch /mnt/dir1/dummy
  touch: `/mnt/dir1/dummy'にtouchできませんでした: Permission denied

そんなときは、/tmp/unionfs を先に指定してマウントしてみましょう。
(マウントしなおすため、一旦アンマウントしています。)

  # umount /mnt
  # unionfs-fuse /tmp/unionfs=RW:/media/cdrom=RO /mnt

すると、/mnt や /mnt/dir1 以下を変更することができます。

  # touch /mnt/dummy
  # rm /mnt/dir1/test1_1.txt
  # ls /mnt
  dir1/  dir2/  dir3/  dummy
  # ls /mnt/dir1
  test1_2.txt  test1_3.txt

ですが、dir2 以下は /media/cdrom が元ですので、 依然として変更することはできません。
そんなときは、マウントする際に、「-o cow」オプションを指定します。

  # umount /mnt
  # unionfs-fuse -o cow /tmp/unionfs=RW:/media/cdrom=RO /mnt

すると、dir2 以下の変更が可能となります。

  # rm /mnt/dir2/test2.txt
  # echo test > /mnt/dir2/test2_new.txt
  # ls /mnt/dir2
  test2_new.txt

変更内容は、/tmp/unionfs 側に記録されています。

  # ls /tmp/unionfs
  dir1/  dir2/  dir3/  dummy
  # ls /tmp/unionfs/dir2
  test2_new.txt

 

ちなみに、ファイルを削除すると、削除したという印が /tmp/unionfs に残ります。 削除したファイルのあったディレクトリに「.unionfs」というディレクトリが作成され、 「削除したファイル名_HIDDEN~」という名前のファイルが作成されます。

  # ls /tmp/unionfs/dir2/.unionfs
  test2.txt_HIDDEN~

 

さらにちなみに、「-o stats」オプションをつけてマウントすると、 読み書きしたバイト数がわかります。

  # umount /mnt
  # unionfs-fuse -o cow,stats /tmp/unionfs=RW:/media/cdrom=RO /mnt

マウントポイントの直下に「stats」というファイルが自動的に作成されます。 これを参照すると、いままでにアクセスしたバイト数が出力されるという寸法です。

  # cat /mnt/stats
  Bytes read: 0,000,009,367,552
  Bytes written: 0,000,009,365,872

ただし、同名の「stats」というファイルが元にあると、 そちらには参照できなくなります。ご注意ください。

funionfs の場合

かたや、Fedoraの場合には、funionfs というコマンドがあります。
こちらも、同名のパッケージがありますので、下記の手順でインストールしてください。

  # yum install funionfs

funionfs コマンドの簡単な書式は、以下のようになります。

  # funionfs -o dirs=ブランチ1:ブランチ2:... none マウントポイント

「ブランチ」と「マウントポイント」は、unionfs-fuse と同じです。

 

こちらも早速試してみましょう。

先ほどと同じように、/media/cdrom と /tmp/unionfs を束ねてマウントするには、 以下のように実行します。

  # funionfs -o dirs=/media/cdrom=RO:/tmp/unionfs=RW none /mnt

基本的には unionfs-fuse と同じように使えますが、 微妙に異なるところもあります。
まず、元のディレクトリが読み込み専用でも、変更ができます。

  # touch /mnt/dir2/dummy
  touch: setting times of `/mnt/dir2/dummy': File exists

最初から「-o cow」を指定しているのと同じだと思えばよさそうです。
ただ、上記のようなメッセージが出力され、 なぜかタイムスタンプの設定に失敗します。(cp -p なども同様です。)

また、同名のファイルとディレクトリがあると、混乱することがあるようです。

  # umount /mnt
  # mkdir /tmp/unionfs/dir2/test2.txt
  # funionfs -o dirs=/media/cdrom=RO:/tmp/unionfs=RW none /mnt

上記のように、dir2を、一方ではディレクトリ、もう一方ではファイルにしてみます。 すると、以下のように、混乱する現象がみられます。
ただ、何度かアクセスしていると、どちらかに落ち着いたりもしました。
(あまりイジワルしないほうがよさそうです。)

  # ls -l /mnt/dir2
  drwxr-xr-x 32 root root 4096 Sep 17 01:54 test2.txt/
  # ls /mnt/dir2/test2.txt/
  ls: cannot access /mnt/dir2/test2.txt/: Not a directory

ファイルの削除は、「ファイル名_DELETED~」というファイルを作成することで、 記録されます。

  # rm /mnt/dir1/test1.txt
  # ls /mnt/dir1
  test1_2.txt  test1_3.txt
  # ls /tmp/unionfs/dir1
  test1.txt_DELETED~  test1_2.txt  test1_3.txt

もし「_DELETED~」の付加が都合の悪いときには、 「-o del_string」オプションで付加する文字列を変更できます。

  # umount /mnt
  # funionfs -o dirs=/media/cdrom=RO:/tmp/unionfs=RW,del_string=__DEL__ \
  none /mnt
  # ls /mnt/dir1
  test1.txt  test1.txt_DELETED~  test1_2.txt  test1_3.txt
  # rm /mnt/dir1/test1.txt
  # ls /mnt/dir1
  test1.txt_DELETED~  test1_2.txt  test1_3.txt
  # ls /tmp/unionfs/dir1
  test1.txt__DEL__  test1.txt_DELETED~  test1_3.txt

aufs の場合

Ubuntu では、unionfs-fuse の他に、aufs も使用できます。
aufs はカーネルモジュールですので、mount コマンドを使用して、 複数のディレクトリを束ねてマウントします。

具体的には、「-t」オプションでファイルシステムタイプに aufs を指定して、 以下のように実行します。

  # mount -t aufs -o br:/tmp/unionfs:/media/cdrom aufs /mnt

この場合、元が /media/cdrom で、 それに対する変更が /mnt/unionfs にすべて反映されます。
ですので、/media/cdrom/dir2 がディレクトリで、 /mnt/unionfs/dir2 がファイルだとすると、/mnt/dir2 はファイルになります。

また、削除したファイルは、「.wh.ファイル名」で記録されます。

  # rm /mnt/dir1/test1.txt
  # ls -l /tmp/unionfs/dir1/.wh.test1.txt
  -r--r--r-- 2 root root 0 2010-09-19 23:56 /tmp/unionfs/dir1/.wh.test1.txt

ちなみに、/media/cdrom に直接マウントすることもできます。

  # umount /mnt
  # mount -t aufs -o br:/tmp/unionfs:/media/cdrom aufs /media/cdrom

aufs には、他にもいろいろなオプションがあるようですが、 今回は調べきれませんでした。ですので、すみませんが以上にさせていただきます。

おわりに

以上、unionfs-fuse や funionfs、aufs を用いて、 複数のディレクトリを束ねてマウントする方法をご紹介しました。

それぞれ微妙に異なりますので、用途に合わせて、オプションなどを指定してください。

宿題の答え

前回の宿題は、

  LUKS で、どれだけパスワードを追加できるか、試してみましょう。

でした。

これはもう、試してみるだけですので、淡々とやってみましょう。
まずは、luksFormat で初期状態にしてしまいます。
(もし大事なデータがあれば、事前に退避しておきましょう。)
そして、念のため luksDump で状態を確認します。

  # cryptsetup luksFormat /dev/sdb2
  # cryptsetup luksDump /dev/sdb2 | grep '^Key slot'
  Key Slot 0: ENABLED
  Key Slot 1: DISABLED
  ...
  Key Slot 7: DISABLED

この時点で、すでに8個が上限ではないのか? という思いが脳裏をよぎりますが、 気にせず確認作業を進めます。
まずは、luksAddKey で、パスワードを1個追加してみましょう。

  # cryptsetup luksAddKey /dev/sdb2
  # cryptsetup luksDump /dev/sdb2 | grep '^Key slot'
  Key Slot 0: ENABLED
  Key Slot 1: ENABLED
  Key Slot 2: DISABLED
  ...
  Key Slot 7: DISABLED

スロット 0 と 1 が ENABLED になりました。
ちなみに、スロット 0 と同じパスワードを入力してみましたが、 なにも言われずに追加できました。

この調子で、延々と luksAddKey を実行していきます。
ただ、コマンドを繰り返し入力する(あるいはカーソルキーでたどる)のは面倒ですので、 while で自動的に繰り返してもらいましょう。

  # while [ cryptsetup luksAddKey /dev/sdb2 ]; do
  > cryptsetup luksDump /dev/sdb2 | grep '^Key slot'
  > done
  ...
  Key Slot 0: ENABLED
  Key Slot 1: ENABLED
  ...
  Key Slot 6: ENABLED
  Key Slot 7: ENABLED
  All key slots full.

予想通り、 8個設定(つまり7回 luksAddKey を実行)したところでいっぱいになってしまいました。

さて、この8個という制限ですが、どうにかして増やしたりできないものかと思い、 少々調べてみました。
ですが、ソースコードを見る限りでは、固定になっているようです。

luks/keymanage.c には、以下のようなコードが各所にあります。

  if(keyslot >= LUKS_NUMKEYS || keyslot < 0)
      return SLOT_INVALID;
  ...
  for(i = 0; i < LUKS_NUMKEYS; i++)
      if(header->keyblock[i].active == LUKS_KEY_ENABLED) {
          ...何か処理...
      }
  }

どうやら、スロット数が LUKS_NUMKEYS に固定されているようです。
これは、luks/luks.h で以下のように定義されています。
つまり、もうどうしようもない、ということですね。

  #define LUKS_NUMKEYS 8

 

結果がつまらなかったので、オマケで、 udev のスクリプトをLUKS対応にしてみたいと思います。
前回の宿題でご紹介したスクリプトは、以下の通りです。

#!/bin/sh
CRYPT_DEVN="HAGIWARA_UD-Pure_985614010100-0:0"
CRYPT_PART="2"              # /dev/sd?2
CRYPT_NAME="test1"          # name
CRYPT_SPEC="aes-cbc-plain"  # cipher specification string
CRYPT_SIZE="256"            # key size

[ "$ACTION" = "add" ] || exit 0
[ "$ID_BUS" = "usb" ] || exit 0
[ "$ID_SERIAL" = "$CRYPT_DEVN" ] || exit 0
[ -n "$DKD_PARTITION_NUMBER" ] \
    && n=$DKD_PARTITION_NUMBER || n=$UDISKS_PARTITION_NUMBER
[ "$n" = "$CRYPT_PART" ] || exit 0
/usr/bin/xterm -display :0 \
    -e "/sbin/cryptsetup create -y -c $CRYPT_SPEC \
        -s $CRYPT_SIZE $CRYPT_NAME \
        /dev/disk/by-id/${ID_BUS}-${ID_SERIAL}-part${n} \
        && echo OK || echo NG; read"

条件(デバイスが $CRYPT_DEVN かどうか、パーティションが $CRYPT_PART かどうか) が合えば、xterm 経由で cryptsetup create を実行します。
ここでは、その前に、isLuks を実行して LUKS かどうかを確認し、 その場合は luksOpen を呼んであげればよさそうです。

#!/bin/sh
CRYPT_DEVN="HAGIWARA_UD-Pure_985614010100-0:0"
CRYPT_PART="2"              # /dev/sd?2
CRYPT_NAME="test1"          # name
CRYPT_SPEC="aes-cbc-plain"  # cipher specification string
CRYPT_SIZE="256"            # key size

[ "$ACTION" = "add" ] || exit 0
[ "$ID_BUS" = "usb" ] || exit 0
[ "$ID_SERIAL" = "$CRYPT_DEVN" ] || exit 0
[ -n "$DKD_PARTITION_NUMBER" ] \
    && n=$DKD_PARTITION_NUMBER || n=$UDISKS_PARTITION_NUMBER
[ "$n" = "$CRYPT_PART" ] || exit 0
/sbin/cryptsetup isLuks \
    /dev/disk/by-id/${ID_BUS}-${ID_SERIAL}-part${n} \
    && /usr/bin/xterm -display :0 \
        -e "/sbin/cryptsetup luksOpen \
            /dev/disk/by-id/${ID_BUS}-${ID_SERIAL}-part${n} \
            $CRYPT_NAME && echo OK || echo NG; read" \
    || /usr/bin/xterm -display :0 \
        -e "/sbin/cryptsetup create -y -c $CRYPT_SPEC \
            -s $CRYPT_SIZE $CRYPT_NAME \
            /dev/disk/by-id/${ID_BUS}-${ID_SERIAL}-part${n} \
            && echo OK || echo NG; read"

実行しますと、xterm 経由で以下のような出力が得られました。

  Enter passphrase for /dev/disk/by-id/usb-HAGIWARA_UD-Pure_9856\
  14010100-0:0-part2: (パスワードを入力)
  Key slot 0 unlocked.
  OK

使い終わったら、忘れずに luksClose してください。

  # cryptsetup luksClose test1

今回の宿題

今回の宿題は、

  3つ以上のディレクトリを束ねてマウントし、挙動を確認しましょう。

です。

それぞれ、書き込めるかどうか、指定する順序、名前の重複など、 調べる内容がたくさんありすぎるかもしれません。

なるべくいろんなパターンで試したいと思いますが、 破綻しそうなときは代表的なものだけに絞らさせていただきます。
(…じゃなかった、絞って試してくださいませ。)

あとがき

こう見えても(?)、そこそこ本は読んでいるほうだと思うのですが、 その成果のようなものが、いつ何時もまったく現れていない気がします。

漠然と手当たり次第に読んでいるだけなのがいけないのだろうな、 ということは漠然とわかります。ですが、もうちょっと踏み込んで、 どのような状態なのか、どうすればよいのか、ということについては、 考えないまま今日に至っております。

そんなことを思っていましたら、「まなめはうす」経由で下記のページに出くわしました。

学ぶ時間を減らし、咀嚼する時間を増やす。
http://d.hatena.ne.jp/favre21/20100917

栄養として取り込んだら、咀嚼して仕事などに応用する必要があること、 そして目的意識、当事者意識を持って挑むということが、 いままで欠けていたように思います。(つまり、上記に書いてあることすべて、です…。)

昔から考えるのが苦手で、直感で行動したり選んだりしてきました。
もちろん、それが必要なこともありますが、 だから考えなくていいということにはなりません。
少なくとも、本を読む前に、なんのために読むのか、読んだらどうするかを決めてから、 読むようにしようと思います。

 

ところで、今月末から1ヶ月、下記で展示をすることになっています。

覚王山アパート 厠画廊
http://www.kakuozan.com/apartment/toilet/

…が、準備がまったく進んでいません。(いえ、開始すらしていません。)
本業のピークも今月末まで続きそうですので、ちょっとやばい状況です。

というわけですので、申し訳ありませんが、 次回の予定である10月3日はお休みをいただきたいと考えております。

今月末を無事乗り切って…いえ、乗り切れなくても、 17日にきちんと発行させていただきます。
すみませんが、よろしくお願いします。

 

今回も、ここまで読んでいただき、たいへんありがとうございました。
次回は、10月17日(日) の未明にお会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」- というわけで、なんとか展示にこぎつけたいと思います。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本