# Literacy(ヅ新入生向け)
リテラシーIという1年生に受講する伝統的な授業の内容に沿ったものです。リテラシーとは、以下のような意味があります。
> リテラシー(英: literacy)とは、原義では「読解記述力」を指し、転じて現代では「( 何らかのカタチで表現されたものを)適切に理解・解釈・分析し、改めて記述・表現する」 という意味に使われるようになり(後述)、日本語の「識字率」と同じ意味で用いられている。
[wikipedia](https://ja.wikipedia.org/wiki/リテラシー)より
ごく簡単に一言で言うと、**コンピュータと仲良くなる**ためのイロハを学ぶ授業です。この授業は、いかなる分野に向かおうと必要であり、大学中で一番大事な授業と言っても過言ではありません。この資料では、授業の内容を噛み砕きつつ、重要な部分をピックアップしたつもりです。
## UnixというOSとUI
世の中には様々な形や特性をもったコンピュータがあります。「形」つまり、物理的な機械のことを**ハードウェア**と言います。ハードウェアだけでは、単なる鉄の箱と変わりありません。ハードウェア上では様々な計算処理を行います。計算処理を行うものを**ソフトウェア**と言います。
皆さんが普段身近で扱っているであろうハードウェアの一つにスマートフォンがあります。スマートフォンはコンピュータと人間が会話(操作)するには、タッチディスプレイやマイクを使用します。この機器を指して**UI**(ユーザインタフェース)と呼びます。また、スマートフォンには、様々なハードウェアがあるにも関わらず、実際の使用感が統一されているはずです。これは、*iOS*や*Android*と呼ばれるソフトウェアによるお陰です。特にこのソフトウェアはアプリ(アプリケーション)と比べて操作の基盤となるため**OS**(オペレーティング・システム)と分別されます。皆さんは普段OSについて意識しなくてもアプリケーションの使い勝手のみを気にするだけで済んでいましたが、これからは**アプリケーションを開発する側に回ります**。その為、OSの違いやOS自身についてしっかり理解を進める必要があります。

しかし、大学の授業や実際のプロの現場の(主にプログラミングのための)道具としてスマートフォンは適していません。大学では、ハードウェアとして本体に加えてディスプレイ・キーボード・マウスを利用します。
OSには、**Solaris**, **MacOS**を利用します。Solarisは、**Unix**(UNIX)という元々一つのOSが枝分かれしたものの一つです。UNIXは、WindowsやMac OSよりも古い歴史を持つOSです。ですが、Mac OSやLinux(LinuxもUnix同様、様々に枝分かれしたOSの総称です。)などのOSに様々な影響を与え、今日ではパソコン・サーバ・スマートフォン・ゲーム機・組み込み機械など本当に様々な機器でその考えが浸透しています。
Unixとスマートフォンなどの機器との大きな違いはなんでしょうか? スマートフォンでは、タッチや音声などの直感的な操作に対して、画面の変化や音声が機器の反応として返ってきました。Unixでは、そのような音声やグラフィカルな表現を使って操作することもできます。しかし、キーボードで打ち込まれた文字に対して、ディスプレイに文字で返すようなインターフェースが重視されます。これをCUI(キャラクタユーザインタフェース)やCLI(コマンドラインインターフェース)と呼びます。

### ポイント
- コンピュータ・スマートフォンなどの物理機器を**ハードウェア**・その上で動く計算処理を行うものを**ソフトウェア**と呼ぶ。
- 様々なハードウェア機器の違いを吸収するソフトウェアのことをオペレーティングシステム(OS)と呼ぶ。
- UNIX(Solaris)は、キーボードと文字を主に利用するCUI(キャラクタユーザインターフェース)を使い操作をおこなう。
## ターミナル・コマンド
文字でコンピュータとやりとりするには、**ターミナル**(端末)または**コンソール**と呼ばれるソフトウェアを起動します(ターミナルに行き着くまでのやり方はオリエンテーション・授業等で)。ターミナルはコンピュータと文字で対話するため**対話型インターフェース**と呼ばれたりします。しかし、本当に自由に対話するわけではありません。あらかじめ決められたプログラムを使い命令をします。この命令の事を**コマンド**と言います。ターミナルは、コマンドに対して結果を文字列で表示することがあります(命令を無言で実行するコマンドも多く存在します)。この結果の文字列のことを**標準出力**と言います。
資料ではコマンドと標準出力の違いをわかりやすくするために、以下のルールで記述していきます。また、**コマンドは英文章の省略形であることが多い**です。例えばファイルを並べて表示するコマンドは```ls```ですが、これは**L**i**S**t filesの略になっています。省略されていない形で覚えることでコマンドとその意味を覚えることができるので積極的に覚えてみましょう。この資料では手助けとして、なるべく省略しない形も併記していきます。
```shell
# $(ドル)の後にコマンドが続きます。$は打ちません。
$ コマンド [オプション] [引数] # シャープ(#)の右側はコメント(説明文)
標準出力
```
オプションは、 ハイフン```-``` が、先頭に付き、引数はハイフンが付きません。オプションも引数も無いコマンドやどちらか片方、または両方ある場合もあります。引数やオプションが複数個ある場合もあります。
試しにファイルやディレクトリを表示するコマンド```ls```(LiSt files)を試してみましょう。
オプション・引数を付けないバージョン
```shell
$ ls # ファイル・ディレクトリを出力するコマンド
# 人によってどのようなファイル・ディレクトリが表示されるかは異なります。
App Movies
Desktop Music
Documents Picture
Library Public
Mail ...
```
オプションを付けるバージョン
```shell
$ ls -l # Long(詳細)な情報を表示する
drwxr-xr-x 3 d8161105 grdd 4096 11月 14 2014 App/
drwx------ 2 d8161105 grdd 4096 12月 15 18:47 Desktop/
drwx------ 7 d8161105 grdd 4096 10月 2 2015 Documents/
drwx------ 2 d8161105 grdd 4096 10月 6 20:06 Downloads/
drwx------ 42 d8161105 grdd 4096 7月 17 2015 Library/
drwx------ 9 d8161105 grdd 4096 3月 28 2014 Mail/
...
```
引数を付けるバージョン
```shell
$ ls Downloads/
# 空の場合何も表示されない。
```
## manコマンド
Unixには、数多くのコマンドが用意されています。また、多くのコマンドには、詳細な使い方のマニュアルが用意されており、```man```(MANual)コマンドで参照することができます。これを**オンラインマニュアル**といいます。オンラインマニュアルを使って、次のようなことを調べることができます。
- コマンドの使い方
- 引数やオプションの指定方法
- オプションの意味
- コマンドの出力する内容
マニュアルは日本語が用意されている場合は日本語で表示されます。しかし、英語でのマニュアルが通常です。```q```を押すことでマニュアルを読み終わることができます。
```shell
# lsのオンラインマニュアルを表示
$ man ls
```
### ポイント
- **ターミナル**というアプリケーションを通じて文字を使いコンピュータに命令する
- 命令をコマンドと呼び。コマンドは引数とオプションを受け取る
- コマンドの使い方は、manコマンドを利用する。
## ファイル

Unixでは、テキスト・画像・設定などのデータは、全て**ファイル**という単位で扱われます。ファイルにはファイル名が付けられます。日本語を扱うこともできますが、使うソフトウェアによっては正しく認識されないケースがあります。基本的には、次のような文字だけをファイル名として用いるとよいでしょう。
- アルファベット
- 数字
- 記号(アンダーバー```_```, ハイフン```-```, ドット```.```)
Windowsでは「.txt」「.doc」のような拡張子によってアプリケーションと関連付けられますが、Unix自体には拡張子の概念はありません。ただ、利用者がどのようなファイルかわかりやすくなることや、ファイルを扱うアプリケーションが拡張子によって判別するケースが多いため一般的には拡張子を付けたほうがよいでしょう。
また、Unixでは、ドット```.```で始まる名前のファイルは**隠しファイル**として扱われ、通常の操作では表示されないようになっています。隠しファイルは、主にユーザの環境やアプリケーションの設定ファイルとして使われます。結果として、以下のようなファイル名が適切です。
```
file text-file2 text_file.txt .editor.conf
```
### ファイルの種類
Unixのファイルは、次の4種類に大別できます。
- 通常ファイル
- ディレクトリ
- リンクファイル
- 特殊ファイル
#### ○ 通常ファイル
データやプログラムが格納されたファイルを通常ファイルと呼びます。通常ファイルは、テキスト情報が格納され、人間の読むことができるテキストファイルと、データやプログラムが格納され、人間が見ると意味不明なバイナリファイル(世の中にはこれを読んでしまう人もいます)とに分類できます。
#### ○ ディレクトリ
いわゆるフォルダに相当するものがディレクトリです。ディレクトリも特殊なファイルの形式です。詳しくは次節で解説します。
#### ○ リンクファイル
ファイル名とファイルの実体(内容)を紐付けることをリンクと言います。リンクファイルのは、**シンボリックリンク**と**ハードリンク**があります。とても重要な概念ですが、残念ながら本資料やリテラシーの授業では取り上げられないと思います(余力があれば追記します)。各人調べて見るか、せめてキーワードだけでも記憶していただけるとよいと思います。
#### ○ 特殊ファイル
Unixでは、あらゆるデバイスをファイルとして抽象化して扱うようにしています。たとえば、ハードウェアを抽象化したデバイスファイルがあります。プリンタに対応するデバイスファイルにデータを書き込むとプリンタから出力されるなど、ファイルを通してデバイスを扱えるようにするのがデバイスファイルです。デバイスファイル以外にもそのような特殊ファイルがいくつか存在します。
コマンドの使い方で紹介した```ls -l```ではファイルの詳細情報を見ることができます。左から順番に、ファイルモード・リンク数・ファイルの所有者・ファイルの所有グループ・ファイルのサイズ・最終更新日時・ファイル名となっています。
```shell
$ ls -l
drwxr-xr-x 3 d8161105 grdd 4096 11月 14 2014 App/
```
ファイルモードの一番左の文字がファイルの種類を表しています。
|文字 | 説明 |
|:---|:-----|
| - | 通常ファイル |
| d | ディレクトリ|
| l | リンクファイル |
| c | 特殊ファイル(キャラクタデバイスファイル) |
| b | 特殊ファイル(ブロックデバイスファイル) |
その他の項目については、後で扱います。
### 作成
さっそくファイルを作ってみましょう。もっとも単純にファイルを作るコマンドは、```touch```コマンドです。touchはタイムスタンプ(ファイルの作成日時)を更新するコマンドです。
```shell
$ touch file
// 特に反応はありません。
```
ファイルが出来たことを確認するために、```ls```を使用してみましょう。再びtouchを実行してタイムスタンプが変動していることを確かめてみましょう。
```shell
$ ls -l file
# ファイルを作った時間が確認できるはずです。
# ああ! 僕が資料を作ってる時期もバレてしまう!
-rw-r--r-- 1 abab staff 0B 3 11 11:58 file
```
次にファイルの中身を表示するコマンド```cat```(ConcATenate)を実行してみましょう。touchはタイムスタンプを更新するだけのコマンドなので、中身が表示されません。悲しいですね。
```shell
$ cat file
# 何も表示されない。
```
ファイルの中身を追記する方法は様々ありますが、引数を標準出力をする(やまびこ)コマンド```echo```を利用してみます。
```shell
# 普通に使うと引数(hello)が表示される。
$ echo hello
hello
# 標準出力をファイルに流し込むredirect(リダイレクト)という仕組みを使う。
# 詳しい説明は後述する。
$ echo hello > file
$ cat file
hello
```
### 削除
無事中身があるファイルが作成出来ました。今回作ったファイルは意味のないゴミなので、溜まってしまうと意味のあるファイルが探しにくくなってしまいます。削除してみましょう。削除には```rm```(ReMove)コマンドを使います。
```shell
$ rm file
# 成功した場合、特に反応はありません。
```
ここまで、しっかり資料通りにコマンドを打ち込んで来た方は、トントン拍子だったと思います。しかし我々は人間です。間違いを犯すこともあるでしょう。間違ったコマンドを実行した場合は、エラーが表示されます。英語ですが、しっかり読めば意味はわかりやすい英語です。わざと存在しないファイルを消そうとしてみましょう。
```shell
$ rm hogehogehoge
# そんなファイルやディレクトリはないよ!消せないよ! と書いてある。
rm: hogehogehoge: No such file or directory
```
### リネーム
課題のファイルやディレクトリを作成した! しかし、名前を間違ってしまった・・・作り直そう。待ってください! ちゃんと名前を変えるコマンドも用意されています。```mv```(MoVe)コマンドです。本来、別なディレクトリに移動をするためのコマンドですが、その場でファイルを移動するということは、名前を変えるということとイコールになります。
```shell
# 一旦ファイルを作成
$ echo hello > file
$ ls file
file
# hello -> hello.txt という名前にリネーム
$ mv file hello.txt
$ ls
# fileが消えて、hello.txtがあることを確認。
hello.txt
# 中身もfileと同じ。
$ cat hello.txt
hello
# 後片付け
$ rm hello.txt
```
### コピー
作成・削除・リネームと来たらコピーですね。同じ内容の別名のファイルを作り出すこともできます。```cp```(CoPy)コマンドを使いましょう。
```shell
$ echo hello > file
# fileと同じ内容のfile-copyを作成
$ cp file file-copy
# どちらのファイルもある
$ ls
file file-copy
# catは、実はファイルの内容をくっつける(concatenate)コマンドです。
# 同じ内容であることがわかりますね?
$ cat file file-copy
hello
hello
# 後片付け
$ rm file file-copy
```
### ポイント
- Unixで扱われるデータはファイルという単位で扱われる
- ファイルには名前が付いておりアルファベット・数字・記号から成る
- 表示・作成・移動・削除・コピーをするためのコマンドが用意されており、それらを使いファイルを管理する
## ディレクトリ
ファイルをまとめる入れ物のことを、WindowsやMac OSではフォルダといいますが、Unixでは**ディレクトリ**といいます。ディレクトリの中にディレクトリを作成することもできます(入れ子関係)。ディレクトリ内のディレクトリは**サブディレクトリ**と呼ばれます。このように、ファイルやディレクトリは階層構造で管理されます。

### パス
たとえば、*sxxxx*ディレクトリ内に*texts*というディレクトリがあるとき、sxxxxディレクトリから見た*texts*ディレクトリのことを```sxxxx/texts```のように```/```で区切って表します。*texts*ディレクトリに*memo.txt*というファイルがあれば、そのファイルは*sxxxx*ディレクトリから見て```texts/memo.txt```のように表します。このような表記を**path**(パス)といいます。
Unixでは、ディレクトリはツリー状の階層構造になっています(ディレクトリツリー)。その頂点となるディレクトリ、すなわちすべてのディレクトリを格納しているトップディレクトリのことを**ルートディレクトリ**といいます。ルートディレクトリは、```/```で表します。

### 絶対パスと相対パス
ファイルやディレクトリの場所を表すパスには、絶対パスと総体パスがあります。絶対パスはルートディレクトリを基点として表す方法です。相対パスは、現在作業しているディレクトリ(**カレントディレクトリ**)を基点として表す方法です。
#### 絶対パス
絶対パス(フルパス)は、ルートディレクトリを基点としてファイルやディレクトリを表す方法で、ディレクトリツリー内のファイルやディレクトリを**一意に特定できます**。

#### 相対パス
CUI環境(ターミナル)で、ユーザが作業を行っているディレクトリのことを**カレントディレクトリ**(カレント・ワーキング・ディレクトリ、作業ディレクトリ)といいます。たとえば、カレントディレクトリ```/home/student/sxxxx```であるとき、絶対パス```/home/student/sxxxx/data/texts/memo.txt```を相対パスで表すと```data/texts/memo.txt```になります。カレントディレクトリが```/home/student/sxxxx/data```であるなら、相対パスは```texts/memo.txt```となります。カレントディレクトリがどこかによって表記が異なるのが、絶対パスとの違いです。次の図では、```texts/memo.txt```で表せるファイルが2つあることがわかります。

#### 絶対パスと相対パスの使い分け
コマンドの引数としてファイルやディレクトリを指定する場合、絶対パスで指定しても相対パスで指定してもかまいません。たとえば、カレントディレクトリが```/home/student/sxxxx/data```であり、```/home/student/sxxxx/data/texts/memo.txt```のファイルの情報を確認したい場合、絶対パスを使うと次のようになります。
```shell
$ ls -l /home/student/sxxxx/data/texts/memo.txt
```
相対パスを使うと、次のようになります。
```shell
$ ls -l texts/memo.txt
```
相対パスを使うほうが簡潔ですね。カレントディレクトリと目的のファイルの場所との位置関係によって、絶対パスと相対パスを使わけるとよいでしょう。そのためには、カレントディレクトリがどこにあるかを意識しておきます。カレントディレクトリは、```pwd```(Print Working Directory)コマンドでいつでも確認できます。
```shell
$ pwd # カレントディレクトリ
/home/sxxxx/data
```
#### パスで扱う記号
パスを表すときに、以下のような記号を使うことができます。
|記号 | 説明 |
|:---|:-----|
| . | カレントディレクトリ(省略化) |
| .\. | 1つ上のディレクトリ |
| ~ | ホームディレクトリ |
下の図をもとにした例を挙げてみましょう。カレントディレクトリが```/home/student/sxxxx/data```であれば、```..```は```/home/student/sxxxx```を表します。```../..```なら```/home/student```です。```../program```なら```/home/student/sxxxx/program```です。```./list.txt```は```/home/student/sxxxx/data/list.txt```を表します。通常、カレントディレクトリを表す```.```は省略します。

**ホームディレクトリ**とは、ユーザごとに割り当てられるディレクトリで、一般的に```/home/ユーザ名```となります。本学の環境では、```/home/student/学籍番号```がホームディレクトリに割り当てられています。ログインすると、ユーザのカレントディレクトリはホームディレクトリになります。ホームディレクトリ内は、基本的にユーザの好きなように使ってかまいません。
### カレントディレクトリの移動
パスの概念を覚えたので、いろんなディレクトリに移動をしてみましょう。移動とはカレントディレクトリを変えていく事です。そのためのコマンドは、```cd```(Change current Directory)です。奥深くのディレクトリに移動してしまうと、*迷子*になってしまいます。そのため3つの方法でホームディレクトリへ戻ることができます。迷子になってしまったら以下のいずれかの方法で、ホームへ帰還しましょう。
```shell
$ cd
$ cd ~
$ cd $HOME
# カレントディレクトリがホームディレクトリに居ることを確認
$ pwd
/home/student/[学籍番号]
```
Linuxを含むUnix系OSでは、FHS(Filesystem Hierarchy Standard)という取り決めによって、ファイルの構造が緩やかに定まっている。以下に基本部分のディレクトリ構造を表にまとめます。```cd```, ```ls```, ```pwd```等のコマンドを利用してファイルやディレクトリを見て回りましょう。管理者権限アカウントではないため、権限エラーが発生してコマンドが上手く行かない場合もあります。権限については後ほど記述します。
|ディレクトリ | 説明 |
|:---|:-----|
|boot |カーネルなど起動に必要なファイル |
|bin |一般ユーザが利用できる基本コマンド |
|dev |デバイスファイル |
|etc |システム設定ファイルや起動スクリプトファイル |
|home |ユーザのホームディレクトリ |
|lib |ライブラリファイル|
|media|外付けHDDやUSBメモリ、DVDドライブなど|
|proc |システム情報|
|root |ルートユーザのホームディレクトリ|
|sbin |システム管理者が利用する基本コマンド|
|tmp |一時ファイル置き場|
|usr |プログラムやライブラリなど|
|var |ログファイルなど頻繁に更新されるファイル|
### 作成
ディレクトリを作るコマンドはファイルと違い一つしか用意されていません。```mkdir```コマンドです。
```shell
$ mkdir dir
// -Fは、ファイル・実行ファイル・ディレクトリ等を区別して表示してくれるオプション。
// ファイルの場合はそのまま、実行ファイルはアスタリスク(*)、ディレクトリの場合は最後にスラッシュ(/)を付けてくれます。
$ ls -F
dir/
// lオプションを付けると最初にディレクトリの```d```が表示される。
$ ls -l
drwxr-xr-x 2 abab staff 68B 3 11 13:43 dir/
```
実はあなたは既に何らかのディレクトリに「居ます」。あなたがどこにいるかを教えてくれるコマンドは、```pwd```(print working directory)コマンドです。
```shell
$ pwd
/home/student/sxxxxx // あなたの学籍番号
```
あなたの位置が確認できたところで、先程作ったディレクトリに移動してみましょう。移動には、```cd```(change directory)コマンドを使います。
```shell
$ cd dir
// 成功すれば何も表示されない。
$ pwd
/home/student/sxxxxx/dir
```
### 削除
削除のコマンドは、既に知っているコマンド```rm```をそのままは使えません。試してみましょう。
```shell
$ mkdir dir
$ rm dir
rm: dir: is a directory
```
ディレクトリを削除するには、rmdirというコマンドを使います。
```shell
$ rmdir dir
// 成功すれば何も表示されない。
```
しかし、rmdirコマンドは中にファイルがある場合、ディレクトリの削除に失敗します。
```shell
$ mkdir dir
// dirの中にfileという名前のファイルを作る。
$ echo foo > dir/file
$ cat dir/file
foo
// ディレクトリの中が空ではないので削除出来ません。
$ rmdir dir
rmdir: dir: Directory not empty
```
そのため、通常は```rm -r```を使います。
```shell
$ rm -r dir
// 成功すれば何も表示されない。
```
一体何が起こったのでしょうか? ```rm -r```の*r*は、recursive(再帰的な)という意味です。*i* オプションを付けると何が起きたか確認しながら削除を行うことができます。
※ ファイルやディレクトリの削除コマンドは、基本的に実行したら復元は出来ません。慎重に実行しましょう。
```shell
$ mkdir dir
$ echo foo > dir/file
$ rm -ri dir
// yは自分で打ちます。
examine files in directory dir? y
// fileを消して
remove dir/file? y
// ディレクトリの中身が空っぽになってからdirを消します。
remove dir? y
```
### 移動・リネーム
```mv```コマンドを覚えてるでしょうか。```mv ファイル名 ファイル名```のような場合は、リネームとして使えました。本来は、ファイルやディレクトリを移動(move)するためのコマンドです。間違った場所へファイルを作ってしまった場合などは、慌てずmvコマンドを使いましょう。
```shell
$ mkdir dir
$ echo foo > file
$ mv file dir
// 無事移動されていることを確認。
$ ls dir
file
// 後片付け
$ rm -r dir
```
mvの対象がディレクトリであれば、ディレクトリを移動することも可能です。もし、移動先のディレクトリが存在しない場合は、リネームとなります。自分で試して確認してみましょう。
### コピー
コピーは削除のときと同じです。```cp -r```です。rオプションを使ってコピーをしましょう。
```shell
$ mkdir dir
$ echo foo > dir/file
$ cp -r dir dir-cp
// 2つのディレクトリがあることを確認。
$ ls -F
dir/ dir-cp/
// ファイルも再帰的にコピーされている。
$ ls dir-cp
file
// 後片付け
$ rm -rf dir dir-cp
```
- ディレクトリはファイルやディレクトリ自身を格納して管理するための仕組みである
- ディレクトリはツリー構造となり、Unix系統のOSでは、トップディレクトリが**ルートディレクトリ**(/)となる
- ファイルやディレクトリを特定するには、パスというスラッシュで区切られた表記を用いる
- パスは絶対パス・相対パスという2種類の表記方法に加え、特殊な意味を持つ記号が用意されている
- ファイルと同様に作成・移動・削除・コピーをするためのコマンドが用意されており、それらを使いファイルを管理する
## ユーザとグループ
システムを利用するユーザは、あらかじめUnixシステムにユーザアカウントが登録されている必要があります。ユーザアカウントは、ユーザ名とパスワードが組み合わされ、それらを使って認証を行うことで、システムを利用できるようになります。その手続がログインです。
### ユーザ名とユーザID
ユーザには、固有のID番号が割り当てられています。これをユーザID(UID)といいます。Unix上では、ユーザの識別はUIDで行われます。UIDは**id**(IDentification)コマンドで確認することができます。ユーザ名を指定しなかった場合は、idコマンドを実行したユーザに関する情報が表示されます。ユーザ名を指定しなかった場合は、idコマンドを実行したユーザに関する情報が表示されます。
```shell
$ id
uid=UID(sxxxx) gid=1000(student) groups=1000(student)
# 隣の人の学籍番号でも聞いて入れてみよう
$ id syyyy
uid=UID(syyyy) gid=1000(student) groups=1000(student)
```
### ユーザの種類
Unixユーザには、以下の三種類があります。
- 管理者ユーザ(root)
- システムユーザ
- 一般ユーザ
```管理者ユーザ(root)```はシステム全体を制御する権限を持っています。**システムユーザ**は、システムプログラムやサーバソフトウェアを実行するために使われる為のユーザで、ログインには利用されません。**一般ユーザ**は、システムを利用するためのユーザで、ログインして作業をしたり、メールアカウントに利用したりします。学内環境では、学生がシステム管理者になることはありません。しかし、自分でサーバを構築して、サーバソフトウェアを制御したりすることがあると思いますが、今回の資料では割愛させていただきます。
### グループとは
ユーザをまとめて管理するための仕組みがグループです。グループを使うと*Aグループのみ閲覧できるファイル*、*Bグループのみ書き込みできるファイル*のように、グループ単位でアクセス権を管理できるため便利です。
Unixでは「すべてのユーザは何らかのグループに所属しなければならないと決められています。そのため、Unixを始めLinuxなどのディストリビューション(派生OS)ではユーザを作成すると、ユーザ名と同じ名前のグループが新たに作成され、そのグループに属するようになります。ユーザは複数のグループに所属することができます。
ユーザがどのようなグループに属しているかは、```groups```コマンドで確認できます。ユーザを指定しなかった場合は、groupsコマンドを実行したユーザが所属しているグループが表示されます。みなさんの場合は、*student*と表示されるはずです。
```shell
$ groups
student
```
通常グループを確認を確認するには、以下のファイルを確認します。しかし、そこには*student*グループは確認できないはずです。
```
$ cat /etc/group
```
これは、みなさんがどの演習室、どの端末からアクセスしても同じ環境を扱えることと関連してます。これは**LDAP**(Lightweight Directory Access Protocol)という機能を利用して、ネットワーク越しに皆さんの環境を管理しています。試しにLDAPに関するコマンド```getent```(GET ENTries from administrative database)コマンドを利用して、グループ一覧を表示してみましょう。するとgakusai(学祭)用のアカウントなど色々な団体が登録されていることがわかる。
```
# これだと一気に表示されてしまう。
$ getent group
# 後で説明するが、パイプという仕組みとlessコマンドを利用してみよう。
# manコマンドと同じく(q)キーで抜けれる。
$ getent group | less
```
## パーミッション
### 所有者と所有グループ
Unixはマルチユーザのシステムなので、複数のユーザが利用できます。ファイルやディレクトリは、いずれかのユーザおよびグループが所有しています。言い方を買えると、ファイルやディレクトリはいずれかのユーザ、いずれかのグループに属しています。通常、ファイルやディレクトリを作成したユーザが**所有者**となり、所有者のプライマリグループ(student)が**所有グループ**に適用されます。所有者と所有グループは、```ls -l```コマンドで確認できます。
```shell
$ cd
$ echo foo > memo
$ ls -l memo
-rw-r--r-- 1 sxxxx student 6 4月 6 22:09 memo
$ rm memo
```
所有者と所有グループを変えるコマンド```chmown```(CHange OWNer)と```chgrp```(CHange GRouP)がありますが、これらは基本的にシステム管理者が実行すべきコマンドのため割愛させていただきます。
### パーミッションの設定
大切なファイルは、ほかのユーザに勝手に見られたり書き換えられたりしないようにしなければなりません。また、システム上の重要なファイルを自由に書き換えられてしまうと、システムに障害が起きるおそれもあります。本学においては課題等のファイルを他の学生から守るように、採点する側の教員からは見えるように適切にファイルを管理するという意味合いが強くあります。そのようなトラブルが起きないよう、ファイルやディレクトリには**アクセス権**が設定されています。アクセス権には「読み出せる」「書き込める」「実行できる」という3種類があります。これらのアクセス権は、以下のそれぞれに対して設定されます。
- 所有者(owner)
- 所有グループに属するユーザ(group user)
- その他のユーザ(other)
これらを皆さんの立場で置き換えると、
- 自分
- 自分以外の学生
- 教員や職員
といった感じになります。設定される内容の例は、たとえば次のようになります(課題のファイルを想定しています)。
- 自分はファイル内容を読み出したり、書き込んだりできる
- 自分以外の学生はファイル内容を読み出しも書き込みもできない
- 教員(や職員)はファイル内容を読み出せるが書き込みはできない。
これを**パーミッション**といいます。
アクセス権は、以下の記号で表記します。
- 読み取り権=r(Read)
- 書き込み権=w(Write)
- 実行権=x(eXecute)
ファイルのパーミッションは、```ls -l```コマンドで確認できます。
```shell
$ cd
$ echo foo > memo
$ ls -l memo
-rw-r--r-- 1 sxxxx student 4 4月 6 23:21 memo
$ rm memo
```
```rw-r--r--```の部分がパーミッションです。パーミッションは左から3文字ずつ「所有者のアクセス権」「所有者のグループのアクセス権」「その他のユーザのアクセス権」を表します。「-」となっている箇所はアクセス権がないことを表します。この例では、所有者(sxxx)は、このファイルの読み取りと書き込みができ、所有グループに属するユーザとその他のユーザは読み取りができる、ということになります。つまり標準では他の学生から課題のファイル等が丸見えになってしまいます(見せた側もカンニングとなります!)。課題ファイルは、この後で説明するパーミッションの変更を必ずしましょう。

なお、アクセス権は数値で表すこともできます。
- 読み取り権=4
- 書き込み権=2
- 実行権=1
これを所有権、所有グループ、その他ユーザごとに足し合わせた数値で表します。この例の場合、数値で表したパーミッションは```644```となります。

### ディレクトリのアクセス権
ディレクトリに設定されるアクセス権は、基本的にはファイルのアクセス権と同様ですが、異なる点もあります。
#### 読み取り権
```shell
$ ls -ld test
dr-------- 2 sxxxx student 4096 4月 10 15:46 test//
ls: cannot access test/orange: Permission denied
ls: cannot access test/apple: Permission denied
ls: cannot access test/banana: Permission denied
apple banana orange
$ cd test
-bash: cd: test: Permission denied
$ cat test/apple
cat: test/apple: Permission denied
```
#### 書き込み権
ファイルに書き込み権が設定されていると、ファイルの内容を変更することができます。ディレクトリに書き込み権が設定されていると、そのディレクトリ内でファイルを作成したり削除したりすることができます。ファイルに対するアクセス権がなくても、ファイルを削除できてしまう点に注意してください。
ディレクトリに書き込み権がない場合
```shell
$ ls -ld /tmp
dr-x------ 2 sxxxx student 4096 4月 10 15:57 test/
$ ls -l test/sample
--w--w--w- 1 sxxxx student 0 4月 10 15:57 test/sample
$ cat test/sample
cat: test/sample: Permission denied
$ rm -i test/sample
rm: remove regular empty file `test/sample'? y
rm: cannot remove `test/sample': Permission denied
```
ディレクトリに書き込み権がある場合、アクセス権のないファイル*sample*に対して```cat```コマンドは失敗してしまいますが、```rm```コマンドは成功しています。
ディレクトリに書き込み権がある場合
```shell
$ ls -l test/sample
---------- 1 sxxxx grdd 0 4月 10 15:57 test/sample
$ cat test/sample
cat: test/sample: Permission denied
$ rm -i test/sample
rm: remove write-protected regular empty file `test/sample'? y
```
#### 実行権
ファイルに実行権が設定されていると、ファイルをプログラムとして実行することができます。ディレクトリ実行権が設定されていると、そのディレクトリ内に```cd```コマンドで移動したり、ディレクトリ内のファイルにアクセスしたりすることができます。逆に、実行権の設定されていないディレクトリには移動することもできません。
```shell
$ ls -ld test/
drw------- 2 sxxxx grdd 4096 4月 11 15:25 test//
$ cd test/
-bash: cd: test/: Permission denied
$ cat test/sample
cat: test/sample: Permission denied
```
ディレクトリに設定されるアクセス権は通常、```rwx``` ```r-x``` ```--x```のいずれかです。実行権が付与されないケースはまずありません。
### パーミッションの変更
パーミションを変更するには、```chmod```(CHange MODe)コマンドを使います。```chmod```コマンドを実行できるのは、変更対象となるファイルやディレクトリの所有者とrootユーザのみです。
-Rオプションを付けると、指定したディレクトリ以下すべてのファイルのアクセス権を変更することができます。
アクセス権には、```755```のように3桁の数値を指定するか、次の表の記号を指定します。
| |記号 |説明 |
|:-------|:---|:--------|
|操作の対象|u |所有者 |
| |g |所有グループ |
| |o |その他のユーザ |
| |a |すべてのユーザ |
|操作 |+ |権限を追加する |
| |- |権限を削除する |
| |= |権限を指定する |
|アクセス権|r |読み取り許可 |
| |w |書き取り許可 |
| |x |実行許可 |
いくつか例を取り上げましょう。diary.txtのファイルのパーミッションを```rw-r-r--```(644)に設定するには、次のようにします。
```shell
$ chmod 644 diary.txt
```
dataディレクトリのパーミッションを```rwxr-xr-x```(755)に設定するには、次のようにします。
```shell
$ chmod 755 data
```
数値を使った指定では、元のパーミッションがどんな値であっても、指定したとおりのパーミッションに変更されます。
一方、現在のパーミッションを基準に、アクセス権を追加したり削除したりする場合は、記号を使って指定するとよいでしょう。次の例では、*diary.txt*ファイルに所有グループの書き込み権を追加しています。
```shell
$ chmod g+x diary.txt
```
次の例では、*data*ディレクトリから所有者以外のユーザの実行権を削除しています。
```shell
$ chmod go-x data
```
## シェル
コマンドを入力して*Enter*キーを押すと、コマンドが実行されて実行結果が表示されます。コマンドの入力を受け付け、適切な処理をして結果を表示しているプログラムを**シェル**といいます。シェルは、ユーザが入力したコマンドをカーネルというOSの中核に実行させる翻訳者(インタープリタ)の役割を果たします。プロンプトを表示しているのもシェルです。

シェルプログラムはいくつかの種類があります。学校環境で標準的に利用されているシェルは```bash```(以前はcshでした、MacOSの標準のシェルもbashです。)です。他にも、```sh```, ```csh```, ```tcsh```, ```ksh```, ```zsh```, ```fish```などいくつかのシェルが存在します。現在使われているシェルを確認するには、以下のように確認します。
```shell
$ echo $SHELL
/usr/local/gnu/bin/bash
```
bashの幾つか便利な機能を紹介しておきます。いくつかコマンドを打った時に、カーソルキーを上下することでコマンド履歴を参照して再利用することができます。
```shell
$ ls
$ pwd
$ cd
$ ↑ # カーソルの上や下キーを押す。
```
また、履歴を検索することもできるようです。
[bashの履歴を検索するコマンドが捗りすぎてヤバい!俺の作業効率が2倍どころか更に倍してドンッ!](http://tetokon.com/2013/01/21/bash-ctrl-r/)
長いファイル名やディレクトリ名はスペルを打ち間違えてしまいがちですが、```tab```キーを打つことで文字の**補完**をしてくれます。補完対象が複数ある場合は、対象のファイルやディレクトリ名を表示をしてくれます。
```shell
$ cd
$ ls
$ cd Do # ここでtabキー
Documents/ Downloads/ # 候補を2つ出してくれる。
$ cd Dow # ここでtabキー
$ cd Downloads/
```
他にもシェルを便利に使うコマンドが多く用意されています。作業効率を上げることで他の事に多く時間を割くことが出来ます。是非マスターしましょう。
### メタキャラクタ
シェルにとって特別な意味を持つ文字をメタキャラクタといいます。ファイル名の指定などに利用できる主なメタキャラクタは次の表の通りです。
|メタキャラクタ|説明 |
|:----------|:-----------------------------|
|\* |0文字以上の任意の文字 |
|? |任意の一文字 |
|[] |[ ]内の任意の一文字 |
|\\ |メタキャラクタの打ち消し(エスケープ)|
いくつか例を見てみましょう。以下の練習をする場合は、前もってコマンドを実行してください。
練習用ファイルの生成
```shell
$ cd
$ mkdir test
$ cd test
$ touch {,a,b,c}{1..5}.txt
```
ファイル一覧を表示
```shell
$ ls
1.txt 3.txt 5.txt a2.txt a4.txt b1.txt b3.txt b5.txt c2.txt c4.txt
2.txt 4.txt a1.txt a3.txt a5.txt b2.txt b4.txt c1.txt c3.txt c5.txt
```
「\*」と「?」の違いは、「?」が一文字だけを表すのに対し、「\*」は任意の長さの文字列を表す点です。
「\*」と「?」の違い
```shell
$ ls *.txt
1.txt 3.txt 5.txt a2.txt a4.txt b1.txt b3.txt b5.txt c2.txt c4.txt
2.txt 4.txt a1.txt a3.txt a5.txt b2.txt b4.txt c1.txt c3.txt c5.txt
$ ls ?.txt
1.txt 2.txt 3.txt 4.txt 5.txt
```
[]を使うと、[ ]内の1文字とマッチします。次の例では、「a」もしくは「b」で始まる名前のファイルにマッチします。
```shell
$ ls [ab]*.txt
a1.txt a2.txt a3.txt a4.txt a5.txt b1.txt b2.txt b3.txt b4.txt b5.txt
```
[ ]内は「-」をつかって範囲を指定することもできます。
```shell
$ ls [3-5].txt
3.txt 4.txt 5.txt
```
ファイル名に「1」か「3」が含まれるファイルにマッチします。
```shell
ls *[13]*
1.txt 3.txt a1.txt a3.txt b1.txt b3.txt c1.txt c3.txt
```
「\*」は0文字以上、つまり0文字にもマッチするので、1.txtや3.txtにもマッチしている点に注意してください。
### 標準入出力
Linux上で実行されるプログラムには、デフォルトで3つの出入り口が用意されます。それが**標準入力**、**標準出力**、**標準エラー出力**です。プログラムは標準入力から入力を受け付けます。デフォルトはキーボードです。
標準出力はプログラムの実行結果が、標準エラー出力はプログラムのエラー結果が出力されます。デフォルトは端末画面です。ただし、シェルはこれらの入力元、出力元を切り替える事ができます。詳細は次の「リダイレクト」で解説します。

```cat```コマンドを例に取りましょう。catコマンドは、何も引数を指定しなければ、標準入力から受け取ったデータを標準出力に出力する、という動作をします。catコマンド(プログラム)が、ユーザが入力した「Unix」という文字列を標準入力として受け取り、標準出力に渡すことで端末画面に「Unix」という文字が表示されます。
```shell
cat
Unix
Unix
Aizu
Aizu
ctrl-D # Ctrl + D で停止。
```
#### リダイレクト
**リダイレクト**(リダイレクション)を使うと、コマンドの標準出力を端末画面ではなく、任意のファイルに切り替えることができます。
```
コマンド > ファイル名
```
次の例では、```date```コマンドの出力を*today*ファイルにリダイレクトしています。todayファイルが存在しない場合は、ファイルが新しく作られます。コマンドの出力はファイルに切り替えられたので、画面上には何も出力されません。実行後、todayファイルにはdateコマンドの出力したメッセージが書き込まれています。
```shell
$ date > today
$ cat today
2017年04月12日 (水) 13時35分47秒 JST
```

リダイレクトはファイルの内容をコマンドの標準入力へ渡すことも可能です。
```shell
$ cat < today
2017年04月12日 (水) 13時35分47秒 JST
```
もう一度リダイレクトを実行しまみます。
```shell
$ date > today
$ cat today
2017年04月12日 (水) 13時40分28秒 JST
```
新しい出力に書き換わりました。このように「>」を使ったリダイレクトでは、ファイルの内容を上書きしています。上書きだけではなく、ファイルの末尾に追記する場合は、「>」の代わりに「>>」(アペンド)を使ってください。
```shell
$ date >> today
$ cat today
2017年04月12日 (水) 13時40分28秒 JST
2017年04月12日 (水) 13時42分17秒 JST
$ rm today
```
なお、エラーメッセージは標準出力ではなく、標準エラー出力に出力されます。標準エラー出力をリダイレクトするには、「2>」もしくは「2>>」を使います。次の例では、```find```コマンドというファイルを検索してパスを表示してくれるコマンドです。検索対象をルートディレクトリに指定して、C言語のファイルを検索しています。しかし、ルートディレクトリには管理者権限しか閲覧できないファイルが大量にあるため*Permission Denied*エラーが大量に出てしまい、標準出力にある知りたい情報が埋もれてしまいます。
標準出力が標準エラー出力に埋もれてしまう例
```shell
find / -name *.c # 処理を止めたい場合は、ctrl-c
# 大量のPermission Deniedエラー
```
そこで、```/dev/null```という特殊ファイルに標準エラー出力をリダイレクトしましょう。そうすると、エラーの出力は破棄されて、標準出力だけが見ることができます。
```shell
find / -name *.c # 処理を止めたい場合は、ctrl-c
# エラーが無いパスだけの情報
```
### パイプ
**パイプ**「|」を使うと、あるコマンドの実行結果を別のコマンドで処理することができます。
```
コマンド | コマンド
```
パイプは、一画面に収まりきらない出力を```less```コマンドで表示するときなどによく使います。先程の大量にあった```find```コマンドの結果をlessで見てみましょう。見るのを終わるには、```q```キーを押してください。
```shell
$ find / -name *.c 2> /dev/null | less
````
### コマンドとパス
コマンドには、組み込みコマンドと外部コマンドがあります。**組み込みコマンド**はシェルに内蔵されているコマンドです。シェルによって多少の違いがみられます。bashの主な組み込みコマンドは、```cd```, ```echo```, ```pwd```などが挙げられます。
**外部コマンド**は、コマンドと同じ名前のある実行プログラムです。whichコマンドを使うと、コマンドの実行ファイルがどこにあるか確認できます。
lsコマンドの実行ファイル
```
$ which ls
/usr/local/gnu/bin/ls
```
外部コマンドを実行するには、そのファイルを絶対パスで指定する必要があります。例えば```ls```コマンドであれば、本来は```/usr/local/gnu/bin/ls```と入力する必要があります。
```/usr/local/gnu/bin/ls```コマンドの実行
```shell
$ /usr/local/gnu/bin/ls
Desktop Pictures program
Downloads Public data ...
```
しかし、いちいち```/usr/local/gnu/bin/```を入力しなければならないのは面倒ですね。そこで、コマンド名だけ入力すれば、対応する実行ファイルを検索して実行できる仕組みが用意されています。コマンドが入力されると、シェルはそのコマンドを実行しようとします。もしコマンドが組み込みコマンドでなければ、シェルは変数PATHに格納されているディレクトリの中を片っ端から検索し、コマンド名に一致する実行ファイルを見つけたらそれを実行します。これを**コマンドサーチパス**(あるいは単に**パス**と言います)。パスを確認するには、以下のように入力します。パスは絶対パスで保存され、コロン(:)で区切られて一度に表示されます。
```shell
/usr/local/gcc/bin:/usr/local/gcc3/bin:/usr/local/perl5/bin:/usr/local/texlive/bin:/usr/local/bin:/usr/local/gnu/bin:/usr/local/java/jdk/bin:/usr/openwin/bin:/usr/bin:/usr/sbin:/usr/local/LPRng/bin:/usr/local/SolarisStudio/bin:/usr/ccs/bin:/usr/dt/bin
```
### シェルのカスタマイズ
シェルは起動時に設定ファイルを元にコマンドを実行していき初期設定をします。```~/.bash_profile```を```emacs```エディタで開き以下の内容を末尾にコピー&ペーストしましょう。
```shell
# lsをカラーリング
if [ `uname` = "Darwin" ]; then
alias ls='ls -FGH'
elif [ `uname` = "SunOS" ]; then
alias ls='ls -F --color'
fi
# コメントアウト
# PS1="\h:\W \u[\!]$ "
# プロンプトをシンプルに
PS1='[ \w ] $ '
# deleteを有効
stty erase '^?'
```
追記が済んだら設定ファイルを有効にするために、```source```コマンドを使います。
```shell
$ source ~/.bash_profile
```
実行後、```ls```コマンドやプロンプトに注目してみましょう。
### Gitコマンドの追加
学生アカウントは管理者権限ではないため、パッケージインストーラと呼ばれるツールを利用してコマンドを導入することはできません。しかし、ソースコード(プログラム)をダウンロードし、```make```(ソースコードをビルドするコマンド)することは可能です。以下の手順に従ってGitと呼ばれるソースコード管理ツールを導入してみましょう。
```shell
$ cd
# Git 2.0.5のソースを取得
$ wget https://www.kernel.org/pub/software/scm/git/git-2.0.5.tar.gz
# ソースを解凍してディレクトリに移動
$ tar xvf git-2.0.5.tar.gz
$ cd git-2.0.5
# ビルド
$ ./configure
$ make
```
```git```コマンドを実行してみましょう。
```shell
$ ./git
usage: git [--version] [--help] [-C <path>] [-c name=value]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
<command> [<args>]
...
```
しかし、通常のコマンドのようには実行できません。なぜでしょうか?それはコマンドサーチパスに追加されていないからです。
```shell
$ git
-bash: git: command not found
```
それでは、コマンドサーチパスに追加するにはどうするでしょうか?答えは、```~/.bash_profile```の末尾に以下の文を追加しましょう。
```shell
PATH=$PATH:~/git-2.0.5
```
```source```を実行してから、gitコマンドを叩いてみましょう。
```shell
$ source ~/.bash_profile
$ git
```
もし、自分で使いたいコマンドがあれば同じような手順で追加することが可能です。容量に注意しながら自由にコマンドを追加してみましょう。また、Git自体についての説明は割愛させていただきますが、このコマンドはプロの現場でも使われるソースコードを管理するための大変有用なツールです。調べてみて使いこなしてみましょう(演習のファイルなどを管理するのに最適です)。
## プロセスとジョブ
### プロセス
プログラムは通常、ファイルの形でハードディスク上に保存されています。プログラムを実行すると、そのプログラムコードがコンピュータのメモリ上に読み込まれ、CPUによって実行されます。メモリ上で実行中のプログラムをプロセスといいます。プロセスの情報は、```ps```(ProceSs)コマンドで表示できます。
psコマンドの主なオプション(引数)
|オプション|説明 |
|:-------|:------------------------|
|a |他のユーザのプロセスも表示する|
|u |ユーザ名を表示する |
|x |端末から実行されたものでない(サーバプロセスなど)も表示する|
オプションなしでpsコマンドを実行すると、psコマンドを実行したユーザが、その端末上で起動したプロセスの一覧を表示します。
```shell
$ ps
PID TTY TIME CMD
3832 pts/42 0:00 ps
3794 pts/42 0:00 bash
```
psコマンドの主な表示項目
|項目|説明 |
|:-------|:---------------------|
|PID |プロセスID |
|TTY |プロセスを実行した端末名 |
|TIME |プロセスの実行時間 |
|CMD |実行コマンド |
プロセスを起動すると、プロセスごとに固有のID番号が割り当てられます。これを**プロセスID**(PID)といいます。プロセスIDはプロセスを特定するために利用できます。そのため、同じ名前のプログラムが複数実行されていても、それらを識別できるわけです。
システム上で実行されているプロセスすべてを表示するには、auxオプションを付けます。
```shell
$ ps aux
[大量のプロセス]
```
### プロセスの終了
プログラムの実行が終了すると、プロセスは消滅します。たとえば、シェル上で```date```コマンドを実行したときの流れを図にすると、次のようになります。
[書き途中]
## 参考書籍
[Linux標準教科書](http://www.lpi.or.jp/linuxtext/text.shtml)
[1週間でLPICの基礎が学べる本-第2版-徹底攻略シリーズ](https://www.amazon.co.jp/ebook/dp/B00IWNEWS8)