Perl入門ゼミ

テキスト処理、Linuxサーバー管理、Web開発ならPerl
  1. Perl
  2. ファイル操作

パーミッションについて理解しよう

UNIX系のOSでは、ファイルパーミッションという仕組みがあります。(このサイトでは便宜のため、UNIX系OSというのはUNIX系OSとLinux系OSの両方を指すことにします。)Perlは、WindowでもUnixでも実行できるマルチプラットフォームな言語ですが、根本的に仕組みが違う部分についてはWindowsとUNIXの両方で実行することができません。

Perlは、Unix生まれですので、標準関数の中にもUnix系OSでのみ意味を持つものがあり、そのひとつがファイルパーミッションに関するものです。今回は、ファイルパーミッションというUNIXの概念を簡単に解説します。

パーミッション(permission)は日本語に直すと「許可」という意味です。この許可の意味は以下のように考えるとわかりやすいと思います。(ここからは、ファイルパーミッションを略してパーミッションと呼びます。)

パーミッションの考え方

「あるファイル」に対して「だれだれ」「なになに」をすることを許可する。

パーミッションは、「ファイル」単位で設定されます。また例外なくすべてのファイルに対して設定されます。

パーミッションの指定では「だれ」に対して許可するのかということを記述します。「だれだれ」という部分に記述できるのは、「そのファイルの所有者」「そのファイルを所有しているグループ」「任意のユーザ」になります。

パーミッション指定では、「なに」をすることを許可するのかということを記述します。「なになに」という部分に記述できるのは、「読み込み」「書き込み」「実行」になります。複数の指定をすることができます。

パーミッションの記述の例をあげると以下のようになります。

ファイル「a.txt」に対して

「このファイルの所有者」が「書き込み」と「読み込み」をすることを許可し

「このファイルの所有グループ」が「書き込み」と「読み込み」をすることを許可し

「任意のユーザ」が「読み込み」をすることを許可する

この説明のなかで、まだ説明していない用語があるので、以下で説明します。

ユーザとは

UNIXには、ユーザという概念があります。すべてのユーザはOSによって管理されてます。

まず最高の権限を持つ「root」ユーザとUNIXのインストール時に存在します。rootユーザは、ファイルのパーミッションにかかわらずファイルへの書き込み、読み込みを行うことができます。他のユーザがファイルの書き込みを禁止したとしてもrootユーザだけは、そのファイルへの書き込み権を持ちます。

rootは、他のユーザを作成することができます。UNIXはマルチタスクOSです。たとえばあなたがプロジェクトに参加したときに、管理者はroot権限であなた用のユーザを作成します。

グループとは

UNIXには、グループという概念があります。たとえば、あるプロジェクトの開発で使用するファイルがあるとします。このファイルは、開発やテストを担当する人以外からは、勝手に書き込まれたりしたくはありません。

こんなときは、管理者がroot権限で、そのプロジェクト用のグループというものを作成します。そして、そのプロジェクトを担当するユーザを、グループに追加します。またユーザは、複数のグループに所属させることができます。

グループを作成することで、グループ単位のパーミッションを設定することができるようになります。

ファイルの所有者とは

UNIXでは、ファイルは必ず誰かが所有しています。所有者のいないファイルはありません。たとえば、あなたがファイルを作成すると、ファイルの所有者は、あなたのユーザIDになります。

ファイルの所有者グループとは

UNIXでは、ファイルは必ずどこかのグループが所有しています。あなたが自分のユーザで新規にファイルを作成した場合は、グループ名は、ユーザ名と同じになります。(これは、ユーザを作成したときに、同時に同じ名前のグループ名が作成されており、そのグループ名が設定されるからです。)

実行権限とは

「なになに」という部分に指定できる「読み込み」と「書き込み」権限は、説明がなくても理解できると思いまので、「実行」権限について説明します。

ファイルには、「データを保存しておくためのファイル」と、「プログラムが書かれたファイル」があります。プログラムが書かれたファイルの一例は、「sample.pl」のようなPerlスクリプトが書かれたファイルです。

コマンドプロンプトで実行するときは、perl sample.pl のように、perlというプログラムに、sample.pl というスクリプトを渡して実行しています。これは、sample.plはデータファイルとして、perlプログラムに渡されて実行されているということです。

UNIXではファイルに実行権限を与えることで ./sample.pl というように、直接ファイル名を指定し、Perlスクリプトを実行することができます。(./ はカレントディレクトリという意味です。sample.pl という記述では、UNIXの仕様上実行はできません。)

#!/usr/bin/perl

という記述は、このファイルに実行権限が与えられている場合、/usr/bin/perl というプログラムでこのファイルを実行してくださいというOSに対するお願いです。

これで、ファイルパーミッションについての用語の解説は終わりです。

