Linuxの基礎知識をまとめてみた

## Linuxって何？
+ Linuxは**OSの一種で、コンピュータを動かすための基本ソフト**
    + 基本ソフトがないとコンピュータは動かない
    + 他のOSとして、Windows,Mac OS X, Androidなどがある

## Linuxはどのように誕生したのか？
+ 1970年頃
    + **UnixというOSが誕生**
    + シンプルな小さいOSで大学や研究所を中心に普及
    + 有料。ライセンス縛りも厳しい
+ 1985年〜
    + オープンソース版のUnixを開発するプロジェクトがスタート
    + ソースコードも公開されていたので、様々な派生版のUNIXが誕生
+ 1991年
    + 当時大学生のリーナス・トーバルズが**Linuxを開発**し、**オープンソース化**
    + UNIXを真似て、一からOSを作る
    + 最終的に最も普及
    + **有料のUnixが、Linuxという形で無料で使えるようになった**

## Linuxはどこで使われているのか？
+ サーバー、組み込み、デスクトップといった幅広い用途て使われている

## Linuxの特徴と欠点
+ `特徴`
    + **オープンソースなので誰でも自由に使える**
    + **世界中で使われていて信頼性が高い**
        + 特にサーバー用途として広く使われている
    + **品質の高い多くのソフトウェアが利用できる**
        + WebサーバーのApacheやデータベース管理システムのMySQLなど
    + **自動化するための仕組みがあり、サーバーの運用が行いやすい**
    + **マルチタスク機能**であり、複数の機能を同時に実行することができる
+ `欠点`
    + **商用アプリケーションがあまり存在しない**
        + WordやExcelなどのMicrosoft Officeが動作しない
        + 画像、音楽、動画などのマルチメディア系ファイルを編集するのが苦手
    + **日本語対応されていない部分が多い**
        + ドキュメントやヘルプが英語しかなかったり。。
        + ソフトウェアによっては日本語を利用すると文字化けしたりすることもある

## Linuxを学ぶ理由
+ Linuxは**枯れている技術**(広く使われることで信頼性が高くなった技術)なので、学ぶことで何年経っても使える技術を得ることができる
+ 幅広い場所で使われている
    + **サーバー用・組み込み器用**
        + 幅広い場所で使われており、そういった場所でマシンを操作するときに必要
    + **長年使える**
        + Linuxの技術は長い時間をかけて多くのユーザーに検証された結果、大きく変更する必要がなくなっている
        + →技術が枯れている
        + →**一度習得すれば何年経っても使える！**

## ディレクトリの操作
* ファイル種別を表示
`$ ls -F`
* コマンドの使い方を調べる
```
<コマンド>  --help
$ less --help
```
* コマンドのマニュアルを表示(manualの略/helpより詳しく知れる)
`$ man ls`
* キーワードに関連したコマンドの一覧を表示する(コマンドをきちんと調べたい時に使う)
`$ man -k <調べたいキーワード>`


## ファイルの操作
+ `$ less <ファイル名>`
    + **ファイルの中身をスクロール表示**するコマンド(長いファイルの中身を見たい時に使うコマンド)
        * **catコマンド**
            * 画面にそのままファイルの中身を出力する
        * **lessコマンド**
            * 別の画面が立ち上がり、ファイルの中身出力してスクロールで確認

| コマンド | 内容 | 
| -------- | -------- | 
| スペースキー or fキー     | 一画面下にスクロール     | 
| bキー  | 一画面上にスクロール | 
| kキー | 一行上にスクロール | 
| jキー     | 一行下にスクロール     | 



### ファイル内で検索

| コマンド | 内容 | 
| -------- | -------- | 
| /文字列     | 下方向に向かって検索     | 
| ?文字列  | 上方向に向かって検索 | 
| n | 次の検索結果に移動 | 
| N     | 前の検索結果に移動     | 


