パーミッションから学ぶ2進数/8進数の面白さ

Linuxの学び始めで、パーミッション設定をなんとなく覚えている人も多いと思うが、そんなパーミッション設定も面白いんだよということを伝えたいのでこの記事を書こうと思う。


# この記事を読んで欲しい人
- Linux初学者
- パーミッションって何? っていう人
- パーミッションについてはなんとなくわかるが、見よう見まねで権限を付与している人
- 2進数、8進数はなんとなくわかるが、メリットをイマイチ感じたことが無い人

# パーミッションについて (前提知識)
正式名称は「***ファイルパーミッション（file permission）***」。文字通りファイルに対する権限についてのことだが、ここで言う権限とはファイルに対する読み出し・書込みなどのアクセスに対する権限のことを指す。

本題に入るための前提知識を書いているので、知っている方は読み飛ばして結構。

## 表記例
例えば、SSHの公開鍵認証に必要な秘密鍵はパーミッションを`600`に設定しないと使えないのだが、実際にパーミッションを確認してみると以下のように表記されている。

```bash: 秘密鍵のパーミッション
hoge@My-PC:~$ ls -al .ssh/
...
-rw------- 1 hoge hogeGroup XXXX Sep 21 00:00 key-ssh.pem
...
```
上記の`-rw-------`部分がパーミッションの設定状況を示しているのだが、`- / rw- / --- / ---`と4つのブロックでそれぞれ意味するものが異なる。

### 1つ目のブロック (1文字目)
最初の1文字目はファイルの種類を示している。ファイル種別は色々あるが、よく使うのは以下の3つ。

- `-` : 通常ファイル
- `d` : ディレクトリ
- `l` : シンボリックリンク

上記例では、秘密鍵は「***ファイル***」なので、パーミッション表記の1文字目は`-`になっている。

### 2つ目のブロック (2～4文字目)
ここはファイル所有者自身、つまり***自ユーザー***に対する権限が表記されている。
ファイル所有者は上記例のパーミッション表記の後に記載されており、`hoge`がそれに該当する。
ちなみに`hogeGroup`はファイル所有のグループを指す。(後述)

表記方法は2～4文字目の計3文字の枠で、以下の文字を使ってそれぞれの権限状況を示している。

- `r` : 読み取り権限。*read* の略。
- `w` : 書込み権限。*write* の略。
- `x` : 実行権限。*execute* の略。

上記例では、秘密鍵のファイルは2つ目のブロック(2～4文字目)が`rw-`となっているので、読み取りと書込みの権限のみ付与されており、実行権限は付与されていないことがわかる。

### 3つ目のブロック (5～7文字目)
ここは***ファイル所有のグループ***のパーミッションを指す。グループとは複数のユーザーをまとめたもの。
例えば管理者権限を複数のユーザーに付与したい場合、`admin`グループを作成して、そのグループに`hoge1`・`hoge2`など複数のユーザーを所属させることで、まとめて権限管理をする時などに大活躍する。

表記方法はユーザーのブロックと同様で、3文字の枠を使ってファイルの権限状況を示している。

上記例では、3つ目のブロック(5～7文字目)が`---`なので、ファイルを所有しているグループ `hogeGroup`に対しては何も権限が付与されていないことがわかる。

### 4つ目のブロック (8～10文字目)
ここは***それ以外のすべてのユーザー・グループ***、いわゆる***不特定多数の第三者***に対するパーミッションを指す。
例えば、一般公開されているwebサイトのHTMLファイルなどは、不特定多数の第三者が見られることを想定しているため、このブロックに読み取り権限のみ付与することが多い。(逆を言えば絶対書込み、実行権限は付与しない)

表記方法はユーザー・グループと同様。

上記例では、4つ目のブロック(8～10文字目)が`---`なので、第三者に対しては何も権限が付与されていないことがわかる。


## パーミッションの設定方法
コマンドは `chmod` を使う。大きく分けて以下の2種類の記法がある。

### 1. 記号で指定する方法
こちらは上記で説明した`r` , `w` , `x` の表記を利用するので、直感的にもわかりやすい。以下の記号を組み合わせて表記する。

- 権限を設定するユーザー・グループの指定
    - `u` : ユーザー
    - `g` : グループ
    - `o` : その他第三者
- 権限の付与/剥奪を指定
    - `+` : 権限付与
    - `-` : 権限剥奪
- 権限の設定を表記
    - `r` : 読み取り
    - `w` : 書込み
    - `x` : 実行


```bash: 設定例
hoge@My-PC:~$ ls -al test.txt
-rw------- 1 hoge hogeGroup XXXX Sep 21 00:00 test.txt
# test.txtはユーザーhogeのみ読み取り・書込み可能。

hoge@My-PC:~$ chmod g+rw test.txt
# test.txtにグループ所有者に対して読み取り・書込み権限を付与。

hoge@My-PC:~$ ls -al test.txt
-rw-rw---- 1 hoge hogeGroup XXXX Sep 21 00:00 test.txt
# グループ所有者hogeGroupにも読み取り・書込み権限が付与されている。
```

### 2. 数字で指定する方法
1の方法だと複数の権限付与、剥奪の表記が複雑になってしまうが、こちらの方法ではユーザー・グループ・第三者をまとめて設定できるので記法がスッキリしている。だが、直感的にわかりにくい。

