最低限 UNIX / Linux [II]

  1. 実習の前準備
  2. ファイルとディレクトリ
  3. ファイルモードとリンクについて

3. ファイルモードとリンクについて

[3.0] 本テキストの目的

  1. ファイルモードを理解する (ls -l の出力結果が理解できるようになる).
  2. ファイル保護ができるようになる (chmod を使いこなせる).
  3. リンクの概念を覚える.

[3.1] ファイルモード

UNIX では、複数のユーザーで同一のマシンを使用することを前提に 設計されています。そこで、ファイルへのアクセス権制御、 即ち他人に見せてもよいファイル・見せたくないファイルの制御が、 UNIX において重要となります。

UNIX では、自分のホームディレクトリへ他人が勝手にファイルを書いたり、 自分のメールを他人に読まれたりされないようにすることが可能です。 また特定のグループに所属するメンバーのみ読み書き可能なファイルを 作ることもできます。 ここではこのようなファイルのアクセス権の制御について見ていきます。

[3.1.1] ファイルモード

自分のホームディレクトリで ls コマンドを幾つかのオプションを指定して実行すると、 およそ以下のような出力が得られます。

$ ls -Flag
drwxr-xr-x   7 inex     inex         1024 Sep 29 02:34 ./
drwxr-xr-x 282 root     root         5120 Sep 29 20:51 ../
-rw-r--r--   1 inex     inex          266 May 12 20:12 .alias
-rw-r--r--   1 inex     inex           91 May 12 20:12 .bash_profile
-rw-r--r--   1 inex     inex           55 May 12 20:12 .bashrc
-rw-r--r--   1 inex     inex          375 May 12 20:12 .cshrc
-rw-r--r--   1 inex     inex          286 May 12 20:12 .emacs
drwxr-xr-x   2 inex     inex         1024 Sep 28 02:52 .ncftp/
-rw-r--r--   1 inex     inex          208 May 12 20:12 .nexrc
-rw-r-----   1 inex     inex           13 May 12 20:12 .qmail
-rw-r-----   1 inex     inex           43 Sep 30 12:30 .qmail-member
drwxr-xr-x   2 inex     inex         1024 May 17 19:05 .ssh/
drwxr-xr-x   2 inex     inex         1024 Sep 26 23:03 lib/
drwxr-xr-x   5 inex     inex         1024 Oct  2 16:11 public_html/
drwxr-xr-x  13 inex     inex         2048 Sep 29 02:34 rps/
-rw-r--r--   1 inex     epnetfan      363 Jun 20 12:11 sample.txt

この出力の最下行を例に取って、この読み方を解説します。左から順に、

-rw-r--r-- ファイルモード
1 ファイルへの"リンク数"
inex ファイルの所有者
epnetfan ファイルの属するグループ
363 ファイルの大きさ(バイト単位)
Jun 20 12:11 ファイルの最終更新時刻
sample.txt ファイルの名前

を表しています。これらをファイルの「属性」と呼びます。 (なお、$ man ls としてみるとより詳しく分かります)

一番左側の表示の文字列はファイルの「モード」、すなわち ファイルの型(type)と利用権限(permission)を表しています。

d rwx r-x r-x

左端の1文字はファイルの型を示します。 とりうる文字と型は後述します。

続く文字列で利用権限を示しています。 利用権限の許可対象には

があり、それぞれに対する許可情報を

と読んでいます。

また利用権限には 3 種類あります。

ファイルモードの読み方は
  d rwx r-x r-x
  ^ ^^^ ^^^ ^^^
  |  |   |   |
  |  |   |   アザーズパーミッション
  |  |   |
  |  |   グループパーミッション
  |  |
  |  ユーザーパーミッション
  |
  ファイルの型(type)
とりうる文字は、
  - --- --- ---
  d rwx rwx rwx
  l   s   s   t
  s   S   S
  b
  c
  P
となっています。

左端の文字とファイルの型は、次のように対応づけられています。

- 通常のファイル
d ディレクトリ
l シンボリックリンク
s ソケット
b ブロックデバイス
c キャラクタデバイス
P 名前つきパイプ

また、利用権限は以下の通りです。

- その権限が出ていない
r 読み込み許可
w 書き込み許可
x 実行許可
s s ビットが立っていて、かつ実行許可
S s ビットが立っていて、かつ実行不可
t スティッキー(sticky)

s ビットについては後述します。 (スティッキー(sticky)については付録参照)