### ファイルの作成
+ `$ touch <新規file1> <新規file2>...`
    + 空のファイルを作成するコマンド
    + ex) $ touch README.md
        + ファイル名が存在していないときはからのファイルを作成
        + 存在しているときはタイムスタンプを更新

### ファイル削除

* ディレクトリも合わせて削除する(rmは通常ファイルを削除するコマンドなので)
`$ rm -r <dir>`

* ファイルを削除する際に警告文を表示させない
`$ rm -f <file>`

* ファイルの削除前に確認する
`$ rm -I <file>`



### ファイルの移動・ファイル名の変更

* ファイル名を変更
`$ mv <file> <file1>`

* ファイルを移動
`$ mv <file1> <dir/>`



### ファイル・ディレクトリをコピー

* ファイルをコピー
`$ cp <file> <new_file>`

* ファイルをディレクトリ内にコピー(コピー先のファイルが既にあると上書きするので注意する)
`$ cp <file> <dir>`

* ディレクトリをコピー
`$ cp -r <dir> <new_dir>`



### リンクを貼る
* **`書式 : ln [オプション] <リンク元ファイル> <リンク名>`**
    * オプションを何も付けないとハードリンクになる

* **ハードリンク**
    * 一つのファイルの実体に複数の名前をつける機能
    * 元のファイルを削除しても消えない
    * 全てのハードリンクが無くなった時に削除される

* **シンボリックリンク**
    * リンク先のパス名が書かれた特殊なファイル
    * リンク先がファイルの実体
    * シンボリックリンクを残したままファイルの実態を削除したり、ファイルを移動すると、ファイルを参照できなくなる


### リンクを貼るコマンド

+ Linuxではファイルに別名をつけることができ、**別名を付ける事を「リンクを貼る」という**(Windowでいうショートカットみたいなもの)

* **ハードリンクを貼る**
    * **一つのファイルの実体に複数の名前をつける機能**
    * 元のファイルを削除しても消えない
    * すべてのハードリンクがなくなった時に削除される

```zsh
$ ln <file1> <file1_hard>
```

* **シンボリックリンクを貼る**(こっちの方がよく使う/異なるディレクトリをまたげる)
    * **リンク先のパス名が書かれた特殊なファイル**
    * リンク先がファイルの実体
    * シンボリックリンクを残したままファイルの実体を削除したり、ファイルを移動すると、ファイルを参照できなくなる

`$ ln -s <file1> <file1_symbolic>`

#### ハードリンクとシンボリックリンクの挙動の違い
```zsh
➜  linux_udemy $ ls
file (空ファイルを作成済)
➜  linux_udemy $ echo "hogehoge foobar foobaz"
hogehoge foobar foobaz
➜  linux_udemy $ echo "hogehoge foobar foobaz" > file
➜  linux_udemy $ cat file
hogehoge foobar foobaz
➜  linux_udemy
➜  linux_udemy
➜  linux_udemy
➜  linux_udemy $ ln file file_hard (ハードリンクを作成)
➜  linux_udemy $ ln -s file file_symbolic (シンボリックリンクを作成)
➜  linux_udemy $ ls
file          file_hard     file_symbolic
➜  linux_udemy $ cat file_hard
hogehoge foobar foobaz
➜  linux_udemy $ cat file_symbolic
hogehoge foobar foobaz
➜  linux_udemy $ rm file
➜  linux_udemy $ cat file_hard (元ファイルを消去しても中身を見れる)
hogehoge foobar foobaz
➜  linux_udemy $ cat file_symbolic (ファイルの実体がなくなると、ファイルを参照できなくなる)
cat: file_symbolic: No such file or directory
```


### ファイルを検索するコマンド
+ findコマンド
    + ファイルやディレクトリを探すためのコマンド
    + **`$find　<検索開始ディレクトリ>　<検索条件>　<検索アクション>`**
    + ex) `$ find . -name README.md -print`
    + ※検索アクションは省略可