ファイルのパーミッションを実際に変更するにはchmod関数を使用します。chmod関数の解説は以下を参考にしてください。

ファイルパーミッションの表現方法

ファイルパーミッションの表現方法について解説します。

まず、「読み込み権限」「書き込み権限」「実行権限」を表現する方法について解説します。UNIXにおいては、これらを3桁のビット列で表現します。3桁のビットの意味は以下のようになります。

  読み込み 書き込み 実行
1 1 1
不可 0 0 0

3桁目が読み込み権限を表すビット、2桁目が書き込み権限を表すビット、1桁目が実行権限を表すビットになります。1であれば権限があり、0であれば権限がないということを意味します。

たとえば、ビット列が110ならば、読み込み権限と書き込み権限があり、101ならば読み込み権限と実行権限があります。

ファイルパーミッションの8進数表現

ファイルパーミッションは単なるビット列ですが、便宜のために8進数で指定することが多いです。chmodというコマンドでパーミッションを変更する場合、sysopen関数でパーミッションの指定する場合などに8進数を使います。

2進数(ビット列)と8進数の対応を記載しておきます。

2進数 8進数 2進から8進への変換
000 0 4×0  +  2×0  +  1×0
001 1 4×0  +  2×0  +  1×1
010 2 4×0  +  2×1  +  1×0
011 3 4×0  +  2×1  +  1×1
100 4 4×1  +  2×0  +  1×0
101 5 4×1  +  2×0  +  1×1
110 6 4×1  +  2×1  +  1×0
111 7 4×1  +  2×1  +  1×1

この中でよく使われるのが、6(110,読み込みと書き込み)、 7(111,読み込みと書き込みと実行)、4(100,読み込み)、5(101,読み込みと実行)の4つです。この4つの数字については覚えておくと便利です。

ファイルパーミッションの文字表現

ファイルパーミッションは人間が読みやすいように文字で表現されることも多いです。chmod関数でパーミッションを指定するときや、ls -l コマンドでファイルの詳細情報を表示するときに使われたりします。

読み込み権限のビットは「r」、書き込み権限のビットは「w」、実行権限のビットは「x」で表現されます。ビットが立っていない場合は「-」で表現されます。

これを踏まえて対応表をもう一度作って見ます。

2進数 8進数 文字表現
000 0 - - -
001 1 - - x
010 2 - w -
011 3 - w x
100 4 r - -
101 5 r - x
110 6 r w -
111 7 r w x

この対応表を書けるようになれば、パーミッションの理解は完璧です。

パーミッションを「所有者」「グループ」「任意のユーザ」に設定する

「所有者」「グループ」「任意のユーザ」に対してファイルパーミッションを設定する方法を解説します。 以下の表を使うと、パーミッションは3ビットで表現され、以下のようになります。

2進数 8進数 文字表現
000 0 - - -
001 1 - - x
010 2 - w -
011 3 - w x
100 4 r - -
101 5 r - x
110 6 r w -
111 7 r w x

これを「所有者」「所有グループ」「任意のユーザ」の順に並べたものが、UNIXにおけるファイルに対するパーミッションの表現になります。

たとえば、ファイルの所有者が「読み込み権限」と「書き込み権限」を持ち、所有グループと任意のユーザが「読み込み権限」を持つならパーミッションの表現は以下のようになります。

  所有者 所有グループ 任意のユーザ
2進 110 100 100
8進 6 4 4
文字 r w - r - - r - -

意味を理解しやすいのは、2進数か文字表現ですが、9文字書かないといけないので引数で指定する場合などめんどうです。ですので、引数で指定する場合は、8進数で指定することが多いです。8進数だけを見てすぐに意味がわかるようになると便利です。

よく使われるパーミッションの8進数表現

データファイルの場合

パーミッション 意図
644 自分だけが読み書きしたい。他の人は読み込みだけを許可する。
664 グループで読み書きを許可したい。他の人には読み込みだけを許可する。
666 だれでも自由に読み書きしてよい
600 自分だけが読み書きできる。他の人は読み込みもしてほしくない

実行ファイルの場合

755 自分だけが実行と読み書きができる。他の人には実行と読み込みを許可する
777 だれでも実行してもよいし、だれでも読み書きしてもよい

ディレクトリのパーミッション

ディレクトリに対するパーミッションの意味はファイルに対するパーミッションの意味と少し異なります。ディレクトリに対するパーミッションの意味を解説します。

UNIXにおいてはディレクトリというのは特殊なファイルです。普通のテキストファイルならばファイルの中身は文字列が書かれていますが、ディレクトリにはファイルの情報が書かれています。

ls -l ディレクトリ名 

というコマンドで、ディレクトリの中身を覗くと