※ファイルの所有者, ファイルの属するグループを変更するには chown, chgrp といったコマンドを使用します.

[3.1.2] 利用権限の設定(ファイルモードの設定)

ファイルの利用権限を設定するには chmod コマンドを用います。 基本的な使い方は次の通りです(詳しくは man chmod )。

$ chmod <mode> file1 [file2 ...]

<mode> の部分には 0 から 7 までの数字を 3 桁並べたものが入ります。 左の桁から順にファイルの所有者、ファイルの所属グループ、 その他のユーザーに対する利用権限を示します。 各々の読みだし、書き込み、実行権限は 4, 2, 1 の数字で表され、 上の <mode> にはこの数字の和が代入されます。

許可 記号 数字
読込 r 4
書込 w 2
実行 x 1

例えば、モードを -rw-rw-r-- と変えたい場合、
-rw-rw-r--	
 42 42 4
 |  |  |
 6  6  4  <mode>
となるので、
$ chmod 664 file
とすれば変更できます。

上では <mode> を数字で与えましたが、記号で与えることもできます。 <mode> の数字列の代わりに、

対象 操作 許可
[ugao] [+-=] [rwxst]

という形式を "," で区切って並べます。

対象と操作の文字は以下の意味を表します。※許可の所はファイルモードと同じです。

対象   操作
u :所有者
g :グループ
o :その他のユーザ
a :全員(ugo と同じ)
 
+ :許可を与える
- :許可を取り消す
= :許可を設定する

この場合、先の例と同じ設定にするには次のようにします。

$ chmod u=rw,g=rw,o=r file

[3.1.3] s ビット

s ビットは、ユーザーに立っている時は suid(セットユーアイディー)、 グループに立っている時は sgid(セットジーアイディー)と呼ばれます。

suid の例として /usr/bin/passwd を見てみます。

$ ls -l /usr/bin/passwd /etc/passwd
-rw-r--r--   1 root   bin   734 Apr 19 13:25 /etc/passwd
-rws--x--x   1 root   bin  7736 Oct  3  1996 /usr/bin/passwd

/etc/passwd には各自の個人情報が記録されています。 このファイルにはアザーズ書き込み許可が出ていません。 よって通常ならユーザーはパスワードを変更することができません。 そこで suid という仕組みを使います。suid ビットを立てると、 そのプログラムはプログラムの所有者の権限で実行されます。

パスワードを設定/変更する際に passwd コマンドを使いますが、 絶対パスで表記すれば、これは /usr/bin/passwd を実行しています。 この場合 /usr/bin/passwd に suid を立てているので、 /usr/bin/passwd は root の権限で実行されます。 このためパスワードを変更できるわけです。

sgid は上のグループ版です。似たようなものなので説明は割愛します。


[3.2] ファイル保護をためしてみる

では, 実際にファイルを作ってみてパーミッションの変更等をしてみましょう.

[3.2.1] 下準備

同席の相方と互いのファイルを見ることができるかためしてもらいますが, login, logout を繰り返すのが面倒なのでちょっとおまじないをします. まず, もう一つ kterm を立ち上げ, 今 login しているアカウント(foo さん)の 相方(bar さん)になりかわります.

$ kterm &
< kterm をもう一つ立ち上げる.

新しく立ち上げた kterm を用いて以下のコマンドを打ち込んでみてください.

$ whoami
$ su bar
$ whoami
$ cd
< 現在のログインアカウント名を尋ねる (foo だったとする) 
< bar になりかわる. このとき bar さんのパスワード入力が必要.
< 無事 bar さんになっているか現在のアカウント名を尋ねる.
< bar さんのホームディレクトリに移動しておく.

以下, もともとあった kterm を "A ターミナル", あたらしく起動し bar さんになり変わった状態の kterm を "B ターミナル" と呼ぶことにします(もし3人の班なら同様に三つ目のktermを立ち上げてください).

[3.2.2] ファイルとディレクトリの作成

では, まず A,B 両ターミナルで以下の作業をして ディレクトリとファイルを作成してください.

$ cd
$ mkdir secret
$ echo 'secret-word' > ./secret/word.txt
$ chmod 777 secret 


$ chmod a+rwx secret/word.txt 



< ホームディレクトリに移動.
< secret ディレクトリを作成.
< 'secret-word' 部分は好きな単語に置き換える. secret ディレクトリの中に ファイルを作成. 
< chmod をつかって secret ディレクトリのパーミッションを変える.
       ただしファイルが相方から見えないようにすること. 
       例文の 777 だとうまくいきませんよ!!