+ ファイル名を指定してファイルを検索(ファイル名の大小文字は区別する)
    + `$find . -name "*.html"`
    + *(アスタリスク)は任意の文字列
    + ?も使えて、任意の1文字に一致する
    + *を使うときは必ず**ダブルクオートもしくはシングルクオートで囲む**ようにする
        + でないと、**bashがパス名展開してしまい、複数ファイルを指定したと思われエラー**となる
+ ファイル名を指定してファイルを検索(ファイル名の大文字小文字は区別しない)
    + `$find . -iname readme.md`


### ファイルの種類で検索

+ 通常ファイル
    + `$ find . -type f -print`
+ シンボリックリンク
    + `$ find . -type l  -print`
+ ディレクトリ
    + `$ find . -type d -print`
+ 複数の条件を指定する(-aは省略可)
    + `$ find . -type d -a -name images -print`
    + →`images`という名前のディレクトリを検索する



## 標準入力とパーミッション

### 標準入出力について
+ **標準入出力**とは、プログラムが特に何も指定されていない場合に利用する標準的な入出力元のこと
    + キーボードから入力したコマンドなどのように、コンピュータにデータを受け渡すことを**入力**と呼ぶ
    + コマンドやプログラムの実行結果を外に向かって出すことを**出力**と呼ぶ
    + 上記の**入力と出力**をあわせて**入出力**と呼ぶ
    + **入力の場合はキーボード、出力の場合はディスプレイというのが標準**になっており、`入力元と出力先は指定すると変更することができる`
    + 入力元と出力先を指定しない場合は、デフォルトで決められているものが使用され、**デフォルトで決まっているもの**を**標準**と呼ぶ

+ **標準入力、標準出力、標準エラー出力の3つ**をあわせて****標準入出力****を呼ぶ
    + **標準入力**
        + プログラムの標準の入力
        + キーボードが通常は使われる
        + 識別子の数値 : 0(省略できる)
    + **標準出力**
        + プログラムの標準の出力
        + ディスプレイが通常は使われる
        + 識別子の数値 : 1(省略できる)
    + **標準エラー出力**
        + プログラムのエラーメッセージを出力する
        + ディスプレイが通常は使われる
        + 識別子の数値 : 2(省略できない)


### リダイレクト

+ **リダイレクト**というのは**入出力先を変更**する機能
+ **入力のリダイレクト**
    + **キーボードの代わり**に**ファイルから入力**する機能
    + ex) /etc/hostsファイルを入力元にしてcatコマンドを実行
    + `$ cat < /etc/hosts`
    + 
+ **出力のリダイレクト**
    + **コマンドの実行結果**を画面に表示するのではなく、**ファイルに保存**する機能
    + ex) lsやcatコマンドの出力先をoutput.txtにして保存
    + `$ ls > output.txt`
    + `$ cat > output.txt`
+ **エラー出力のリダイレクト**
    + **エラー結果**を画面に表示するのではなく、ファイルに保存する機能
    + ex) `$ ls /hoge 2> error.txt`

#### リダイレクトのその他の使用方法

+ 出力とエラー出力をまとめる
    + まとめる場合は、出力をリダイレクトした後に**2>&1**とかく
    + `$ ls / /hoge > output.txt 2>&1`
        ```zsh
        ➜  linux_udemy $ ls / /hoge > output.txt 2>&1
        ➜  linux_udemy $ cat output.txt
        # ▼出力とエラー出力がまとめて表示される
        ls: /hoge: No such file or directory
        /:
        bin dev etc home lib
        ```
+ リダイレクトで追記する
    + 「**>**」でリダイレクト指定するとファイルを上書きする
    + 「**>>**」でリダイレクト指定するとファイルに追記する
        + `$ echo Hello！ >> output.txt`

+ /dev/null
    + **入力先として指定**しても`何も返さず`、**出力先として指定**しても`データは消え何も表示されない`スペシャルファイル
    + **入力先として指定**
        + 入力が何もない状態になる
        + コマンドのテストなどで入力を空にしたい時に使用
        + あまり使われない
    + **出力先として指定**
        + 結果が何も表示されない
        + 結果が大量にあり、結果を非表示にしたい時に使用
        + よく使う

