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

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

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

先日、会社のインターネット接続が、ADSL から光に変わりました。

ADSL でも遅いということはなかったのですが、速ければ速いほ…いえ、 将来のことを考えてということで、変えることになりました。

当日の工事は、慣れた兄ちゃんがテキパキと作業して、なんの問題もなく滞りなく、 なめらかに移行できました。

…ですが、なぜか、速いという実感を感じることができません。
逆に、画像などが読み込めない頻度が上がっている気がします。

手前が光でも、その先を多くのユーザで共有しているとか、 ADSL の方が実は少ないユーザで共有していて速いとか、 疑惑が頭の中を駆けめぐっています。

そんなことないよ光の方が速いんだよと、 もっともらしい技術的な説明を誰かがしてくれるのを待っている、今日この頃です。

いつか原因究明しようと思いますが、 と言うときは絶対しないことが明白だとわかっていつつ、 今回もはりきってまいります。

今回のお題 - ハードリンクとシンボリックリンクを理解する

月に2回、ゆるゆるとはいえ、発行し続けるというのは、自分で言うのもなんですが、 思った以上の時間と労力を必要としています。

その中でも一番悩ましいのが、ネタです。 カラカラに乾いた雑巾を絞って探していますので、 ときにはすごくニッチなお題になってしまうことも、少なからずございます。

たとえば、前回の FS-Cache などは、NFS を使われていない方にとって、 ものすごくどうでもいいネタだった…かもしれません。

かたや、システム管理屋さんは、 一見するとシステム管理に関係ないように思われる知識も、 いろいろ知っておく必要があります。

カーネルやネットワーク、プログラミング、データベース、UI、 などなどの幅広い知識を持っていますと、 思わぬところで役に立ったりするのではないかと思います。

そして、その知識が、基礎的なものであればあるほど、 役に立つ可能性が高いのではないでしょうか。

…という言い訳めいた前フリをしたところで、今回は、 だれもがお世話になっている「リンク」について、おさらいしたいと思います。

ハードリンクやシンボリックリンクがどういうものか、 具体的にイメージできていれば、なにか問題が起こったとき、 役に立つ…かもしれません。
(ハードリンクにしておいてよかった! とか。あ、ありますかね…。)

まずはざっくりと基本をおさらい

普段、何気なくファイルやディレクトリなどと戯れていますが、 これらがどういうモノなのか、意識することはないんじゃないかと思います。

ですので、リンク云々の話に入る前に、 ファイルやディレクトリについてさらっとご説明したいと思います。

ご存じの方、文字ばっかりだとアナフィラキシーの症状が出る恐れのある方は、 次まですっ飛ばしていただいて構いません。

 

ファイルは、ドキュメントだったり画像だったり動画だったりしますが、 ようは、なにかのデータのまとまりを表す単位です。

ディレクトリは、ファイルを格納するための保管場所です。 もし世の中にファイルしか存在しなかったら、 同じファイル名をつけられなかったり、 つけたファイル名を忘れて途方に暮れてしまったりしてしまいます。 ですが、ディレクトリを使ってファイルを分類すると、整理できて超便利! になるわけですね。

そして、ディレクトリにはディレクトリを含められるので、 階層的な構造に仕立て上げることができます。これがファイルシステムです。

 

では、ファイルやディレクトリが、具体的にどうなっているかといいますと、 実際のファイルシステムを斜め読めば、それとなく感じられます。

ここでは例として、 EXT2(あるいは EXT3、EXT4)ファイルシステムの中を、 覗き見してみたいと思います。
Linuxカーネルのソースコードをお持ちの方は、 fs/ext[234]/ext[234].hか include/linux/fs.h あたりをご参照いただくと、 よいかもです。

まず、ファイルは、「iノード」と呼ばれるモノで管理されています。
(inode か ext2_inode 構造体を眺めると、具体的な構造が分かります。)

iノードには、ファイルの属性(種類やモード(i_mode)、所有者(i_uid)、 サイズ(i_size)、各種日時(i_atime, i_ctime, ...)など)と、 ファイルの中身の情報(i_block)が格納されています。

ここでポイントなのは、iノードにはファイル名の情報が含まれない、 ということでしょうか。

さて次に、ディレクトリです。ディレクトリもファイルの一種です。
ディレクトリの中身は、「ディレクトリエントリ」です。
(ext2_dir_entry 構造体を眺めると、具体的な構造が分かります。)