< chmod をつかって secret/word.txt ファイルのパーミッションをかえる.
       ただしファイルが相方から見えないようにすること. 
       またまた a+rwx も悪例ですのでご注意を.

[3.2.3] ファイルを見てみましょう

foo さん, bar さん共に, 今作った相手のファイルを見てみましょう.

$ cat ~foo/secret/word.txt
あるいは
$ cat ~bar/secret/word.txt

お互いに相手のファイルが見えなければ成功です. もし見られてしまった場合は, 先の chmod コマンドを 先程とは違うモードで再度実行し, 見られない様にしてください.

見られないようにする方法がわかったら, 今度はいろいろな モードにしてその違いを確かめてください. ディレクトリのモードを変えると, そのディレクトリに移動できなくなったり するはずです. cd コマンドなどを試してみてください.

最後に自分の作った word.txt を消去してください. このとき, どのようなモードだとファイル消去できないかも是非試してください. 自分の卒論などを誤って消してしまわないためにも重要な知識です!!

UNIX ではファイルモードの設定によって, 他人のファイルを見ることが可能です. 大抵の場合, 普通に作成したファイルは他人が見れる状態にあるでしょう. もし本当に見られてはこまる内容のファイルはモードを正しい設定にするように 心がけましょう. 他人がみても良い設定のファイルは基本的に "見ても良い" 訳ですが, "mail" といった文字列のつく名前のファイルやディレクトリの中, あるいは個人的な情報であることが推測できるファイルは, 仮に見れる状態にあっても絶対にみてはいけません. また, 同様に見られては困るファイルを見れる状態で置いておくことも避けましょう. こういったファイルは見た方も, 見られた方も嫌な思いをしてしまいます.


[3.3] リンク

リンクには、"ハードリンク"と"シンボリックリンク"の2種類があります。

[3.3.1] ハードリンク

先に ls コマンドを用いた説明で、 その実行結果の左から2番目に表示される数字は、 リンク数を表すと述べたと思います。

$ ls -l sample.txt
-rw-r--r--   1 inex     epnetfan      363 Jun 20 12:11 sample.txt

これは正しくは「ハードリンク」の数を表しています。 ハードリンクの数は簡単に言うとファイルの「名前」の数を表しています。

人間は文字列(上の場合 'sample.txt')でファイルを識別しますが、 システムはファイルを「番号」として管理しています。 UNIX では、この番号を「i-ノード」と呼びます。 ファイルと i-ノード番号は1対1に対応(リンク)しています。

i-ノードという概念は、そもそも UNIX のカーネルが、それぞれのパーティションに、 装置番号(device number)を割り当て、 「ディスク」ではなく「ファイルシステム」 という論理的なレベルで処理を行うことに由来しています。 ファイルシステムは、論理的なブロックの集まりから構成され、 単位となるブロックの大きさはシステムによって異なります。

ファイルシステムは、次のような4つの部分に分けられます。

i-ノードには、次のような情報が含まれています。 ここで注意して欲しいことは、i-ノードには、ファイル名は含まれていないということです。

ls -i とするとファイルの i-ノード番号を実際に見ることができます。

$ ls -i sample.txt
  31657 sample.txt

ハードリンクの数は、 実はそのファイルの対応している i-ノード番号を参照しているファイルの数を表しています。

したがって同じ i-ノード番号をもつ別名のファイルを作ること、 即ちファイルに複数の名前をつけることができます。 これは "ln" コマンドで実行できます。

touch コマンドで空のファイル file1 を作り試してみましょう。 通常ファイルのリンク数は1です。

$ touch file1
$ ls -l file1
-rw-r--r--   1 inex     epnetfan   0 Jun 27 02:39 file1

ここで
$ ln file1 file2
とすると file1 に新しい名前 file2 を加える(リンクを張る)ことができます。
$ ls -l file1 file2
-rw-r--r--   2 inex     epnetfan   0 Jun 27 02:39 file1
-rw-r--r--   2 inex     epnetfan   0 Jun 27 02:39 file2

リンク数が2に増えています。 一方ディレクトリのリンク数は必ず2以上になります。 リンクを消すには rm コマンドを使います。

[3.3.2] シンボリックリンク