+ パイプライン
    + 複数のコマンドを連携させる機能
    + コマンドの標準出力を別のコマンドの標準入力に繋げる
    + **`$ コマンド | コマンド`**
    + ex1) `$ ls /bin | less`
    + ex2) `$ ls /bin | grep systemd | less`


### パーミッション

+ **パーミッション**とは、**ファイルの権限管理**の事
+ **`なぜ、パーミッションという仕組みがあるのか？`**
    + Linuxは**複数人が1台のコンピュータにログインして操作することが前提**で作られている
    + 他人のファイルを勝手に削除されても困るし、システムの設定なども勝手に変えられて欲しくない
    + 上記のことが起こらないように、**システムの設定は管理者しかできない**ようになっていたり、**ファイルのアクセス権限はユーザーごとに決められる**ようにしたい
    + パーミッションを理解することで、**Linuxのシステムを安全に管理したり、使用したり**できる
    + また、パーミッションについて理解していないと、ファイルにアクセス出来なくて**エラーになった時に解決出来ない**

### ファイルのオーナーとグループ
+ ファイルには全てオーナー(所有者)とグループ(所有グループ)が設定され権限管理されている
    + 前提 : Linuxではユーザーごとにアカウントを発行する
    + オーナー : ファイルの所有者
    + グループ : ファイルの所有グループ
        + ユーザーをグループに所属させ、グループに権限を与えることで、複数ユーザーの権限を一括で管理できるようにする
    + `$ ls -l` コマンドでファイルのオーナーとグループが確認できる
        ```zsh
        ➜  hoge $ ls -l
        total 0
        -rw-r--r--  1 linux-user(オーナー)  staff(グループ)  0  4 30 13:31 owner-group.txt
        ```

### パーミッション
+ ファイルやディレクトリを「**誰がどのように操作できるか**」を定めたのがパーミッション
    + ex) `-rwxr-xr--`
        + \- : ファイルタイプ
        + rwx : オーナーのパーミッション
        + r-x : グループのパーミッション
        + r-- : その他ユーザーのパーミッション
+ 以下の**3種類の権限**がある
    + **読み取り（r）**: ファイルの内容を読み取る権限
    + **書き込み（w）**: ファイルの内容を変更する権限
    + **実行（x）**: ファイルを実行する権限（通常はプログラムやスクリプトに対して適用される）
+ ファイルタイプ
    + **通常ファイル（-）**: テキストファイル、バイナリファイル、プログラムなど
    + **ディレクトリ（d）**: ファイルおよび他のディレクトリを格納するコンテナ
    + **シンボリックリンク（l）**: 他のファイルやディレクトリへの参照（ショートカット）
    + **ブロックデバイスファイル（b）**: ブロックデバイス（例: ハードディスク）へのインターフェイス
    + **キャラクタデバイスファイル（c）**: キャラクタデバイス（例: シリアルポート）へのインターフェイス
    + **ソケットファイル（s）**: プロセス間通信に使用されるソケット

### ファイルモードの変更 

+ **ファイルやディレクトリのパーミッションを設定**する(change modeの略)
+ **`$ chmod [ugoa] [+-=] [rwx] ファイル名`**
    + u : 所有者の権限
    + g : グループの権限
    + o : その他のユーザーの権限
    + a : 全ユーザーの権限
    + \+ : 権限を追加
    + \- : 権限を削除
    + = : 記述した権限にする
+ ex) `$ chmod u+r file`(相対指定)
    + **現在の権限から特定のユーザーの権限だけ変更したいとき**はこっちをよく使う


#### 数値で指定する方法

+ **`$ chmod　<8進数の数値>　<ファイル名>`**
    + r(読み取り) : 4
    + w(書き込み) : 2
    + x(実行) : 1
+ ex) `$ chmod 755 file`(絶対指定)
    + 「オーナーもグループもその他もこの権限にする！」みたいに、あらかじめ決まっている時などに使う