[root@colinux y-kimoto]# ls -l dir1
合計 16
-rw-rw-r-- 1 y-kimoto y-kimoto 164 2008-05-28 00:36 b.pl
-rw-rw-r-- 1 y-kimoto y-kimoto   6 2008-08-16 10:26 c.txt
----rw-rw- 1 root     root       6 2008-08-16 10:30 d.txt

のようになっています。

ディレクトリはファイルの情報が書かれている特殊なファイルです。

ディレクトリに対する読み込み権限と書き込み権限

ディレクトリを特殊なファイルだと理解するとディレクトリに対する読み込み権限と書き込み権限は理解しやすくなります。

ディレクトリに対する読み込み権限とは、ディレクトリに書かれたファイル情報を読み込むことができる権限のことです。たとえば、ディレクトリに対して読み込み権限を与えなければ、ls コマンドでディレクトリの情報を表示することができません。

ディレクトリに対する書き込み権限とは、ディレクトリに書かれたファイルの情報を変更する権限です。たとえば、ディレクトリにファイル追加したり、削除することができません。

ここで気にとめておいてほしいことは、ファイルを削除したり追加したりする権限はディレクトリに対する書き込み権限によって設定するということです。ファイルに対して書き込み権限を与えないとしても、ディレクトリに書き込み権限があればそのファイルを削除することができます。

ディレクトリに対する実行権限

ディレクトリには必ず実行権限をつけます。ディレクトリにたいする実行権限をなくすとlsでディレクトリの内容を見ること、cdで移動すること、ディレクトリの中にあるファイルの情報を変更することなど、ディレクトリとディレクトリの中にあるファイルに対する操作のすべてを行うことができなくなります。

ディレクトリに対する実行権限をなくす意味はほとんどありません。ディレクトリに対しては実行権限を必ずつけて、読み込み権限と書き込み権限で設定を行えば十分です。

よく使われるディレクトリのパーミッション

パーミッション 意図
755 ファイルの追加や削除を自分だけが行いたい
777 ファイルの追加や削除をすべてのユーザに許可してもよい

ファイルパーミッションを調べる

パーミッションを調べる方法を解説します。ファイルパーミッションを調べるには、stat関数を使ってファイルパーミッションの情報を取り出します。3要素目がモード情報になります。取得した S_IMODE 関数で変換すると純粋なパーミッションの情報になります。

use Fcntl ':mode';
my $mode = (stat $file)[2]; 
printf "%03o\n", S_IMODE($mode);

ビット演算できる定数や関数です。

# パーミッションに関する定数
S_IRWXU S_IRUSR S_IWUSR S_IXUSR
S_IRWXG S_IRGRP S_IWGRP S_IXGRP
S_IRWXO S_IROTH S_IWOTH S_IXOTH

# Setuid Setgid Stickiness SaveTextに関する定数
S_ISUID S_ISGID S_ISVTX S_ISTXT

# ファイルタイプに関する定数
S_IFREG S_IFDIR S_IFLNK S_IFBLK S_IFCHR S_IFIFO S_IFSOCK S_IFWHT S_ENFMT

# ファイル演算子と同じ役割を果たす関数
S_ISREG($mode) S_ISDIR($mode) S_ISLNK($mode)
S_ISBLK($mode) S_ISCHR($mode) S_ISFIFO($mode) S_ISSOCK($mode)

stat関数が返す3番目のモード情報は、Fcntlで定義されている定数とビット演算を行うことでたくさんの情報を取り出すことができます。

パーミッションを調べるサンプル

パーミッションを調べるサンプルです。

use strict;
use warnings;

# ファイルパーミッションに関する定数をインポート
use Fcntl ':mode';

my $file = shift || die "Usage: $0 file\n";

# stat関数の戻り値の3つ目の要素がファイル
# パーミッションの情報
print "ファイルパーミッションの取得する。\n";
my $mode = (stat $file)[2];

# S_IMODE関数で数値に変換
printf "$fileのパーミッション(8進表示): %03o\n", S_IMODE($mode);
printf "$fileのパーミッション(2進表示): %09b\n", S_IMODE($mode);

ビットマスクとは

ビットマスクはsysopen関数やmkdir関数でのファイルやディレクトリの作成時のパーミッションに影響を及ぼします。

たとえばsysopen関数で指定するパーミッションが666で、ビットマスクの設定が022だった場合、作成されるファイルのパーミッションは644になります。

ファイルをプログラムで作成する場合は、パーミッションの値をファイルの場合は666、実行ファイルやディレクトリの場合は777にしておくほうがよいです。こうしておけば、そのプログラムを使う人はビットマスクを指定することで作成するパーミッションを自由に変更できます。

ビットマスクについては、以下で詳しく解説しています。

Giblog