上の ln コマンドにオプション -s をつけて実行してみます。 これは「シンボリックリンク」と呼ばれ、 簡単にいうとファイルの「別名」をつけるようなものです。 類似のものに、Windows 系では「ショートカット」、MAC では「エイリアス」があります。

$ ln -s file1 file3
$ ls -l file1 file3
-rw-r--r--   2 inex     epnetfan   0 Jun 27 02:39 file1
lrwxrwxrwx   1 inex     epnetfan   5 Jun 27 02:45 file3 -> file1

ハードリンクの場合は i-ノードを直接参照しているのに対し、 シンボリックリンクは「ファイル名」を参照しています。 従って、上の例でも file1 のリンク数も増えませんし、 file3 のリンク数も1のままです。

シンボリックリンクの特徴をみるため、 次のようにコマンドを実行してみましょう。

$ rm file1
$ cat file3
cat: file3: No such file or directory

するとエラーが返されます。しかし、
$ ls file3
file3

となり file3 そのものは存在します。

これはシンボリックリンクでは「ファイル名」を参照しているためです。 参照先のファイル名が消去されてしまうと、 参照していたファイルの i-ノードを見ることができなくなり、 上の例では file3 を表示しようとするとエラーが返るのです。

ハードリンクとは異なり、 ディレクトリに対するシンボリックリンクは可能です。 シンボリックリンクを消すにはやはり rm コマンドを使います。


[3.5] 付録

[3.5.1] スティッキー(sticky)ビット

ルートディレクトリ( / )の下には tmp というディレクトリがあります。 このディレクトリの属性は、

$ ls -l /
drwxrwxrwt   6 root     root    1024 Jul  1 12:16 tmp

となっています。

モードをみると誰でも読み書きができるようになっていますが、 「アザーズ」の実行許可のところに "t" (スティッキー(sticky)ビット)が立っています。

ディレクトリにスティッキービットが立っている場合、 そのディレクトリの中にあるファイルの名前の変更や消去は、 そのファイルの所有者だけが行えるようになります。

[3.5.2] デバイスファイル

ls -l /dev としてみると以下のような出力が得られます。

$ ls -l /dev/
total 50
-rwxr-xr-x   1 root     root   14373 Nov 30  1996 MAKEDEV*
-rwxr-xr-x   1 root     root   28676 Nov 30  1996 MAKEDEV-C*
-rw-r--r--   1 root     root    1035 Nov 30  1996 README.MAKEDEV
-rw-r--r--   1 root     root    1434 Nov 30  1996 README.MAKEDEV-C
lrwxrwxrwx   1 root     root       4 Jan 15 21:46 X0R -> null
crw-r--r--   1 root     root 10, 134 Jun  8  1996 apm_bios
crw-------   1 root     root 16,   1 Feb 19  1994 arp
crw-rw-rw-   1 root     sys  10,   3 Jul 18  1994 atibm
crw-rw-rw-   1 root     sys  14,   4 Jul 19  1994 audio
crw-rw-rw-   1 root     sys  14,  20 Jul 19  1994 audio1
brw-r-----   1 root     disk 29,   0 Feb 16  1995 aztcd
crw-r--r--   1 root     root 10, 128 May 25  1996 beep
.
.
.
crw-r-----   1 root     disk 27,  25 Dec  8  1995 zqft1
crw-r-----   1 root     disk 27,  26 Dec  8  1995 zqft2
crw-r-----   1 root     disk 27,  27 Dec  8  1995 zqft3

ファイルモードを見ると、一番左が見慣れない c や b になっています。 このようなファイルは通常のファイルではありません。

UNIX では基本的にあらゆる物を抽象化して「ファイル」として扱います。 たとえばマウス(/dev/mouse) や画面等もファイルに抽象化して取り扱ってしまいます。

このようなファイルは「デバイスファイル(device file)」と呼ばれます。 デバイスファイルには、c で表されるキャラクタデバイスと、 b で表されるブロックデバイスがあります。

★ /dev/null ★

次を実行してみましょう。

$ ls > /dev/null
何も出力されません。では、これはどうでしょう?
$ cat /dev/null
やはり何も表示されません。

/dev/null というファイルは、 いかなる入力も捨ててしまう性質を持つデバイスファイルです。 コマンドの出力がうるさい時などに、リダイレクトと組み合わせて使います。

※リダイレクトについては次回、最低限 UNIX / Linux [III]で説明します。




最終更新日: 2003/10/24(中神雄一) Copyright © 2003 inex