最低限 UNIX / Linux [II]

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

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

[3.0] 本テキストの目的

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

[3.1] ファイルモード

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

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

[3.1.1] ファイルモード

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

$ ls -Flag
total 100
drwxr-xr-x    9 inex     inex         4096 Oct 13 18:55 ./
drwxrwsr-x  319 root     staff       12288 Oct 18 10:47 ../
-rw-r--r--    1 inex     inex          266 May 12  2000 .alias
-rw-------    1 inex     inex         6169 Jan 15  2003 .bash_history
-rw-r--r--    1 inex     inex          174 Mar 16  2001 .bash_logout
-rw-r--r--    1 inex     inex           91 May 12  2000 .bash_profile
-rw-r--r--    1 inex     inex           55 May 12  2000 .bashrc
-rw-r--r--    1 inex     inex          375 May 12  2000 .cshrc
-rw-r--r--    1 inex     inex          286 May 12  2000 .emacs
-rw-r--r--    1 inex     inex         1077 Oct 19  2001 .kkcrc
drwxr-xr-x    2 inex     inex         4096 Dec  6  2000 .ncftp/
-rw-r--r--    1 inex     inex          169 Sep 22  2001 .nexrc
-rw-r-----    1 inex     inex           13 May 12  2000 .qmail
-rw-r-----    1 inex     inex          120 Oct 21 16:52 .qmail-member
drwxr-xr-x    2 inex     inex         4096 May 17  2000 .ssh/
-rw-r--r--    1 inex     inex           39 Nov  3  2003 .users
-rw-r--r--    1 inex     inex         1919 Sep  8  2001 README
drwxr-xr-x    9 inex     inex         4096 Sep  3 16:56 bbs/
drwxr-xr-x    2 inex     inex         4096 Dec  1  2003 cgi-bin/
drwxr-xr-x    2 inex     inex         4096 Sep  3 11:44 lib/
drwxr-xr-x    7 inex     inex         4096 Sep 24 15:27 public_html/
drwxr-xr-x   13 inex     inex         4096 Sep 10 19:28 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) を表しています. 例えば, sample.txt のすぐ上の rps/ を見ると,

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)については[付録2]参照).


※ファイルの所有者, ファイルの属するグループを変更するには 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 ビットとは, あるファイルの実行者を「成り変わる」機能のことを言います.

s ビットには, SUID ビットと SGID ビットの二種類あります.

具体例で見て行きましょう. SUID の例として /usr/bin/passwd を見てみます.

第二回目の実習で, passwd コマンドが出てきました. passwd は /usr/bin/ ディレクトリに存在します. passwd コマンドを実行してパスワードを変更すると, /etc/shadow が書き変わるのでしたね. そこで, /etc/shadow のパーミッションを見てみると,

$ ls -l /etc/shadow
-rw-r--r--    1 root     root        22485 Oct 21 16:52 /etc/shadow

ですから, このファイルの書き込みができるのは, このファイルの持ち主, すなわち root だけです. しかし, 誰もがパスワードを変更したい(/etc/shadow が書き変わって欲しい) と思っています. どうやって /etc/shadow を書き変えることができるのでしょうか?

そこで /usr/bin/passwd のパーミッションを見てみます. すると,

$ ls -l /usr/bin/passwd
-rwsr-xr-x    1 root     root        24680 Apr  8  2002 /usr/bin/passwd
となっています.

左から 4 番目に s という文字が書かれています. これが SUID ビットで, このファイルが実行されると, プログラムの持ち主がこのファイルを実行したものと解釈されることを表します. つまり, passwd コマンドを実行すると, root が実行したものと解釈される のですから, /etc/shadow を書き換えることができるという訳です.

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


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

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


問題: 各自作ったファイルを, 同席の相方が見られないようにパーミッションを変更せよ.

[3.2.1] 下準備

以下の作業では, login, logout を繰り返すのが面倒なのでちょっとおまじないをします. まず, もう一つ kterm を立ち上げ, 今 login しているアカウント(foo さん)の 相方(bar さん)になりかわります.

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

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

$ whoami
foo
$ su bar
Password:
$ whoami
bar
$ cd
< 現在のログインアカウント名を尋ねる(foo だったとする). 

< bar になりかわる. このとき bar さんのパスワード入力が必要.

< 無事 bar さんになっているか現在のアカウント名を尋ねる.

< bar さんのホームディレクトリに移動しておく.

以下, もともとあった kterm を "A ターミナル", あたらしく起動し bar さんになり変わった状態の kterm を "B ターミナル" と呼ぶことにします.

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

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

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

$ chmod ??? secret 

$ chmod ??? secret/word.txt 

< ホームディレクトリに移動.
< secret ディレクトリを作成.
< 'secret-word' 部分は好きな単語に置き換える. 
    secret ディレクトリの中に ファイルを作成. 
< chmod をつかって secret ディレクトリのパーミッションを変える.
    ファイルが相方から見えないように ??? の部分を考えよう. 
< chmod をつかって secret/word.txt ファイルのパーミッションを変える.
    上と同様にファイルが相方から見えないよう ??? の部分を考える. 

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

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

$ cat ~foo/secret/word.txt
$ cat ~bar/secret/word.txt

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

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

最後に自分の作った word.txt を消去してください. このとき, どのようなモードだとファイル消去できないかも是非試してください.


発展問題: word.txt もしくはディレクトリ secret のモードを変更し, secret/word.txt ファイルが消去できないようにせよ.

この知識は自分の卒論などを誤って消してしまわないためにも重要です! つまり, 消去できないようにファイルのモードを変更しておけば, 誤って rm コマンドを実行しそうになったときも, 消去されずに済むわけです!

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


[3.3] 付録1--リンク

リンクとは, あるファイルやディレクトリを, 別のファイルやディレクトリに関連付ける仕組みをいいます.

リンクには,

の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.4] 付録2

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

スティッキービットとは, ファイルまたはディレクトリの所有者だけが目的のファイルの削除や名前の変更を行えるようにする機能のことです.

s ビットの時と同様に具体例で見て行きましょう. ルートディレクトリ( / )の下には tmp というディレクトリがあります. このディレクトリのパーミッションを見ると,

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

となっています.

これによるとこのディレクトリは誰でも読み書きができるようになって いますが, 「アザーズ」の実行許可のところに t と書かれています.

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

[3.4.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]で説明します.




最終更新日: 2005/10/22(森川靖大) Copyright © 2005 inex