UNIXの基礎（前編）

# この記事について

UNIX系のパソコンについて基本的なことをまとめています。2003年という少し前の本になりますが、山口先生、古瀬先生らの[UNIX Super Text](https://www.amazon.co.jp/新The-UNIX-Super-Text-改訂増補版/dp/4774116823)という素晴らしい本があったので、これを参考にしています。この本の内容は、古い記述もたくさんあります（記憶装置として磁気テープとかが紹介されてます）が、そういう点は飛ばして、今も変わらないところを中心に解説します。

- `cd`とか`ls`とか基本的なUNIX系コマンドは使えるけどbashとかUNIXとかよくわからない
- Linux系ってどうやって動いているの？
- 環境変数ってなに？

という人向けの記事になると思います。かなり文量が多いので、前後編に分けました。後編は以下のリンクをどうぞ。

UNIXの基礎（後編）
https://qiita.com/minnsou/items/2f8173b08c0a3d5cfc48

# 書式
・`[ ]`は省略可能
・`|`はそのいずれかならOK（例えば`[a|b|c]`なら`a`か`b`か`c`か）
・`filename...`のように`...`がある時は`filename`を空白で区切っていくつも入力可能

これは`man`コマンドなどでマニュアルを見る時にも共通の書き方である。

# 歴史

UNIXはAT&T(The American Telephone & Telegraph company)の**Bell研究所**で1969年に動き出した。UNIXには大きく分けて**BSD系**と**System V系**の2種類がある。

・BSDはBerkeley Software Distributionの略で、**カリフォルニア大学バークレー校**を中心として機能拡張されたUNIX。例えばMacOSはBSD系に属する。

・System V系はAT&T社に由来するUNIXで「**システムファイブ**」と読む。Sun Microsystems(現oracle)が作ったSolarisとかはSystem V系に属する。

また、GNUプロジェクトによりUNIXを真似した**Linux**が作られる。LinuxはBSD系とSystem V系の両方の特徴が混じっているが、**正式なUNIXではない**。

要はMacOSもSolarisもLinuxのUbuntuとかも全部UNIX（正確にはUNIX系）なので、この記事の話は**ほぼ適用できる**。

# UNIXの基本

### キーボードの見方

キーの表面には文字が書かれており、このキーの表面を**キートップ**という。**shiftキーを押すと上部**、**かなキーを押すと右半分**、何も押さないと左下の文字になる。**Caps Lockはshiftキーを押している状態**になる。

<img width="300" alt="スクリーンショット 2020-03-31 12.54.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395943/6d585cb6-b473-3abe-1b97-0ee2ffe07f15.png">

### パスワードの変更

`passwd`コマンドを使う。

### プロンプト 

**プロンプト**はターミナルを開くと出てくる記号のこと。
<img width="605" alt="スクリーンショット 2020-03-31 15.29.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395943/67f9120e-09cf-ee4c-7ab2-de16963ca8b9.png">
上の例はラズパイにログインした時の表示であるが、最終行の`pi@raspberry:~ $`の部分をプロンプトという。csh系(cshとかtcshとか)のプロンプトは`%`、sh系(shとかbashとかzshとか)のプロンプトは`$`、スーパーユーザのプロンプトは`#`が一般的。

### I/Oリダイレクションと標準入出力

UNIXにはコマンドへの入力やコマンドからの出力を簡単に切り替える機能が用意されている。これを**I/Oリダイレクション**という。`echo 1 + 2 > aa.out`とかの`>`によって出力を切り替えている。なお、`>`はそのファイルに上書きするもので、末尾に追加したい時は`>>`を使う。

例えば`bc < aa.out > answer`とすれば`answer`には3が入る。なお`bc`コマンドは計算をしてくれるコマンド。

詳細は後半の「[bashプログラミング](https://qiita.com/minnsou/items/2f8173b08c0a3d5cfc48#bashプログラミング)」の章で解説する。

### manについて

UNIXのオンラインマニュアルを参照するには`man`コマンドを使う。章を指定するときには`man section title`という書き方をする。sectionが指定されない時は、最初に見つかった章のマニュアルが表示される。

1. ユーザーコマンド
2. システムコール
3. ライブラリ関数
4. デバイスとネットワークインターフェース
5. ファイルフォーマット
6. ゲームとデモ
7. 公共ファイル、テーブル、TROFFマクロ
8. メンテナンスコマンド

以上は標準的な章構成で、実際にはこれ以外の章があったりする。

キーワードで検索したいときには
`man -k keyword`とする。

これらのマニュアルは、`/usr/share/man`や`/usr/man`に存在するが、そのマニュアルは`roff`というデータ形式で記述されている。これらのマニュアルを直接見たいときには`nroff -man filename`のように`nroff`コマンドを使う。

### ディレクトリ

`.`は**自分自身**のディレクトリ、`..`は**親**のディレクトリの名前を指す。`rmdir`コマンドは空のディレクトリを消すコマンドだけど、この二つは入っていてもOK（以下の例のように、空のディレクトリでも`ls -a`すると必ず`.`と`..`が入っているのが確認できる）。
<img width="255" alt="スクリーンショット 2020-03-31 16.14.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395943/51e1c7a2-e4e9-d777-e495-70af7bc8fd40.png">
ホームディレクトリは`~`で指定する。また`~name`とユーザー名を書いた時はユーザー名がnameの人のホームディレクトリを表す。

### ファイルの属性

UNIXのファイルとディレクトリは、所有者、更新された日付などの**属性**を持っている。`ls -l`コマンドでファイルの属性が表示される。

属性の１つに**モード**がある。これはファイルの型とファイルへのアクセスを決めるためのもの。
モードの一番最初の文字は**ファイルの型**を表し、-ならファイルで、dならディレクトリとなっている。
続く9つの文字はアクセスの可否を表す。rは読み出し可、wは書き出し可、xは実行可（ディレクトリの時は検索可）。最初の3文字がファイルの所有者、次の3文字がファイルが属しているグループのメンバ、最後の3文字がそれ以外の人を表す。
<img width="480" alt="スクリーンショット 2020-03-31 16.05.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395943/d1cfc2be-c0e5-8bfa-8e55-e52022d438bc.png">
モードを変更するには`chmod`コマンドを使う。
`chmod set file1 file2 ...`という書式
`set`は`[ugoa][=+-][rwx]`で指定する。アルファベットはそれぞれuser, group, others, allの意味。
例えば`chmod go+r file`ならグループとそれ以外の人に対するfileの読み出し可能の許可を与えるということ。

ここも「[ファイルとディレクトリについて](https://qiita.com/minnsou/items/6b6b74fcd79bd00ace1a#ファイルとディレクトリについて)」の章で詳しく扱う。

### プロセス

ネットワークからの要求に対してサービスを提供するプロセスや、プリンタの制御をするプロセスは特定の端末と結び付けられていない。このように端末と結び付けられていないプロセスのことを**デーモンプロセス**という。`ps`コマンドの端末表示名(TTとかTTYで表示される行)が?になっているものはデーモンプロセス。

キーによるプロセスの強制終了について、`Ctrl-C`が有名でみんな使うけど、`Ctrl-\`もできる。`Ctrl-\`ではデバッグ用にcoreという名前のファイルができる。

ここも「[プロセスについて](https://qiita.com/minnsou/items/6b6b74fcd79bd00ace1a#プロセスについて)」の章で詳しく解説する。

# bash入門

### シェルとは

コマンドを実行するために使われている**シェル**について、ちゃんと解説していく。まずは、シェルが何をするものなのかを理解するために、「コマンドを実行する」までにどのような処理がなされるかをざっと眺める。次の1から6までの処理が行われている。

1. プロンプト（`$`とか`%`とか）を出力してコマンドの入力を促す
2. キーボードから入力された文字をEnterが押されるまでためておく
3. Enterが押されたら、その文字列を空白などで区切ってコマンドの文字列と引数の文字列に分ける
4. コマンドの名前からその名前のプログラムを見つけ出す
5. 見つけたプログラムを起動して、引数の文字列を渡す
6. 特に指定しなければ、シェルは起動したプログラムが終了するまで待つ

文字列として与えられるコマンドを解釈、実行するものを一般に**コマンドインタプリタ**と言う。UNIXのではOSの中心にカーネルという核があるが、コマンドインタプリタはカーネルの機能を使ってキーボードから文字を受け取ったりプログラムを起動したりする「殻」の部分に位置する。なのでUNIXのコマンドインタプリタは**シェル**と呼ばれている。

シェルにはshやcsh、bash、fish、zshなどたくさんあるが、今回は**bash**に話を絞る。Linuxの標準のシェルはbashだし、Macも前までbashだったから(macOS Catalinaからzshになった）。この章で出てくる大半の話はどのシェルでも同じように動作する。

### ログインシェル

ログインに成功すると、シェルが起動されてキーボードからコマンドを受け付けるようになる。このシェルを**ログインシェル**という。

ログインシェルには
1. ログイン直後に起動されるシェルの種類
2. ログイン直後に起動されるシェルのプロセス

の2つの意味がある。どちらの意味で使っているかは文脈で判断すべし。UbuntuやMacとかのデフォルトのログインシェルはbash（MacはMacOS Catalinaからzsh）である。

シェルは基本的に`exit`コマンドでも`logout`コマンドでも終了できる。ただしログインシェルじゃない時に`logout`してもそのシェルを終わらせることはできないので注意。

### キーバインド

コマンドライン編集にはEmacsのキーバインドが使える。だから`Ctrl-P`で一つ前のコマンド履歴が遡れるし、`Ctrl-A`で行頭に移動できる。もしviっぽく使いたければ`set -o vi`と打てば良い。

よく使うEmacs風のキーバインドは以下

- `Ctrl-P` コマンド履歴を戻る(↑と同じ、previous line)
- `Ctrl-N` コマンド履歴を進む(↓と同じ、next line)
- `Ctrl-F` カーソルを右へ1文字進める(forward char)
- `Ctrl-B` カーソルを左へ1文字進める(bach char)
- `Ctrl-A` カーソルを行頭に移動(beginning of line)
- `Ctrl-E` カーソルを行末に移動(end of line)
- `Ctrl-D` カーソルの位置の文字を削除(delete)
- `Ctrl-K` カーソルより右を全て削除(kill line)

### リダイレクション

コマンドの実行結果は基本的に画面に表示されるが、表示された結果を使って次の処理をしたい時がある。シェルにはコマンドの入力や出力を切り替える機能を持っている。切り替えの対象となる入出力として、

- 標準入力（普通はキーボード）
- 標準出力（普通は画面）
- 標準エラー出力（普通は画面）

の三つは切り替えがある。`>`を使って標準出力先などを変更することを**リダイレクション**、**リダイレクト**と呼ぶ。

ここの詳細も後半の「[bashプログラミング](https://qiita.com/minnsou/items/2f8173b08c0a3d5cfc48#bashプログラミング)」の章で述べる。

### パイプ

**標準出力と標準入力を繋ぎたい**2つのコマンドを`|`で並べること。これによりファイルに中間結果を出力する必要がなくなる。
例　`ps ux | grep user名 | sort -r`
これにより`ps`コマンドで`user名`が含まれているものをソートして表示される。`ps ux`の出力を`grep user名`に渡し、その出力を`sort`に渡すという感じ。`user名`を自分のものに変えて実行してみよう。

`>`と似てるけど、`>>` は標準出力の出力をファイルの末尾に追加する。`>&`だと標準出力だけでなく標準エラー出力もリダイレクションされる。なお、cshのパイプには`|&`という標準出力と標準エラー出力を同時に送るコマンドがあるが、bashでは使えない。bashは`|`だけで標準出力も標準エラー出力も送る。


### 変数

シェルでは普通のプログラミング言語と同じように、**変数**が使える。`echo $x`というコマンドで変数xの中身を確認できる。bashでは、変数の代入は`x=12`のように行う。`=`の両端にスペースは入れない。変数には**シェル変数**と**環境変数**の2種類がある。

環境変数は、**全てのサブプロセスが知ることのできる変数**である。`export variable`で変数`variable`を環境変数に設定できる。環境変数は起動されたコマンドから**参照できる**が、シェル変数は**参照できない**。以下の例を考える。
<img width="427" alt="スクリーンショット 2020-04-04 13.19.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395943/9296ad81-f149-86c8-ff38-1d26cc5c9fcd.png">

環境変数には、コマンド検索に使われる`PATH`やホームディレクトリを指定する`HOME`などがある。また全ての環境変数は`printenv`コマンドや`export`コマンドで見ることができる。

シェル変数は、**シェルで使われる全ての変数**を指す。bashを起動した時点で勝手に設定される**組み込み変数**(例えば端末の表示列数を表す`COLUMNS`とか)もシェル変数であるし、環境変数もシェル変数である。全てのシェル変数を見たい時は`declare`コマンドで見れる。

### メタキャラクタとエスケープ

コマンドラインの文字には「シェルが解釈する文字」（`>`とか`|`とか）と「コマンドに渡される文字」（コマンド名や引数など）がある。「シェルが解釈する文字」を**メタキャラクタ**という。メタキャラクタとして解釈しないで単なる文字として扱うことを**エスケープする**という。

`\`を使えば全てのメタキャラクタをエスケープできる。でも複数ある時はそれぞれに`\`をつけるのは面倒なので、`''`で囲むという方法もある。ただしこれでも`!`はエスケープされない。また`""`で囲むという方法もあるけど、これも`!`や`$`はエスケープされない。

例えば`a$1`という名前のディレクトリが直下にあったとして、`cd 'a$1'`で移動ができるが、`cd "a$1"`では移動できない。これは`$1`が変数だと解釈され、空文字列に変更される(もし変数に値が入っていたらその値に変更される)からである。

### ファイル名置換

`*`は任意の文字列、`?`は任意の1文字、`[str]`はstrの中の1文字、`{str1,str2,...}`はそれぞれをファイル名置換したもの（つまりstr1とかの中に?とかが入っていないといけない）を示す。
また、例えば`[aA]`ならaかAを表す、`[0-9]`なら数字を表す。
<img width="628" alt="スクリーンショット 2020-03-31 20.01.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395943/6793461d-b5c9-ae7c-e8fb-7d358089a1a3.png">
これらは、ファイルの名前にシェルが変換する機能なので、それにマッチするファイルが存在しない場合はそのままの文字列が表示される。
<img width="628" alt="スクリーンショット 2020-03-31 20.06.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395943/00b29ad6-75dd-55af-9568-0209be87c6a3.png">

### ジョブ

UNIXでは一連の仕事しているプロセスの集合を**ジョブ**という。

**フォアグラウンドジョブ**：シェルがそのコマンドの終了までプロンプトを出さずに待っているジョブ。
**バックグラウンドジョブ**：シェルがコマンドの終了をまたずに、キーボードから切り離された状態で実行されるジョブ。バックグラウンドジョブにするためには末尾に`&`をつける。

順次実行の記号は`;`
例えば`cd /tmp ; du -a`とすれば`cd ..`コマンドの後に`du -a`コマンドが実行される。ちなみに`du`コマンドはDisc Usageの意味でファイルの容量を確認できる。

グループ化の記号は`()`
例えば`(cd /tmp ; du -a) > temp`としたとき、`temp`ファイルはカレントワーキングディレクトリに作られる。`()`で囲むことによって、それが一つのコマンドとなるようにサブシェルで実行される。bashでは`{}`も使えて`{ cd /tmp ; pwd ; }`とすればサブシェルではなくそのシェルで実行される。`{}`の前後にはスペースがいることに注意。

とりあえず`( cd /tmp ; pwd ; )`と`{ cd /tmp ; pwd ; }`をそれぞれ実行してみれば、実行後のディレクトリが違うことがわかるはず。前者を実行してもディレクトリは移動しないが、後者ではカレントワーキングディクレクトリが`/tmp`になっている。

### 終了ステータス

コマンドの成功・失敗を簡単な整数値で表したもの。正常に終了すれば0、異常終了したらそれ以外の値をとるのが基本。`echo $?`とすると一つ前のコマンドの終了ステータスが見れる（bashでは`$?`に終了ステータスが入っているので、`echo $?`で見れる）。例えばcan't open fileなら2、command not foundなら127が`$?`に入る。

コマンドの終了ステータスを利用して、実行を制御する簡単な方法は以下になる。より複雑な制御については、後半の「[bashシェルプログラミング](https://qiita.com/minnsou/items/2f8173b08c0a3d5cfc48#bashプログラミング)」に記述した。
・`&&`は前のコマンドが正常終了したら、そのあとのコマンドを実行する
・`||`は前のコマンドが異常終了したら、そのあとのコマンドを実行する
例えば`cd /aaa && ls`というコマンドなら`/aaa`は(たぶん)存在しないので`ls`が実行されないけど、`cd /aaa || ls`なら`ls`は実行される。

### ヒストリー機能

以前に入力したコマンドを簡単に参照できる機能をシェルは備えている。
`history`コマンドで今まで打ったコマンドの一覧を見ることができる。`!!`とすると直前のコマンドを実行。`!str`とすると先頭の文字列が`str`であるもっとも近いコマンドを実行する。bashは↑を押せば以前のコマンド履歴を遡れるが、何回も↑を押すのが面倒な時には`!str`は便利である。例えば、pythonでプログラムを何回も実行させる時に`python foo.py`とかを繰り返し実行する時は、`!p`と押すだけで良い。

ヒストリーで記憶しているのはコマンドライン全体だが、その一部だけを使いたい時がある。コマンドラインを空白でワードに区切り、その中から必要なワードだけを指定できるものとして**ワード指定子**が存在する。`:num`ならnum番目のワード（つまり0ならコマンド名となる）。`:*`ならコマンド名を除く全てのワードのように指定する。

例えばヒストリーに`554 cd ~/Desktop`があったとき(554番目に`cd ~/Desktop`というコマンドを打っていた時の話、この順番は`history`コマンドで見れる)、`echo !554:1`とすると`echo ~/Desktop`が実行される。

### コマンドサーチパス

1. commandが`/`を含めば、パス名を指定したものとしてそのプログラムを実行
2. commandが組み込みコマンドなら、その組み込みコマンドを実行
3. シェル変数`PATH`を使って、実行可能なファイルを探し、最初に見つけたものを実行
4. Command not foundを出す

コマンド名に対してどのファイルが実行されるかを知るには`which`コマンドを使う。

### こんな時どうする

キー入力がおかしい時は、まずはCaps Lockやかなキーが押されていないかを確認する。キーボードや本体の状態に問題がない時は、端末回線設定をリセットする。例えばBSD系なら`reset`コマンド、System V系なら`stty sane`コマンドをいれる。またBackSpaceキーで文字が消せずに`^H`が表示される時は、`stty erase ^H`と設定し直すのも良い。

異常な名前のファイルができたとき、`rm -i *`コマンドを使うのが良い。`-i`オプションは消す時に一つ一つ確認してくれるもので、シェルのメタキャラクタを含んだファイル名とか大丈夫である。でも`/`を含んだファイル名はこれでも消せない。

キー入力がおかしくて、ログアウトすらできない時は、外部からログインシェルを終了させる。`ps`コマンドからプロセスIDを見つけて、`kill`コマンドを使う。ただしシェルは通常のkillコマンドでは殺すことができず、`kill -HUP 10089`のようにハングアップシグナル(もしくはキルシグナル)を使う必要がある。

### 知っていると便利なコマンド集

・`whereis`コマンドでも、指定したコマンドのパス名を表示できる。ただし、これはコマンドサーチパスを探すのではなく、あらかじめ決められたディレクトリを全て探す。

・`file`コマンドは引数で指定したファイルのタイプを推定する。

・`diff`コマンドは行単位で2つのファイルの比較をする。
例えばtest1ファイルが

```
test,
for test,
This is a test.
```
という中身で、test2ファイルが

```
test,
For test,
This is a text.
```
という中身の時に`diff test1 test2`とすると

```
2,3c2,3
< for test,
< This is a test.
\ No newline at end of file
---
> For test,
> This is a text.
\ No newline at end of file
```

と出力される。最初の行の`2,3c2,3`は第一引数のtest1の2行目と3行目が変更された（c:change）ことを示している。`diff`コマンドは**第一引数のファイルから第二引数のファイルを作るための操作**で表現される。

・ファイルの行数を知りたい時は`wc`コマンド(word count)を使う。表示されるのは、「ファイルの行数」「単語数」「文字数」である。

・画面出力の保存として`script`コマンドがある。これを実行するとbashが新たに起動されて、`exit`する(もしくは`Ctrl-D`を押す)までの画面の出力（制御記号付き）を`typescript`というファイルに書き込む。最初からファイル名を指定して`script filename`というコマンドでも良い。

# ファイルとディレクトリについて

ファイルの名前とファイルの内容を入れる入れ物は別である。後者を**ファイルの実体**という。ファイルの実体には**i-ノード番号**という識別番号がついている。これは`ls -i`で見ることができる。コマンドは基本的に「ファイル名」⇨「ファイルの実体（i-ノード番号）」⇨「ファイルの内容」という順番に辿られる。

### ハードリンクとシンボリックリンク

ファイル名には二つある。
1. ハードリンク
2. シンボリックリンク

である。**ハードリンク**はファイルの本名で、どんなファイルも必ず1つは持っており、全てのハードリンクがなくなるとファイルの実体が消される。ハードリンクの数は`ls -l`で確認できる（モードの次の数字がハードリンクの数を表す）。`ln oldname newname`のように`ln`コマンドでハードリンクを増やすことができる。これで片方のファイルを変更すると、もう片方のファイルも書き変わることになる。また、新たに追加したハードリンクを以前からあったファイル名（ハードリンク）と区別することはできない。

**シンボリックリンク**はただのファイルの別名である。シンボリックリンクを増やすには、`ln -s oldname newname`というコマンドを使う。

これらの違いはrmコマンドを使ったときに現れる。`file1`にハードリンクを新しく貼って`file2`を作ったとき、`rm file1`してもファイルの実態は`file2`として残っている。しかし、`file1`にシンボリックリンクを貼って`file3`を作ったとき、`rm file1`とすると`file3`という名前ではそのファイルにアクセスできない。シンボリックリンクにはリンク先のパス名が記録されているだけなので、リンク先が消えたらアクセスはできなくなる。

ディレクトリは、そのディレクトリの中にあるファイルとディレクトリの内容の名前の一覧を情報として持つファイルとみることができる。この見方のディレクトリを**ディレクトリファイル**という。ファイルの場合、ハードリンクの数は最初は1であるが、ディレクトリの場合は2である。なぜなら、そのディレクトリの中にそのディレクトリを表す`.`があるため。ディレクトリの木構造が崩れるようなループが生じてしまうと、カーネルの中でディレクトリの探索が無限ループとなり、システムが落ちてしまうことを防ぐため、ディレクトリにはハードリンクが貼れないようになっている。ただしシンボリックリンクはディレクトリにも貼ることができる。

### ディレクトリに関する小技

・ファイルを削除禁止する方法
直接削除禁止にはできないが、そのファイルが格納されているディレクトリを書き込み禁止にすることで、そのファイル名を削除した結果をディレクトリファイルに書き込めないから削除できないという方法がある。例えば`dir1`に入っている`file1`について、`chmod a-w dir1`とすることで、`rm dir1/file1`ができなくなる。そのディレクトリ内でファイルの作成もできなくなるが、`file1`の変更はできる。

・ファイル名で記号を使う
`-`から始まるファイル名について、これはファイル名やディレクトリ名に使っても良い記号だが、UNIXの多くのコマンドラインで`-`をコマンドのオプションの指定と解釈するために、これをファイル名に下手に使うと問題が生じやすい。先頭が`-`じゃなければ良いので、絶対パスにするとか、`.`から始まる相対ファイル名にするなどで解決可能。(`''`で括るではだめ)

### マスクとモード

ファイルを新たにつくった時に作成されたファイルのモードは
1. ファイルを作るプログラムの中で指定したモード
2. マスク

の二つから決まる。具体的には１から２を落とす（「落とす」とは、1になっているビットを0にすること）。

**モード**とはファイルの型と許可されたアクセス方法を制御するビット列(16ビット)のこと。
モードの上位4ビットは**ファイルの型**を表す。`ls -l`で左端の1文字。-なら普通のファイル、dならディレクトリなど。
第11ビットは**set-uidビット**(User-IDビット)といい、このファイルの所有者のユーザIDが実行プロセスの実行ユーザIDにセットされる(つまりコマンドを実行したユーザの権限ではなく、ファイルの所有者の権限で実行される)。
第10ビットは**set-gidビット**(Group-IDビット)であり、set-uidビットのグループ版。つまりこのプログラムを実行する時に、このファイルのグループIDがプロセスの実行グループにセットされる。
第9ビットは**stickyビット**で、このビットが立っているファイルは`ls -l`で右端にtと表示される。ディレクトリにこのビットが立っている時は、ファイルの消去や名前変更を許されるのがその所有者だけに限定される。実行可能ファイルに立っている時はプロセスが終了した時にテキストのスワップイメージを保存して次に同じコマンドが実行される時の速度が速くなるが、仮想記憶が導入されてからはこの機能の効果は薄れて、この機能が無効になっているUNIXもある。
モードの下位9ビットは許可されたアクセス方法(パーミッション)を表す。(例えば`rw-r--r--`とか)

ファイルのモードを変えるのに記号を使った例を先に紹介した(`chmod a+x file1`など)が、`chmod 644 file1`のように数字で変えるという方法もある。

マスクを設定するには`umask`コマンドを使う。
`umask 0`を実行して、マスクを0にした時にfileを作成するとモードは`rw-rw-rw-`であるが、マスクを022にしてfileを作成すると`rw-r--r--`となる(下二つのwを落とす)。これは設定ファイル(.bash_profileとか)に書いておくこともある。

### ファイル属性の変更

・所有者属性の変更
`chown owner file1 file2 ... filen`
file1からfilenまでownerの所有となる。基本的にはスーパーユーザが使える。

・グループ属性の変更
`chgrp group file1 file2 ... filen`
file1からfilenまでgroupの所有となる。

・ファイルの時刻属性の変更
ファイルには三つの時刻属性がある。
1. 最終アクセス時刻
2. 最終更新時刻
3. 最終変更時刻

である。2の最終更新時刻は**ファイルの内容**の変更時刻で、3の最終変更時刻は**属性**の変更時刻を指す。
`touch`コマンドでは最終アクセス時刻や最終更新時刻を好きな時間に変更できるが、3は現在の時刻に変わる。例えば
`touch -t 201909080706 file`
ならfileの最終更新時刻は2019年9月8日7時6分となる。

### デバイスファイル

ハードウェアのデバイスを表すファイルを**デバイスファイル**という。通常`/dev`の下にある。デバイスファイルには**ブロック型**と**文字型**の2種類がある。前者はディスク装置を操作するためのデバイスファイルで、後者はそれ以外を扱うためのファイルである。

デバイスファイルは、そのファイル名を使って操作するデバイスと、メジャー番号とマイナー番号で関連づけられている。メジャー番号は、RAMディスクなら1番のように、デバイスの種類ごとに決められている。マイナー番号は、同じディスクのパーティションを区別したりするのに使う。

### ソケット

**ソケット**はプロセス間通信の終端点である。プロセス間通信にはパイプやTCP/IPなど色々な方法があるが、その中に数えられるUNIXドメインのソケット(同一コンピュータの内容で閉じたプロセス間通信で使うソケット)はファイルとして見ることができる。

### プロセスファイル

`/proc`というディレクトリの下にプロセスの状態がファイルとして見れるようになっているシステムが存在する(MacOSは違うけど)。例えばLinux全般や、FreeBSDなど。このファイルを読むことで、プロセスのメモリの状態が得られるようになっている。

### マウントとアンマウント

ディスク上に作られたファイルシステムは、最初は単に一続きの大きなデータとしてしか扱われない。この状態からUNIXのカーネルにファイルシステムの木があることを認識させることを**マウントする**という。例えば`mount`コマンドを使って`mount /dev/sd0g /usr`とすると、`/dev/sd0g`で示されたディスクパーティションにあるファイルシステムがUNIXに認識される。これ以降に`/usr`にアクセスすると、`/dev/sd0g`にあるファイルシステムのルートにアクセスできる。この場合`/usr`を`/dev/sd0g`の**マウントポイント**という。

### NFSマウント

**NFS**(Network File System)とは、Sunが開発したネットワークファイルシステムである。ネットワークファイルシステムとは、ネットワークで繋がった別のコンピュータにあるファイルをあたかも自分自身が持っているディスクにあるファイルのように扱うことができる仕掛けのこと。

どんなファイルシステムがマウントされているかは、一般ユーザでも見ることができる。`mount`と入力すればよい。

### ディスクの残り容量

ファイルシステムのディスクの容量を調べるには`df`コマンド(disk free space)を使う。
macOSで`df`コマンドを打つと、Filesystemにはディスクパーティションに対応したデバイスファイルの名前、Mounted onにはどこにマウントされているかを示すマウントポイントなどが表示される。
ファイルシステムという木全体のディスク容量ではなく、あるディレクトリ以下という部分木のディスク容量を調べるには`du`コマンド(disk usage)を使う。`/`で`du`コマンドを使うと、全てのファイルのサイズを表示しようとするので時間がかかる。

### ファイルシステムのiノード番号

先ほど紹介したiノード番号は、ファイルシステムごとに割り振られる。そのため、ファイルシステムが違えば同じiノード番号が存在することになる。
<img width="778" alt="スクリーンショット 2020-03-31 23.32.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395943/60edf0a9-d178-88dd-4028-31ec2c7dfd16.png">
例えばラズパイでは`/boot`と`/proc`と`/sys`は同じiノード番号として1が割り振られている。UNIXでは名前が違っていても、同じファイルの実体を示していることがある。正確にファイルが同じかどうかを調べるにはiノード番号だけでなく、ファイルシステムまで合わせて比較する必要がある。

### ルートファイルシステム

`/`によくあるディレクトリとその内容について簡単にまとめる。

| ディレクトリ名           | 意味                                             |
|:----------------------|:-------------------------------------------------|
| `/bin`(binary)        |`sh`, `ls`, `mv`, `cp`など基本的なコマンドが置かれる。システムにトラブルがあるとルートファイルシステムしか使えない時があるから、そのような時でも必要なコマンド。 |
| `/sbin`(system binary)|システム管理用のバイナリ（実行可能な機械語のことをバイナリという）で、特にブート時に必要なもの。|
| `/etc`(et cetera)     | 重要なシステム管理用のコマンドやデータファイルがある。`ssh`とか`mount`とか。            |
| `/root`               | BSD系のUNIXやLinuxでは、rootのホームディレクトリとしてここを使う。                     |
| `/tmp`(temporary)     | 一時的なファイルを置くディレクトリ。                      |
| `/var`                | 起動時には不要で、実行時に変化するもの、複数のホストで共有できないものを置く。              |
| `/usr`                | ユーザシステムファイルには一般的なコマンドの実行形式やライブラリを置く。昔は個々のユーザのホームディレクトリなどが置かれていたからこの名前。User System Resourceの略という説もあるけど、どうやら嘘らしい。今はユーザのホームディレクトリとかは`/home`とかの他の場所に置くことが多くなったけども、引き続き使われているとのこと。`/bin`ほど重要なコマンドではないけど、UNIXで標準的なコマンドは`/usr/bin`に置かれていることが多い。                       |
| `/opt`(optional)      | 後から追加するソフトウェアパッケージを置くために使われる。     |
| `/home`               | ユーザのホームディレクトリ。MacOSでは`/Users`の下にユーザーのホームディレクトリが置かれる。Linuxでは`/home`の下にユーザのホームディレクトリがあることが多い。 |



# プロセスについて

### プロセスの資源と属性

プロセスには**資源**と**属性**がオペレーティングシステムによって割り当てられる。

プロセスが持つ**資源**には以下のようなものがある。

1. メモリ
2. スワップ領域（主記憶が不足した場合にプロセスのメモリイメージを格納する二次記憶上の領域で、通常はハードディスク）
3. レジスタセット
4. 開いたファイル（UNIXではプロセスごとにファイルを開いて、データをファイルから読んだりファイルに書き出したりしている。プロセスはその開いたファイルの表を持つ）
5. 制御端末（プロセスごとにキーボードからのシグナルを受けとる端末が1つ定められており、この端末のこと）
6. カレントワーキングディレクトリ
7. ルートディレクトリ

プロセスが持つ**属性**には以下のようなものがある。
1. プロセスID（PID）
2. 親プロセスのプロセスID（PPID、プロセスがある命令を実行すると新しくプロセスができる。これ以外の方法ではプロセスはできない。つまりプロセスにはそのプロセスの生みの親がある。これを親プロセスという）
3. ユーザID（UID）
4. グループID（GID）
5. マスク
6. 状態（RとかDとかSとかZとか、`ps`コマンドのSTATに書いてある）
7. 優先順位
8. 制限資源量（CPU時間とか同時に生成できるプロセス数とか）

他にもTTY（そのプロセスがどの端末と結びついているかを示す。TTなら省略形、TTYならフルネームで示す）とか。

### シグナル

UNIXではプロセスに**シグナル**を送ることができる。プロセスはシグナルを受け取るとその時に実行中の機械語命令を中断してシグナルに対して設定された動作を実行する。シグナルには種類がある。INTなら受け取ったプロセスを終了する（interrupt）、TSTPならプロセスを殺す（terminal stop）、KILLならプロセスを殺す（TERMより強力）、STOPならプロセスを停止するなど。ここの話はBashプログラミングの章でも述べる。

### ジョブ

UNIXの**ジョブ**とは、一連の仕事をしているプロセスの集合のこと。例えば`ls -l | less`というコマンドなら、このパイプで繋がった二つのプロセスからなる集合が一つのジョブとなる。このコマンドを`Ctrl-Z`でどちらのプロセスも止めることができ、ジョブを止めたり殺したり再開したりすることを**ジョブ制御**という。

キーボードの入力を伝えるジョブをフォアグラウンドジョブ、それ以外のジョブをバックグラウンドジョブという。ジョブ制御の1つの側面は、**端末入出力の交通整理**である。例えば`cat & cat`というコマンドだと、前の`cat`はバックグラウンドジョブとして、後ろの`cat`はフォアグラウンドジョブとして実行される。ジョブの停止（`Ctrl-Z`）や終了（`Ctrl-C`）などはプロセスとほぼ同じ。ジョブをフォアグランドで実行するには`fg`コマンドを、ジョブをバックグラウンドで実行するにはコマンドの最後に`&`を付ける。実行中のジョブを見るには`jobs`コマンドを使う。ジョブの指定には`%`を用いる。例えば`%n`でジョブ番号nのジョブを表す。

なお、シェル自身は`Ctrl-Z`では止まらない。シェル自身を止めるには`suspend`コマンドを使う。ログインシェルではエラーが出て`suspend`は使えないが、`kill -STOP $$`とすることでシェルを無理やり止めることもできる。なお、これをログインシェルでやった場合は、同じホストに開いた別のシェルから`kill -CONT pid`(pidは止めたシェルのプロセスID)として、再度シェルを再開させる必要がある。

### インタプリタとプロセス

シェルスクリプトやperlスクリプトなどはインタプリタにより実行されるプログラム。このような実行ではプロセスはインタプリタの実行形式から作られ、インタプリタに与えるプログラムはそのプロセスが読み込む単なるデータと見なされる。一般のインタプリタの形式は以下。

```
#!interpreter arg-1 arg-2 arg-3
(以下プログラム)
```

ここで`interpreter`はインタプリタの実行形式の絶対パス名。

シェルスクリプトの最初につける`#!/bin/bash`とかは、インタプリタとしてそのシェルを起動しなさいという意味。シェバンとかシバン(Shebang)という。ただし`#!`の行を解釈するのはUNIXとかのカーネルなのでシェル変数や環境変数、エイリアスは使うことができない。

### プロセスの優先順位の制御

`ps l`のPRIが優先順位で、NIがnice値。このnice値は-20から19の数で、デフォルトでは0。この数字を大きくすると優先順位を表す数字が大きくなり、結果的に優先度が下がる。nice値を大きくするには`nice`コマンドを使う。

### プロセスとシステムコール

プロセスが動いている間は基本的にはメモリ中の機械語のプログラムに従ってメモリの中のデータが読み書きされていく。ファイルからデータを読み込んだり端末に文字を出力するためには、プロセスはオペレーティングシステムの機能を呼び出すことになる。これを**システムコール**という。プロセスが実行していく過程でどのようにシステムコールを発行していったのかの足跡をプロセスの**トレース**という。Linuxでは`strace`コマンドで見ることができる。例えば`echo hoge`というコマンドのトレースを表示するには`starce echo hoge`とする。

BSD系のMacは`ktrace`コマンドでトレースを表示して、`kdump`で表示する。

# アクセス制御

### ユーザーとグループ

**ユーザ**は、UNIXの外の世界では、コンピュータを使う人間のこと。UNIXの内部では**ユーザ名**という文字列、またはそれとほぼ1対1に対応した16ビットの整数である**ユーザーID**で表す。**グループ**とは、UNIXの外の世界では、コンピュータを扱う人間の集合のこと。UNIXの内部ではユーザと同様に**グループ名**という文字列、またはそれとほぼ1体1に対応した16ビットの整数である**グループID**で表す。ただし、一人のユーザが複数のグループに属するということがある。
全てのファイルやプロセスはあるユーザの所有物で、その属性にユーザID（UID）を持たせることで実現している。またユーザIDと同様に、ファイルとプロセスは属性としてグループIDも持っている。プロセスは複数のグループIDを持っているが、ファイルは一つのグループIDしか持っていない。
プロセスの所有者を見るには`whoami`コマンドを使う。そうするとそのシェルプロセスの所有者のユーザIDがわかる。またシェルプロセスが属しているグループのグループ名を表示させるには`groups`コマンドを使う。`id`というコマンドでも良い。
ユーザ名とユーザIDの対応づけはパスワードファイル`/etc/passwd`に記述されている。グループ名とグループIDの対応づけは`/etc/group`に記述されている。

### アクセス制御

**アクセス制御**とは、あるプロセスがファイルや他のプロセスに対して許されている操作だけを実行させること。ファイルなら内容の読み出しや書き込み、実行、属性の読み出し、変更ができるかを調べ、プロセスならシグナルを送れるかどうかを調べる。「ファイルの内容のアクセス制御」に関して、UNIXでは3段階で行う。
1. ファイルのユーザIDがプロセスのユーザIDと同じ場合
2. ファイルのグループIDがプロセスのグループIDのリストのどれかと同じ場合
3. 上記以外の場合

「ファイルの属性のアクセス制御」については2種類あり、
1. ファイルのユーザIDがプロセスのユーザIDと同じ場合
2. 上記以外の場合

である。前者は全てのファイルの属性を読み出すことができてモードやグループ、時刻とかを変更できる（`chmod`, `chgrp`, `touch`）が、後者は読み出すのみ。

「プロセスのアクセス制御」は2段階で行う。
1. 操作対象のプロセスが操作するプロセスのユーザIDと一致する場合
2. 上記以外の場合

プロセスの操作としては、シグナルを送ることができるかどうかや、デバッガでデバッグすることができるか、トレースを調べることができるか、などがある。それらの操作は前者の場合は許されるが、そうでない場合は許されない。

### set-uidとset-gidについて

プロセスには属性としてユーザーIDがある。これは、例えばファイルを開くときにファイルの所有者属性と比べられ、シグナルを送るときにそのシグナルを受けるプロセスのユーザIDと比べられる。プロセスのユーザID属性は、通常親プロセスから引き継ぐ。

**set-uid**(set user id)とは、そのコマンドを実行するときに、そのコマンドの実行形式を保存しているファイルのユーザ属性を、プロセスの属性であるユーザIDにセットして、そのユーザIDの権限でプロセスを実行する仕組みである。グループIDでもset-uidと類似の仕組みがあり、それは**set-gid**(set group id)と呼ばれる。

set-uidは主にスーパーユーザの権限でコマンドを実行する場合に利用される。set-uidのコマンドはls -lで見ると、ユーザによる実行可能を表すxが表示される位置にsと表示される。set-gidのコマンドはグループによる実行可能を表すxが表示される位置にsと表示される。
<img width="513" alt="スクリーンショット 2020-04-02 2.55.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395943/b74e95d7-6ff6-be69-cad2-d5d261ddff40.png">

その他のコマンドは`ls -l /bin/ | egrep '^...s'`などで探せる。なお、set-uid、set-gidのコマンドを作るには`chmod u+s file`や`chmod g+s file`など、`chmod`コマンドを使って作る。

### 実効ユーザIDと実ユーザID

ユーザIDには**実効ユーザID**と**実ユーザID**の2種類がある。同様にグループIDにも**実効グループID**と**実グループID**の2種類がある。アクセス制御（ファイルの読み出し書き出し、シグナルの送出など）に使われるのは実効ユーザID（実効グループID）である。実ユーザIDは、set-uidのプログラムを実行しても変わらない。実効ユーザIDが変わってしまっても、元のユーザIDは実ユーザIDを見ることで調べることができる。

# インターネット

「インターネット」とは、元々ネットワークのネットワーク、つまりいくつかのネットワークをルータという機器を使って相互接続したもの。ここでいうネットワークとは、それぞれ独立した方針で運営されているコンピュータネットワークのこと。組織内のLANやパソコン通信は、「インターネット」ではないネットワークに分類される。世界最大の「インターネット」は、そのまま**インターネット**と呼ばれている。この固有名詞としてのインターネットは次のような意味を含んでいる。

1. TCP/IPという共通の通信プロトコルに基づくネットワークのネットワーク
2. このネットワークを活用し発展させる人々のコミュニティ
3. このネットワークを通じて到達できる資源の集積

**プロトコル**とは、通信を行う機器、コンピュータ、あるいはプログラムの間でどのような手順で通信するのかを定めた規則のこと。

インターネットの特徴5つ
1. 繋がっている機器はコンピュータ
2. ネットワークを流れるデータはコンピュータで扱える2進数
3. コンピュータにはIPアドレスと呼ばれる番号が振られている
4. どのコンピュータもどのコンピュータとも接続可能
5. 通信をするとき使う人はIPアドレスを指定するだけでよく、使う人は途中の通信を中継しているルータの存在を気にしなくて良い

インターネットでよく利用されるアプリケーション
1. 電子メール
2. ファイル転送（ftp, archie）
3. リモートログイン
4. WWW


### TCP/IPによるインターネットの仕組み

TCP/IPを用いた通信では、4つのプロトコルの層が使われることになる。TCP/IP自身は、TCP層とIP層という2つのプロトコルから成り立っている。ネットワーク通信では様々なプロトコルが決められ、全体として層をなしている。これを**プロトコルスタック**という。
<img width="567" alt="スクリーンショット 2020-04-02 12.53.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395943/1a612175-44cd-0d70-8204-fcbd33fe3f6c.png">

**IP（Internet Protocol ）** は信頼性がないデータグラム転送サービスを提供する通信プロトコル。データグラムは
1. データの送り手と受け手の間に結合、通信路が作られない
2. 複数回に分けて送り出したデータの順番が入れ替わる可能性がある
3. 送り出したデータが途中で失われることがある
の3つの特徴がある。データグラムは**パケット**とも言う。IPのデータグラムが配達される時に使われる番号が**IPアドレス**である。

**TCP（Transmission Control Protocol）**はIPの機能を利用して**信頼性のある**双方向のストリーム転送サービスを提供する通信プロトコル。ストリームは
1. データの送り手と受け手の間に**コネクション**が作られる
2. 複数回に分けて送り出したデータの順番が入れ替わることはないが、データの区切りは保存されない
3. 送り出したデータが相手に届くようにする（再送機能あり）

の3つの特徴がある。TCPで通信するためにはIPアドレスと**ポート番号**がいる。ポート番号は16ビットの整数で、よく使われるアプリケーションにはあらかじめどの番号を使うか決まっている。このすでに決められている番号のことを**well-kwownポート番号**という。

TCP層の上には**応用層**（アプリケーション層）が定義されている。この層では、電子メールの転送やファイル転送、リモートログイン、WWWといったTCP/IPを利用するプログラムの間の通信方法が定義されている。TCP/IPの上位に定義されているプロトコルとそのプロトコルで使われるポート番号の例を以下に示す。

| ポート番号 | プロトコルの名前                     | 目的             |
|:---------|:-----------------------------------|:----------------|
| 21       | FTP(File Transfer Protocol)        | ファイル転送      |
| 22       | SSH(Secure Shell)                  | リモートログイン   |
| 25       | SMTP(Simple Mail Transfer Protocol)| 電子メールの転送   |
| 80       | HTTP(HyperText Transfer Protocol)  | WWWのデータ転送   |
| 110      | POP3(Post Office Protocol ver3)    | 電子メールの受信   |
| 443      | HTTPS(HTTP over TLS/SSL)           | WWWのデータ転送   |

**物理層**では、IPのデータグラムを転送するために、様々な物理的な媒体が使われる。例えば**イーサネット**など。

**UDP（User Datagram Protocol）** もTCPと同じようにIP上に構築されたプロトコルで、IPと同様にデータグラム転送サービスを提供する。通信相手を識別するにはIPアドレスとポート番号が必要。トランスポートプロトコルの２大有名プロトコルとしてTCPとUDPがある。

ネットワークに接続されているコンピュータの中で、ネットワークに１箇所の出入り口（ネットワークインターフェイス）を持っているものは**ホスト**と呼ばれる。２箇所以上のネットワークインターフェイスを持っているコンピュータは**ルータ**と呼ばれている。ルータは**ゲートウェイ**と呼ばれることもある。なお、ゲートウェイは異なるプロトコルを使う通信を中継するという意味もある。

### 仮想回線

TCP/IPで、プロセス間に形成されたストリーム通信のことを、コンピュータ間に張られた物理的な回線と考え、仮想回線という。仮想回線は以下の手順で作られる。

1. サーバプロセスがポート番号を指定して、接続要求受付用ポートを作って待機する。このポートでは**データの送受信はできない**。
2. クライアントプロセスが通信用ポートを作る。サーバプロセスが動いているホストのIPアドレスと接続要求受付用ポート番号を使って、接続要求を行う。
3. 接続要求が受け付けられると、サーバプロセスは新たに通信用ポートを作る。これでお互いが通信用ポートで接続ができるようになる。

TCP/IPの通信路開設では、クライアントはサーバ側の接続要求受付用ポートのポート番号を事前に知っている必要がある（1番での話）。サーバ側は基本的には、アプリケーションごとに決まっているwell-knownポート番号を使う。クライアント側の通信用のポート番号は、OSにより空いている番号から自動で割り振られる。

### DNS(Domain Name System)

TCP/IPで通信するには、通信相手のIPアドレスとポート番号が必要になる。しかし、このIPアドレスとポート番号はコンピュータにとって扱いやすいものであるが、人間にとってはわかりにくい。そこで人間にとってわかりやすいアルファベットなどを使ったホスト名からIPアドレスに変換するサービスが生まれた。このサービスを**名前サービス**という。これを行うプロセスを**名前サーバ**と言い、「名前」から「名前を指している番号」に変換することを**名前解決**という。

インターネットで使われている名前サービスは、DNS(Domain Name System)という。DNSでは、膨大な数のホスト名を含む名前空うかんを階層的にドメイン（領域）に分割して管理する。

例えば「host1.is.u-ust.ac.jp」という名前を考える。このようにDNSで使われるホストの名前は.で区切られた文字列である。DNSで使われる名前はUNIXのファイルのパス名とは逆で、右から左に向かって解釈される。例えば上のホスト名をUNIXのパス名のように書くと「/jp/ac/u-ust/is/host1」のようになる。

このように根からの長い名前を完全ドメイン名(Full Qualified Domain Name)という。文脈によっては単にドメイン名といっただけでFQDNを意味することもあるし、ホスト名といっただけで最後の葉の部分（この例ではhost1）を指すこともある。

根の直下には、トップレベルドメイン（TLD）がある。TLDには、ISOが定めた2文字による国別コード(country code)を使う国別コード(ccTLD)と、国別コードを使わない汎用TLD(gTLD)がある。日本のccTLDは.jpであり、gTLDの例としては.comや.net、.eduなどがある。

名前サーバのクライアントとして名前解決する部分をリゾルバという。例えば「host1.is.u-ust.ac.jp」というホスト名のIPアドレスを探すことを考える。ローカルの名前サーバは、まずルートの名前サーバに問い合わせる。ルートの名前サーバは自分で知らないので、代わりにjpの名前サーバの名前とIPアドレスを返す。ローカルの名前サーバは、今度は、jpの名前サーバに問い合わせる。これも自分では知らないので、acの名前サーバのホスト名とIPアドレスを返す。こうしてさらにu-ust、isと検索が進み、最後にこのisの名前サーバが持っているhost1のIPアドレスが返されることになる。


### 電子メール

メールボックスはUNIXではファイルやディレクトリとして表現され、それらに直接アクセスすることでメールができる。しかし、ネットワークの別のコンピュータ上にあるメールボックスを扱う場合は、NFSを使って別のコンピュータ上にあるファイルを同一のコンピュータ上にあるものとして扱うようにするか、POPやIMAPというTCP/IP上に定義された通信プロトコルを使う必要がある。

### ftpとtelnet

file transfer protocolに由来しており、ftpで使われるプロトコルを大文字でFTPと書くことが一般的。小文字の時はそのプロトコルを使って実際に通信を行うコマンド（ソフトウェア）をさすことが多い。FTPでは認証のためのユーザ名やパスワード、転送データは暗号化されないため、今ではFTPの通信をSSL/TLSにより保護した**FTPS**や、SSHの仕組みを利用した**SFTP**などの代替プロトコルに置き換えられている。

`telnet`はリモートにログインするためのコマンド。これも認証を含め全て平文で送るので今はSSHが使われる。

### WWW

**WWW**(the World Wide Web)はハイパーメディアという仕組みによって作られている。**ハイパーメディア**とはマルチメディアが発展し、他の情報への参照（ポインタ、リンク、ハイパーリンクとも呼ばれる）を含むようになったもの。**マルチメディア**とは文字や数値といったデータに加えて、静止画像、動画、音声といったデータを統合的に扱うことができるもの。ハイパーメディアの特徴は、参照をたぐって、他の情報に簡単に移動することができるという点にある。データとしてテキストしか含まれていない場合は、**ハイパーテキスト**という。

文書に「ここは表題」といった文書の構造を示す目印をつけることを**マークアップする**という。マークアップのための目印を文書に埋め込むための人工言語をマークアップ言語という。HTML、LATEX、SGMLなどが代表的。軽量マークアップ言語（人間がシンプルなテキストエディタを使っての入力が容易になるように設計された簡潔な文法を持つマークアップ言語）の例としてMarkdownがある。QiitaもgithubもMarkdownを採用している。

HTMLでは他のデータの参照を実現するために **URL（Uniform Resource Locator）** という形式を用いる。一般的なURLの形は以下。

`http://www.u-ust.ac.jp/dir/index.html`

上の例でのURLの先頭の`http`はHTTP(HyperText Transfer Protocol)という通信プロトコルを表している。このプロトコルは、WWWのデータを保持しているプロセス（**WWWサーバ**、あるいは**HTTP Daemon**や**httpd**など）と、WWWを表示するプロセス（WWWクライアント、普通はWWWブラウザ）の間で通信によりデータをやりとりする形式を定めた約束。

`www.u-ust.ac.jp`はそのデータを持っているコンピュータの名前（ドメイン名）で、残りの`/dir/index.html`の部分が、そのコンピュータの中でのデータの名前（普通はファイルの名前が使われる）だが、最近はこの構造のURLも少なくなってきている。

### URLの一般的な形

`scheme:scheme-specific-part`

**scheme**（**スキーム**）とは、データを取ってくるための仕組み。schemeには通信プロトコル（http, ftpなど）が来ることが多いが、それ以外もある（file, mailtoなど）。インターネットで使われるURLだとscheme-specific-partの部分は//host/pathnameという形が多い。これは次の`//user:password@host:port/pathname`という一般形が省略されたもの。

他のURLの例としては`http://host1.is.u-ust.ac.jp/path?pattern`というものもある。これは多くの場合、`/path`に対応したプログラムが実行されて、`pattern`がその引数となる。

他にも`file:///dir1/file1`では、同一ホスト上の「/dir1/file1」という名前のファイルを示す。

### Proxyとキャッシュ

WWWサーバは基本的には直接WWWサーバに要求を送る。WWWサーバ（httpd）は普通はファイルからデータを読み出し、WWWブラウザに返す。しかし、設定によってはWWWブラウザは直接WWWサーバに要求を送らずに、WWWProxyサーバに要求を送ることがある。**プロキシ**とは代理の意味で、WWWブラウザに変わってWWWサーバと通信をするプロセスを表す。WWWProxyはWWWブラウザから受け取った要求をWWWサーバに送り、WWWサーバから送られてきた結果をWWWブラウザに返す。

WWWプロキシを使う目的は以下
1. キャッシング（caching）
一度アクセスした内容のページを自分のハードディスクに保存する。この保存されたものを**キャッシュ**（**cache**）という。同じページに対する要求が来た場合にはProxyはローカルのハードディスクにあるキャッシュを返す
2. ファイアーウォールを超えるため
セキュリティ確保のため、ファイアーウォールの内側のコンピュータは外のコンピュータに直接接続できないようになっていることがあるので、その中継のため
3. より高速な通信経路を選ぶため

なお、キャッシングは、ブラウザのメモリやブラウザが動いているホストのディスク（ファイル）に行われることもある。この場合、WWWブラウザはWWWサーバに要求を送る前に、まずメモリやファイルにキャッシュが保存されていないかをチェックし、あればそれを使うようになる。

### CGI
WWWサーバは、普通はファイルに保存されたHTMLデータやイメージデータを読み込み、WWWブラウザに返す。これに対して、**CGI**(Common Gateway Interface)では、ファイルが読み込まれる代わりにコマンドが実行され、その実行結果がブラウザに返される。ここでいうGatewayは、WWWで使われているHTTPというプロトコルへの入り口という意味。

### SSI(Server Side Include)
CGIではどのようなプログラムも実行することができるが、設定が少し複雑になる。これに対して**SSI**は、CGIよりも手軽にHTMLの途中に、他のファイルの内容や、プログラムの実行結果を埋め込むための仕組みである。


残りは[後編](https://qiita.com/minnsou/items/2f8173b08c0a3d5cfc48)に続きます。