|数値|権限内容|権限表記|
|----|----|----|
|0|権限無し|---|
|1|実行権限|--x|
|2|書込み権限|-w-|
|3|書込み&実行権限|-wx|
|4|読み取り権限|r--|
|5|読み取り&実行権限|r-x|
|6|読み取り&書込み権限|rw-|
|7|読み取り&書込み&実行権限|rwx|

上記の数字を3つ組み合わせ、ユーザー・グループ・第三者の順に権限設定を表現する。
例えば、ユーザーにのみ`rw`の権限を付与したい場合はユーザーは`6`、グループ・第三者は`0`なので、`600`となる。

```bash: 設定例
hoge@My-PC:~$ ls -al test.txt
-rw------- 1 hoge hogeGroup XXXX Sep 21 00:00 test.txt
# test.txtはユーザーhogeのみ読み取り・書込み可能。

hoge@My-PC:~$ chmod 660 test.txt
# test.txtにグループ所有者に対して読み取り・書込み権限を付与。

hoge@My-PC:~$ ls -al test.txt
-rw-rw---- 1 hoge hogeGroup XXXX Sep 21 00:00 test.txt
# グループ所有者hogeGroupにも読み取り・書込み権限が付与されている。
```





# パーミッションの数字の意味を考える (本題)
これまでパーミッションについてとその設定方法を簡単に紹介してきたが、設定方法で`600`など数字を使う場面がある。
上記で紹介した数字と権限の対応表を暗記している人もいるかもしれないが、実はこれらは***とてもシンプルなルール***に基づいて決まっており、そのルールに大きくかかわっているのが2進数と8進数である。

## 2進数と8進数について

情報処理試験でも出てくる、***ITの超基本***。

- 2進数
    - 2を底として表現する方法。0と1しか使わない。(1の次は0)
    - 信号のON/OFFや、フラグ、TRUE/FALSEなど、2つだけで表現されるものととても相性が良い。
- 8進数
    - 8を底として表現する方法。0～7しか使わない。(7の次は0)
    - 2進数と相性が良く、長くなりがちな2進数表記をまとめて表記するときに使われる。

ITで2進数が重要な理由は、回路に電気を流す/流さないで0と1を表現しているため。それの集合体がみんな使っているパソコン。
ただ、2進数だけで表現していると画面が文字ですぐ埋まってしまうので、8進数や16進数に置き換えて表記することが多い。

## パーミッションの数字表記は8進数表記
上記で紹介した数字と権限の対応表は0～7までの数字なのでまさに8進数。つまり2進数に変換することができる。
0～7を2進数表記に変換すると以下のようになる。

|8進数表記|2進数表記|
|----|----|
|0|000|
|1|001|
|2|010|
|3|011|
|4|100|
|5|101|
|6|110|
|7|110|

## パーミッションの数字はそれぞれの権限のフラグを示しているだけ
上記の8進数と2進数の対応表とパーミッションの'r' , 'w' , 'x' の表記との対応表を並べてみる。

|8進数表記|2進数表記|権限表記|
|----|----|----|
|0|000|---|
|1|001|--x|
|2|010|-w-|
|3|011|-wx|
|4|100|r--|
|5|101|r-x|
|6|110|rw-|
|7|111|rwx|

察しの良い方はだいぶ前にお気づきだとは思うが、パーミッションの数字は実は***各権限の有無をフラグで表記しているだけ***なのだ。

ここまで聞くと、`600`がなぜユーザーだけに`rw`を付与しているかが腑に落ちると思う。

## とても理にかなっている8進数表記
例えば、`chmod`の数字表記を学ぶ際、以下のように習ったことがある or 書かれている記事を見たことがある人も多いだろう。

```
x=1, w=2, r=4と覚えておけば、あとは足し算すればOK。
例えば読み取りと書込み権限であれば4+2=6、読み取りと実行権限であれば、4+1=5と求めることができる。
```
これだけ聞くと「なんでそんな上手いこといくの?」となる人も多いと思うが、数字が8進数、もっと言えば2進数のフラグであることから辿っていくととても分かりやすい。

上記の例だと、読み取り権限は8進数だと`4`、2進数だと`100`。書込み権限は8進数だと`2`、2進数だと`010`。2進数で見ると、読み取り権限と書込み権限はビット(フラグ)の立つ位置(1の位置)が異なるため、それぞれのフラグに干渉しない。従って、2進数では以下のように足し算が簡単にできる。

```
'100' + '010' = '110'
```
答えの`110`は読み取りと書込み権限にビットが立っているわけだが、これは8進数で言うところの`6`に他ならない。

このように、8進数ないしは2進数はビットやフラグの表記ととても相性が良く、chmodになぜ数字表記の方法があるのかが理解できると思う。

# 執筆後の感想
自分もパーミッション設定をなんとなく覚えていた人だが、初めて意味を理解したときとても感動したのを覚えている。
2進数も8進数も大したものでもないし、法則はシンプルで当たり前のものなのだが、「***なるほど、こういう使い方ができるのか。考えた人かしこいな***」と感心した。

パーミッションはほんの一例でしかなく、2進数、8進数、16進数で表されているものはこの世界にたくさんあるので、気にしてみるとよりITが面白く感じると思う。
なんなら、普通の10進数の数字を見ていても「***あ、ここにビット立ってるじゃん***」とか思ったりできると、世界が面白く見えると思う。



# 参考
パーミッションについてはWikipediaがものすごくわかりやすく解説しているので一読すると良いと思う。
- [ファイルパーミッション - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%91%E3%83%BC%E3%83%9F%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3)