ディレクトリエントリには、ファイルの実体であるiノードと、 ファイル名が格納されています。ここに格納されているiノードとは、 32bit長の値で、ファイルシステム内で一意なモノです。

ユーザがパス名でアクセスすると、ディレクトリエントリの中から、 一致するファイル名を探し出し、それに対応するiノードをもとに、 いろいろな情報をユーザに提供する、という芸当が可能になるわけです。

ちなみに、この32bitの値を「iノード番号」と呼びます。
iノード番号を知るには、「-i」オプションを指定してlsコマンドを実行します。

  $ ls -i1 /
   7340033 bin/
  45875201 boot/
  19398657 cdrom/
         3 dev/
  35127297 etc/
  50069505 home/
        17 initrd.img@
        13 initrd.img.old@
  ...中略...
         1 proc/
  ...中略...
         1 sys/
  ...後略...

/proc や /sys が 1 なのは、 それぞれ procfs や sysfs をマウントしているためだと思われます。

また、「stat」コマンドでも、iノードの情報を確認できます。

  $ stat /etc/hosts
    File: `/etc/hosts'
    Size: 2562        Blocks: 8        IO Block: 4096  通常ファイル
  Device: 805h/2053d  Inode: 35132117  Links: 1
  Access: (0644/-rw-r--r--)  Uid: (  0/  root) Gid: (  0/  root)
  Access: 2013-06-01 12:55:02.009358371 +0900
  Modify: 2013-05-27 12:50:35.151572836 +0900
  Change: 2013-05-27 12:50:35.207573114 +0900
   Birth: -

というわけで、ハードリンクとは?

文章ばっかりでクラクラしてきました…が、気を取り直して進めます。

「ハードリンク」とは、すでにあるファイルを、 別のファイル名(パス名)で参照できるようにするモノです。

ハードリンクを作成するには、「ln」コマンドを使います。元のファイル名と、 新たに作成するファイル名を引数に指定して実行します。
たとえば、foo.txt の別名で bar.txt というハードリンクを作成するには、 以下のように実行します。

  $ ln foo.txt bar.txt

別ディレクトリにあるファイルと同じ名前ハードリンクを作成するには、 元だけを指定します。

  $ ls
  $ ln foo/bar.txt
  $ ls
  bar.txt

もう少し具体的に説明すると、ハードリンクとは、 既存のiノードを参照するディレクトリエントリを1つ追加すること、とも言えます。

たとえば、さきほど作成した bar.txt と、 その元の foo.txt のiノードを確認してみると、同じiノードであることが分かります。

  $ ls -i1 foo.txt bar.txt
  32256332 bar.txt
  32256332 foo.txt

iノードにファイル名の情報が含まれない理由は、ここにあります。

そして、別のファイルシステムにあるファイルに対して、 ハードリンクを作成することができません。iノード番号が、 ファイルシステム内でのみ一意だからです。

また、iノードには、 リンク数(i_nlink か i_links_count)という情報が含まれています。通常は、 あるディレクトリのディレクトリエントリから参照されているため、 リンク数は 1 です。

  $ echo test > foo.txt
  $ ls -li foo.txt
  32256333 -rw-r--r-- 1 usu usu 5  6月  1 18:00 foo.txt

上記の場合、32256333 が iノード番号、その後の 1 がリンク数です。
ここでハードリンクを作成すると、 2つのディレクトリエントリから参照されることになるため、 リンク数は 2 になります。

  $ ln foo.txt bar.txt
  $ ls -li foo.txt bar.txt
  32256333 -rw-r--r-- 2 usu usu 5  6月  1 18:00 bar.txt
  32256333 -rw-r--r-- 2 usu usu 5  6月  1 18:00 foo.txt

そして、ファイルを削除するコマンドといえば「rm」ですが、 rmコマンドの役割は、厳密には、ディレクトリエントリを削除し、 iノードのリンク数を1つ減らすこと、だと言えます。

たとえば、ここで foo.txt を rm コマンドで削除すると、 foo.txt だけがなくなり、bar.txt は残ります。もちろん、 中身は foo.txt のときのままです。(リンク数は 1つ減って 1 になります。)

  $ rm foo.txt
  $ ls -li foo.txt bar.txt 
  ls: foo.txt にアクセスできません: そのようなファイルやディレクトリ\
  はありません
  32256333 -rw-r--r-- 1 usu usu 5  6月  1 18:00 bar.txt

つまり、foo.txt のディレクトリエントリはなくなりますが、 32256333番のiノードと、 そのiノードを参照する bar.txt のディレクトリエントリは存在するので、 削除されずにすみます。

もちろん、ここでさらに bar.txt を削除すると、 32256333番のiノードを参照するディレクトリエントリがなくなる (リンク数が 0 になる)ため、今度こそ(?)削除されることになります。

ちなみに、元のファイルを移動させても、iノードで参照しているため、 問題なく参照できます。

  $ cat foo.txt
  I am a foo.txt
  $ ln foo.txt bar.txt
  $ mv foo.txt foo2.txt
  $ ls -li foo2.txt bar.txt
  $ cat bar.txt
  I am a foo.txt
  32256335 -rw-r--r-- 2 usu usu 15  6月  1 18:00 bar.txt
  32256335 -rw-r--r-- 2 usu usu 15  6月  1 18:00 foo2.txt

それから、ディレクトリに対するハードリンクは、root の権限があり、 ファイルシステムが対応している場合のみ、可能です。
(残念ながら、EXT2(EXT3,EXT4)では、対応していないようです。)

それじゃあ、シンボリックリンクって?

リンクには、前述のハードリンクの他に、 「シンボリックリンク」というモノがあります。

シンボリックリンクも、すでにあるファイルに別名をつけて、 その名前で参照できるようにするモノです。

ハードリンクとは違い、元のファイルをiノードではなくパスで指定するため、 別のファイルシステムのファイルを参照できます。

シンボリックリンクの作成にも、ln コマンドを使います。
「-s」オプションと、元のファイルのパス、 それを参照するシンボリックリンクとなるファイル名を指定して、 ln コマンドを実行します。

たとえば、foo.txt のシンボリックリンク bar.txt を作成したい場合、 以下のように実行します。

  $ ln -s foo.txt bar.txt
  $ ls -li foo.txt bar.txt 
  32256334 lrwxrwxrwx 1 usu usu 7  6月  1 22:01 bar.txt -> foo.txt
  32256333 -rw-r--r-- 1 usu usu 5  6月  1 18:00 foo.txt

ハードリンクとは違い、元のファイルのリンク数は増えません。
ですが、もちろん、元のファイルと同じようにアクセスできます。

  $ cat foo.txt
  test
  $ cat bar.txt
  test
  $ echo test from bar.txt > bar.txt
  $ cat foo.txt
  test from bar.txt

また、引数に元のファイルのパスだけを指定すれば、 同名のシンボリックリンクが作成されます。
たとえば、 /etc/passwd のシンボリックリンクをカレントディレクトリに作成するには、 以下のように実行します。

  $ ln -s /etc/passwd
  $ ls -l passwd
  lrwxrwxrwx 1 usu usu 11  6月  1 21:58 passwd -> /etc/passwd

では、シンボリックリンクを削除するとどうなるか、といいますと、 元のファイルはどうもならず、シンボリックリンクが削除されるだけです。

  $ rm bar.txt
  $ ls -li foo.txt bar.txt
  ls: bar.txt にアクセスできません: そのようなファイルやディレクトリ\
  はありません
  32256333 -rw-r--r-- 1 usu usu 5  6月  1 18:00 foo.txt

では逆に、元のファイルを消すとどうなるかといいますと、 シンボリックリンクは残りますが、ファイル自体は失われてしまいます。

  $ rm foo.txt
  $ ls -li foo.txt bar.txt
  ls: foo.txt にアクセスできません: そのようなファイルやディレクトリ\
  はありません
  32256334 lrwxrwxrwx 1 usu usu 7  6月  1 22:01 bar.txt -> foo.txt
  $ cat bar.txt
  cat: bar.txt: そのようなファイルやディレクトリはありません

…ひゃー、悲しいですね。

それから、ハードリンクでは、 元のファイルを移動させても問題なく参照できましたが、 シンボリックリンクでは参照できなくなります。

  $ echo test > foo.txt
  $ ln -s foo.txt bar.txt
  $ mv foo.txt foo2.txt
  $ cat bar.txt
  cat: bar.txt: そのようなファイルやディレクトリはありません

さらにそれから、ディレクトリに対するシンボリックリンクは、 問題なく作成できます。

  $ ln -s /etc etc_link
  $ ls etc_link/
  ...後略...

その他注意するところ

それぞれ特性や制約はありますが、どちらも、 別名でのアクセスができるという点で、とっても便利な仕組みです。

以上で…と終わりにしたいところですが、あとひとつだけ、 注意すべき点がありますので、記します。

それは、アーカイブにしたときの扱いです。
ここでは、tar と zip でどうなのか、確認しておこうと思います。

まずは tar ですが、ハードリンクには気づいていただけるようです。

  $ tar cfz test.tgz foo.txt bar.txt
  $ tar tvfz test.tgz
  -rw-r--r-- usu/usu   5 2013-06-02 00:20 foo.txt
  hrw-r--r-- usu/usu   0 2013-06-02 00:20 bar.txt foo.txt へのリンク

ただ、どちらが元かというのは、作ったひとにしかわからないので、 先に指定した方がオリジナルだと判断されるようです。

  $ tar cfz test2.tgz bar.txt foo.txt
  $ tar tvfz test2.tgz
  -rw-r--r-- usu/usu   5 2013-06-02 00:20 bar.txt
  hrw-r--r-- usu/usu   0 2013-06-02 00:20 foo.txt bar.txt へのリンク

といっても、どちらも展開したら同じ結果になるんですけどね。

シンボリックリンクの場合も、問題なく扱えます。

  $ tar cfz test.tgz foo.txt bar.txt
  $ tar tvfz test.tgz
  -rw-r--r-- usu/usu   5 2013-06-02 00:27 foo.txt
  lrwxrwxrwx usu/usu   0 2013-06-02 00:27 bar.txt -> foo.txt

元がアーカイブに含まれないときなど、 シンボリックリンクではなく実体として取り込みたいときは、 「h」オプションを指定します。
以下の場合は、オリジナルが含まれるため、ハードリンクとして含められました。 なんだかカシコイですね。

  $ tar cfzh test2.tgz foo.txt bar.txt
  $ tar tvfz test2.tgz
  -rw-r--r-- usu/usu   5 2013-06-02 00:27 foo.txt
  hrw-r--r-- usu/usu   0 2013-06-02 00:27 bar.txt foo.txt へのリンク

 

お次は zip です。
残念ながら、ハードリンクは考慮していただけないようです。

  $ zip -r test.zip foo.txt bar.txt
  $ unzip -l test.zip
  Archive:  test.zip
    Length     Date   Time    Name
   --------    ----   ----    ----
          5  06-02-13 00:20   foo.txt
          5  06-02-13 00:20   bar.txt
   --------                   -------
         10                   2 files
  $ unzip test.zip
  $ ls -li foo.txt bar.txt 
  32256336 -rw-r--r-- 1 usu usu 5  6月  2 00:20 bar.txt
  32256335 -rw-r--r-- 1 usu usu 5  6月  2 00:20 foo.txt

シンボリックリンクも、そのままだと、上記と同様です。
ですが、「-y」オプションを指定すると、 シンボリックリンクを考慮してくださいます。

  $ zip -yr test.zip foo.txt bar.txt
  $ unzip test.zip
  Archive:  test.zip
   extracting: foo.txt                 
      linking: bar.txt                 -> foo.txt 
  finishing deferred symbolic links:
    bar.txt                -> foo.txt
  $ ls -li foo.txt bar.txt 
  32256339 lrwxrwxrwx 1 usu usu 7  6月  2 00:34 bar.txt -> foo.txt
  32256338 -rw-r--r-- 1 usu usu 5  6月  2 00:20 foo.txt

おわりに

以上、ハードリンクとシンボリックリンクについて、 おさらい的にさらりとご紹介しました。

それぞれの特徴をざっくりまとめますと、以下のようになります。

[ハードリンク]

  • iノードで参照
  • 同一ファイルシステム内に限られる
  • ファイルのみ(と思っておいた方がいい)
  • 元のファイルを移動しても問題ない
  • 元のファイルを削除しても消えない

[シンボリックリンク]

  • パスで参照
  • 別のファイルシステムでもいける
  • ディレクトリに対してもいける
  • 元のファイルを移動すると参照できなくなる
  • 元のファイルを削除すると消える

個人的には、tar コマンドはいろいろ考えているなあ、と思いました。

宿題の答え

前回の宿題は、

  NFSマウント中にcachefilesdを停止・起動するとどうなるでしょうか。

でした。

というわけで、試してみましょう。
cachefilesd が動いていることを確認して、NFSマウントします。

  # service cachefilesd status
  cachefilesd (pid  2200) を実行中...
  # mount -o fsc 192.168.1.1:/export/home/nfs /home/nfs
  # du -sk /var/cache/fscache
  692     /var/cache/fscache

アクセス前の、キャッシュディレクトリのサイズも、確認しておきます。
で、NFSマウントした中のファイルに、どーんとアクセスしてみます。

  $ tar tvfz /home/nfs/foo/bar-0.0.1.tgz

…これは、単なる例なので、自由に、適当なアクセスをしてください。
そうすると、当然ですが、キャッシュサイズは増えていきます。

  # du -sk /var/cache/fscache
  80184   /var/cache/fscache
  # du -sk /var/cache/fscache
  353596  /var/cache/fscache
  ...後略...

では、アクセスさせたままの状態で、cachefilesd を止めてみましょう。

  # service cachefilesd stop
  cachefilesd を終了中:                                  [  OK  ]

すると、アクセスできなくなるか…というと、そんなことはありません。
その後も問題なくアクセスできます。

ちなみに、cachefilesd が動いていない状態でマウントすると、 どうなるでしょうか。

  # umount /home/nfs
  # mount -o fsc 192.168.1.1:/export/home/nfs /home/nfs
  # du -sk /var/cache/fscache
  676156   /var/cache/fscache
  (何かアクセス)
  # du -sk /var/cache/fscache
  676156   /var/cache/fscache

ご想像通り、問題なくアクセスできます。
キャッシュのサイズも、使われていないから当然ですが、変わりません。

もし、マウント後にサービスを開始しても、ちゃんとキャッシュされて、 キャッシュが使われるようになります。

  # service cachefilesd start
  cachefilesd を起動中:                                  [  OK  ]
  # du -sk /var/cache/fscache
  48      /var/cache/fscache
  (何かアクセス)
  # du -sk /var/cache/fscache
  1824    /var/cache/fscache

ユーザ空間で動作するプロセスのせいでアクセスできなくなったりする、 というのは困りますので、当たり前なのかもしれませんね。

今回の宿題

今回の宿題は、

  シンボリックリンクの場合ディレクトリエントリにどう記録されるか、
  確認してみましょう。

です。

フツーに readdir() で読んだら…ということではなく、 EXT2 などでベタにどう記録されているのか、ということを調べてください。

検索すればわかると思いますので、宿題の答えでは、実際に生で読んで、 その通りだった! というところまでたどり着きたいです。

あとがき

某新聞で、能楽師の務めは、過去から未来へと芸を運ぶこと、という文章を読みました。

その中の一文、「自分という存在は、長い線上の一点にすぎない。」に、 なんだか、ぐぐっと来るものがありました。

みなさんはまだお若いと思いますが、それとなく年を食ってくると、 夢や目標があいまいになり、それに向かってがんばることより、 目の前のことだけで限界だと思い込んだり、 酒を飲んでくだを巻いたりしがちではないかと、勝手ながら思っています。

ですが、夢に向かって突き進むことだけでなく、後からくる人のために、 きちんと何かを残していくことも大事なのではないかということに、 その文章を読んで気づくことができました。

このメルマガをはじめたきっかけも、 小銭稼ぎになるといいなあ…という邪心だけでなく、 わからなくて途方に暮れている若い管理者さんの助けになりたい、 という考えが、少なからずありました。

…あ、いえ、あります、です。現在進行形ですよ…。

というわけで、今後は、長い線上の一点として、 未来のひとに何か残せるようなことを考えてやっていこうと、強く思いました。

 

…いやいや、まだまだ、栗で世界征服の野望は、諦めていませんけどね。
小遣い稼ぎという邪心が、そこそこ達成できたとはいえ…。(^ε^;

 

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

 

「いますぐ実践! 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/ (モバイル栗日記)
http://twitter.com/kuriking/ (栗つぶやき)
http://facebook.com/kuriking3 (栗顔本)


[バックナンバーのトップへ] [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

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本