+ **755**はよく指定する設定で、**オーナーは全部できて、その他のユーザーは読み取りと実行はできるけど、書き込みができない設定**という意味
    + 7(オーナーの権限) : rwx(4 + 2 + 1)
    + 5(グループの権限) : r-x(4 + 1)
    + 5(その他の権限) : r-x(4 + 1)


### スーパーユーザー
+ スーパーユーザーとは、**管理者権限を持つ特別なユーザー**のこと(**switch user and doの略**)
+ 背景
    + システムの根幹に関わる作業が誰にでもできると危険
    + その為、システムの根幹に関わる作業はスーパーユーザー(root)だけができるようにしている
+ コマンドの前にsudoをつけるとスーパーユーザーとしてコマンドを実行
    + **`$ sudo <コマンド>`**
+ ex) `$ sudo mkdir /storage`
    + rootディレクトリ直下の書き込み権限はrootユーザーしかないので、エラーとなる



## プロセス・ジョブの管理
+ なぜ、`プロセス・ジョブの管理`(**コマンドが実行されている裏側**)を理解する必要があるのか？
    + **複数の作業を同時に行うことができる**
        + 複数のターミナルを立ち上げるみたいなことをしなくても済む場合がある
    + **トラブルシューティングが出来るようになる**
        + 負荷の高い作業をしている中、メモリやCPUなどが枯渇してきてサーバーがダウンした時などに、不要なコマンドを停止したりして、メモリやCPUの負荷を下げることができる
+ まとめると、**今後より複雑な作業をしている時に困らなくなる**

### プロセスについて学んでいきましょう
+ **`プロセス`**とは**メモリ上で実行中のプログラムのこと**を指す
    + コマンドを実行すると、**実行ファイルをメモリに格納**して、メモリ上で**CPUがプログラムを実行**する。一つ実行すると新しいプロセスが一つ作られる
    + たとえ**同じコマンドを実行**したとしても、プロセスは**別々のものが作られる**
    + **プロセスごとにプロセスIDが割り当てられて**プロセスを管理できるようになっている
    + プロセスもファイルと同じように**個々に実行ユーザーが割り当てられている**
        + 他のユーザーが自分のプロセスを勝手に操作できないようになっている


### 実行中のプロセスを表示するコマンド
* 実行中のコマンドを確認するのだったら実行中のコマンドを確認するこ&でプロセスを確認したないとどこでプログラムを時効されているつのか確認する必要があるために

+ ps(process statusの略)
    + **`$ ps [オプション]`**
        ```zsh
        ➜  linux_udemy $ ps
        # PIDにプロセスIDが、CMDに実行中のコマンドが表示されている
        # PID : プロセスID、　CMD : 実行中のコマンド
          PID TTY           TIME CMD
          699 ttys000    0:00.31 -zsh
         8318 ttys000    0:00.02 tmux
        ```
+ オプション
    + **`aux`** : 全ユーザーのプロセスを、詳細情報を合わせて表示する
    + `$ ps aux`
    + →オプションだけど - を付けなくて良い。
        + x : psコマンドを実行したユーザーの全てのプロセス
        + a : 全てのユーザーのプロセス
        + u : 詳細情報を合わせて表示する



### ジョブ
+ **ジョブ**とは、**まとめて実行されるプロセスの集まり**のこと。シェルごとに管理される
+ ジョブとプロセスの違い
    + プロセスは**OS全体で統一して管理される**
        + システムが自動で実行しているプログラムや他のユーザーは実行している
        + コマンドを一括して管理
    + ジョブは、**そのジョブを実行するshellで管理される**
        ```zsh
        $ ps aux | grep bash | less
        # →プロセスは3つ生成される
        # →ジョブは1つ生成される
        ```
### ジョブの状態を変更する
+ **シェルの画面外でコマンドを実行**することを**バックグラウンド**という
+ **シェルの画面内でコマンドを実行**することを**フォアグラウンド**という

    

+ **現在のジョブの一覧**を表示するコマンド
    + `$ jobs`
        ```zsh
        $ jobs
        [1]+ 実行中 sleep 10 &
        ```
    + →ジョブid, 実行状況、実行コマンドを表示する


+ ジョブを**フォアグラウンド**にするコマンド
    + **`$ fg %<ジョブid>`**
    + `$ fg %1`
    + →ジョブをフォアグラウンドに戻して対話的に操作したい時に使う


+ ジョブを**バックグラウンド**にするコマンド
    + **`$ bg %<ジョブid>`**
    + `$ bg %1`
    + →長い時間かかる処理をバックグラウンドで実行する事で、コマンドが終了するのを待たなくて良くなる

+ コマンドをバックグラウンドで実行する
    + `$ sleep 5 &`

#### 使用例
+ LinuxやUnix系のシェルで、`実行中のジョブを停止（一時停止）または中断（終了）するためのコマンド`は以下の通り
+ **ジョブの停止（一時停止）**
    + **実行中のジョブを一時停止させる**には、**Ctrl + Z** キーを押す
    + これにより、ジョブは**バックグラウンドで停止状態**になる
    + **停止したジョブを再開**するには、**fg コマンド**（フォアグラウンドに戻す）または **bg コマンド**（バックグラウンドで実行）を使用
+ **ジョブの中断（終了）**
    + **実行中のジョブを中断（終了）させる**には、**Ctrl + C** キーを押す
    + これにより、ジョブは**強制終了**される


```zsh
➜  linux_udemy $ man zsh # zshの使い方を調べる
[1]  + 26609 suspended  man zsh　#Ctrl + zで停止
➜  linux_udemy $ jobs
[1]  + suspended  man zsh
➜  linux_udemy $ fg %1　# フォアグラウンドに停止したコマンドを戻す(マニュアルの途中から表示してくれる)
[1]  + 26609 continued  man zsh
```

### ジョブやプロセスの終了
+ ジョブやプロセスを終了させるには、killコマンドを使用する
    + `kill process`の略
+ **`$ kill [オプション] %<ジョブID>`**
    + ex) `$ kill %1`
+ **`$ kill [オプション] <プロセスID>`**
    + ex) `$ kill 4967`
+ `フォアグラウンドのジョブ`は**Ctrl+cで終了**する
+ `停止中やバックグラウンドのジョブ`は**killコマンドで終了**できる



### 補足 
+ 正確には、killコマンドは**シグナルを送信するコマンド**
    + デフォルトでは、**TERM**という**終了を指示するシグナル**を送信している
+ **`$ kill -<シグナル名> <プロセスID>`**
+ 以下の２つのコマンドは同じ意味
    + `$ kill 4567`
    + `$ kill -TERM 4567`
+ **時々使う、SIGKILLという強制終了のシグナル**
    + killコマンドを打っても終了しない異常なプロセスがいる時に使う
        + ただし、**必要な処理を行なってから終了するプロセスもある**ので、できる限り使わないようにする(**最終手段として使う！**)
    + 以下の2つのコマンドは同じ意味
        + `$ kill -SIGKILL 4567`
        + `$ kill -9 4567`


#### 使用例
```zsh
➜  linux_udemy $ sleep 10
^C # Ctrl + cで中断
➜  linux_udemy $ jobs
➜  linux_udemy $ sleep 100 & #バックグラウンドで実行
[1] 27173
➜  linux_udemy $ jobs
[1]  + running    sleep 100
➜  linux_udemy $ kill % 1　#実行中のsleep 100を終了させる
[1]  + 27173 terminated  sleep 100
➜  linux_udemy $ jobs
➜  linux_udemy # ジョブが終了している事がわかる
```

## 参考教材
[もう怖くないLinuxコマンド。手を動かしながらLinuxコマンドラインを5日間で身に付けよう - Udemy](https://www.udemy.com/course/unscared_linux/)