必要最低限で覚えるLinuxコマンド超入門

# はじめに
Linuxコマンドを「普段使い」できるように必要最低限のもので解説します。正確な解説ではないので、シェルとはカーネルがなんとか、とか、アーキテクチャがなんとか、とかはありません。（し、自身に知識がないのでそもそも説明できません）

コマンドを覚えて使いこなせるのが最良ですが、それができなくても **こういうことができる** と知るだけでも十分役に立ちます。

「できる」と知っていれば、たとえ詳細に覚えてなくても、そのときに探せばいいのです。仮に「できない」なら、それを一生懸命に検索する時間は無駄です。

:::note
**「知っている」だけで強いのです**
:::

このエントリで記載している各コマンドの使い方は、ごく基本的な書式と初歩的なオプションに限定しています。

Git for WindowsをインストールするとついてくるGitBashをベースにしていますが、Linuxでも操作方法は同じです。

説明文は文献をあたっていないので、いいかげんなものが含まれている可能性があります。ごめんちょ。


# コード表示について

説明ではコードの表示エリアにコマンドなどを記載している。

行頭に`$`が記載されている場合は、`$`以降のコマンドを実行する。もしくは実行するコマンドと、その結果を記載している。
```:この場合は pwd だけをコピーor手打ちして実行する
$ pwd
/c/Users/basha
```

行頭に`$`が記載されていない場合は、そのコード全体をコピーして実行してよい。
```:この場合はコード全体をコピペしてOK
pwd
echo $PWD
```
コード表示欄の右上にあるコピーマークをクリックして
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334782/2c87a869-c282-407f-ce95-e8f9a837e00b.png)

ターミナルに貼り付けてエンター
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334782/786f32d1-729f-0a9c-35a4-d01468adaed4.png)


いずれの場合も、行頭に`#`がある場合はコメントなので無視する。コピーして実行してよい場合は、自動的に無視されるのでそのままコピーして実行してよい。

```:この場合もコード全体をコピペしてOK
# ここはコメントなのでコピーしても無視される
pwd
echo $PWD
```

# 基本コマンド

「なんだかわかんないけどターミナルから応答がなくなった！」なら`Ctrl-c`でとりあえず強制終了でいいです。


## ディレクトリ/ファイル操作

これができないと死にます。
がんばって覚えましょう。

|コマンド|略|効果|
|:--:|:--:|:--:|
|`cd`|Change Directory|ディレクトリを変更|
|`pwd`|Print Working Directory|カレントディレクトリを表示|
|`mkdir`|MaKe DIRectory|ディレクトリを作成|
|`ls`|LiSt|ファイル/ディレクトリの一覧表示|
|`cp`|CoPy|ファイル/ディレクトリをコピー|
|`rm`|ReMove|ファイル/ディレクトリの削除|
|`mv`|MoVe|ファイル/ディレクトリの場所/名前の変更|
|`cat`|conCATenate|ファイルの表示|
|`less`|MORE|ファイルの表示（ページャー）|

**`cd`/`pwd`**
現在いるディレクトリのことをカレントディレクトリ（もしくはワーキングディレクトリ）という。
カレントディレクトリは`pwd`コマンドもしくは環境変数の表示で確認することができる。
```
# カレントディレクトリ（＝現在いるディレクトリ）を表示
$ pwd
/c/Users/basha

# カレントディレクトリは$PWDでも確認できる
$ echo $PWD
/c/Users/basha
```

カレントディレクトリを移動するには`cd`コマンドを利用する。
```
# 移動したいディレクトリを指定すると、
$ cd Downloads

# 現在のディレクトリが変わっている
$ pwd
/c/Users/basha/Downloads
```

ログイン直後のディレクトリをホームディレクトリといい、環境変数`$HOME`に格納されている。

Linuxでは、`/home/$USER`が一般的である。

GitBashでは、Windowsシステム内で動作するので、ホームディレクトリは`C:\ユーザー\<ユーザ名>`に相当する`/c/Users/$USERNAME`となる。
ホームディレクトリへの移動は引数なしの`cd`コマンドを発行することで可能である。
```
# 引数なしだと、ホームディレクトリに移動する
$ cd
$ pwd
/c/Users/basha

# ホームディレクトリは$HOMEという環境変数で確認できる
$ echo $HOME
/c/Users/basha
```

ディレクトリ移動時には`~`がホームディレクトリのことを指す。
パスのすべてを指定することを「絶対パス指定」という。Windowsでいうところの`cd C:\Users\Desktop`とおなじ。
```
# ディレクトリの移動時はホームディレクトリを ~/ として指定してもよい
$ cd ~/Desktop
```

カレントディレクトリを起点としてパスを指定することを「相対パス指定」という。Windowsでいうところの`cd ..\..`とおなじ。
```
# cdは複数階層（ディレクトリ配下のディレクトリ）にも移動できる
$ cd ~/Videos/Captures
$ pwd
/c/Users/basha/Videos/Captures

# ひとつ上の階層は .. で表現される
$ cd ..
$ pwd
/c/Users/basha/Videos
```

**`mkdir`**
ディレクトリを作成するコマンド。
```
$ mkdir <dir>

# -p: 存在しないディレクトリ配下のディレクトリも作成
$ mkdir -p <dir>/<dir>
```

**`ls`**
ファイル/ディレクトリの一覧を表示するコマンド。
```
$ ls

# -l: 各ファイル/ディレクトリの詳細情報を表示
$ ls -l

# -a: 隠しファイル/ディレクトリ表示
$ ls -a

# -R: ディレクトリ内を再帰的に表示
$ ls -R

# -t: 時刻でソートして表示（-trで逆順になる）
$ ls -t

# オプションは複数を一度につけることもできる
$ ls -altr
```
隠しファイルとは、ファイル名やディレクトリ名が `.` で始まるもの。 `.bashrc`ファイル や `.git`ディレクトリなどがある。


**`cp`**
ファイル/ディレクトリをコピーするコマンド。
```
$ cp <file> <file>

# -r: ディレクトリを再帰的にコピー
$ cp -r <dir> <dir>
```

`-r`は`recursive`/`recurse`で「再帰的」のことを指す。たとえば、以下のようなディレクトリ構造のとき、`cp -r sample01 copy01`とすると、`sample01`ディレクトリに含まれる`file0101`と`file0102`も含む、ということである。
`sample01`ディレクトリに他のディレクトリが存在していた場合もどうように、そのディレクトリに含まれるディレクトリやファイルなどもすべて含むということである。

```:
tmp/
|-- sample01
|   |-- file0101
|   `-- file0102
`-- sample02
    |-- file0201
    `-- file0202
```

**`rm`**
ファイル/ディレクトリを削除するコマンド。
```
$ rm <file>

# -rf: ディレクトリを再帰的に強制削除
$ rm -rf <dir>
```

`-f`は`force`で「強制的」のことを指す。
システムによっては`rm`が`rm -i`のエイリアス（ショートカットのようなもの）に指定されている場合があり、こうなっていると`-r`だけでは、そこに含まれるディレクトリやファイルの削除のたびに「消しますがいいですか？」というメッセージがいちいち表示されてしまうため、これを一気に実行するために`-f`を付与することが多い。

**`mv`**
ファイル/ディレクトリを移動/リネームするコマンド。
```
$ mv <file/dir> <file/dir>
```
`mv`は`cp`/`rm`と違って、対象がディレクトリでも再帰オプション(`-r`)は不要である。（がなぜだか、よくわからない。ポインタが変わる、ってだけなのかもしれない？）


**`cat`/`less`**
ファイルの内容を表示するコマンド。
```
# ファイルを表示
$ cat <file>

# ファイルを表示（ページャー）
$ less <file>
```

### コマンド操作練習

以下の操作を「ホームディレクトリから移動せずに実行」する。
* カレントディレクトリ配下に`tmp\sample`ディレクトリを作成
* `tmp\sample`ディレクトリを`tmp\sample01`に名称変更
* `tmp\sample01`ディレクトリにホームディレクトリの`.bashrc`をコピー
* `tmp\sample01`ディレクトリを`tmp\sample02`としてコピー
* `tmp`ディレクトリの詳細一覧を表示
* `tmp\sample01`ディレクトリを削除（`tmp`はそのまま）
* `tmp`ディレクトリを削除


## シェル操作

これもできないと死にます。
パイプやリダイレクトはコマンドを組み合わせるだけでなく、様々な他ドキュメントを読解する際にも必要なことが多くあります。

### パイプ/リダイレクト/標準入力/標準出力
|コマンド/操作|効果|
|:--:|:--:|
|`\|`|パイプ|
|`<` , `>`|リダイレクト|

**パイプ**
前のコマンドの標準出力結果を次のコマンドに引き渡す機能を持つ。パイプ経由で複数のコマンドを連結させて処理させることができる。
以降でregexという用語が出てくるが、これは正規表現のことで、ひとまずは「検索する文字列」と考えておいて問題ない。
```:パイプの使い方
$ cat <file> | grep <regex>
$ cat <file> | grep <regex> | grep <regex>
```

**リダイレクト**
コマンドへの標準入力のソースをファイルとしたり（`<`）、コマンドからの標準出力をファイルとしたり（ `>`）、と、標準入出力とファイルを連携させるときに利用する。
標準入力はキーボード入力、標準出力はディスプレイ表示のことと考えてしまって、おおよそ問題ない。
```:ファイル内を検索して別ファイルに書き出す
$ cat <file> | grep <regex> > <file>
```

`<` は、あまり使う場面がないが、`>`と逆の役割である。
```:ファイル内容をソートする
$ sort < <file>
```

`sort`は標準入力を順番に表示するコマンドのことであり、以下のように使うこともできる。
```:標準入力としてキーボード入力してみる
$ sort
zzz
iii
aaa
（ここで Ctrl-d をタイプすると、ソートされて表示される）
aaa
iii
zzz
```

`Ctrl-d` は「入力の終了」という意味で`EOF`(=End Of File)という意味でもある。（ということは覚えなくて良い）


### シェル変数と環境変数
シェル変数/環境変数は、プログラムでの変数代入と同じようなものである。シェル変数/環境変数は慣例的に大文字で利用される。

|コマンド/操作|効果|
|:--:|:--:|
|`VAR=DATA`|シェル変数をセット|
|`export VAR`|シェル変数を環境変数としてセット|
|`unset VAR`|環境変数をクリア|
|`export VAR=DATA`|環境変数をセット|
|`VAR=$(command)`|コマンド結果をシェル変数/環境変数にセット|
|`echo $VAR`|シェル変数/環境変数を表示する|

セット（代入）の際には`$`なし、参照の際には`$`あり、で利用されることに注意する。

**シェル変数**
そのシェル内で有効な変数のこと。
そのシェルから起動したコマンドには**引き継がれない**。
そのシェルで発行したコマンドの引数としてシェル変数を展開することは可能。

以下のようにシェル変数を変数展開して利用することができる
```
$ TEST_STRING=test
$ echo $TEST_STRING
test
```

そのシェルから起動されるコマンドに、シェル変数は引き継がれない
```
$ TEST_STRING=test
$ echo $TEST_STRING
test

# シェルから新しいコマンド（bash）を起動する
$ bash
# 新しいプロセス内で先ほど定義したシェル変数を確認してみる
$ echo $TEST_STRING

$
# ↑シェル変数は引き継がれないため、新しいbashプロセスでは利用できない
```


**環境変数**
そのシェル内で有効な変数のこと。
そのシェルから起動したコマンドにも**引き継がれる**。
そのシェルで発行したコマンドの引数としてシェル変数を展開することも可能

以下のように環境変数を変数展開して利用することができる
```
$ export TEST_STRING=test
$ echo $TEST_STRING
test
```

そのシェルから起動されるコマンドに、環境変数は引き継がれる
```
$ export TEST_STRING=test
$ echo $TEST_STRING
test

# シェルから新しいコマンド（bash）を起動する
$ bash
# 新しいプロセス内で先ほど定義した環境変数を確認してみる
$ echo $TEST_STRING
test

$
# ↑環境変数は引き継がるため、新しいbashプロセスでも利用できる
```

**コマンド結果をシェル変数/環境変数にセット**

```
# id は自身のユーザ状況を表示するコマンド
$ id
uid=197609(basha) gid=197609 groups=197609

# id のコマンド結果を MY_ID というシェル変数にセットする
$ MY_ID=$(id)

# シェル変数 MY_ID を表示する
$ echo $MY_ID
uid=197609(basha) gid=197609 groups=197609
```

**デフォルトで存在する主な環境変数**
`$USER`: (linuxの場合)そのユーザのユーザ名
`$USERNAME`: (GitBashの場合)そのユーザのユーザ名
`$HOME`: そのユーザのホームディレクトリ
`$HOSTNAME`: いまログインしている端末のコンピュータ名
`$LANG`: 現在設定されている言語
`$PATH`: コマンドのパス

`env` コマンドは、シェル変数と環境変数のすべてを表示する。
```
$ env
```

**文字列を指定する場合の注意**

文字列にスペースが含まれる場合は、クオーテーションで囲む。
```
$ VAR='abc def'
$ echo $VAR
abc def
```

前にセットした変数を流用することも可能
```
$ VAR1='qqq'$VAR
$ echo $VAR1
qqqabc def
```

複数行をセットする場合、参照する際に""をつける
```
$ VAR_ML='
> aaa
> bbb
> ccc
> '
$ echo "$VAR_MR"

aaa
bbb
ccc

$
```

シェル変数/環境変数は、シェルスクリプトでも利用されるし、かなり多様な使い方があるが、ひとまずこれらを覚えておけば事足りる。
もちろん私は使いこなせてません。


### コマンド履歴
ごく簡単なものだけでも効率爆上げ効果がありますです。

|コマンド/操作|略|効果|
|:--:|:--:|:--:|
|`Ctrl-p` / `Ctrl-n`|previous/next|コマンド履歴を１つずつ表示|
|`Ctrl-r` / `Ctrl-s`|reverse/search|コマンド履歴を検索|
|`history`|HISTORY|コマンド履歴の一覧を表示|
|`!`|-|history結果の添え字のコマンドを再実行|

`Ctrl-p`と`Ctrl-n`はカーソルキーの`↑`と`↓`でも代用可能。

`Ctrl-s`を利用する場合は`stty stop undef`をしておく必要がある。`.bashrc`に書いてしまうのが楽。

**コマンド履歴の検索**
プロンプトの状態で `Ctrl-r` をタイプすると以下のようになる。
```
(reverse-i-search)`':
```

ので、このまま検索したい文字列を入力すると、インクリメンタルサーチされる。
```:curlまで入力した状態
(reverse-i-search)`curl': curl -s https://yesno.wtf/api -w '%{http_code}' -o /dev/null
```

このままエンターで確定すればここに表示されているコマンドがそのまま実行される。
カーソルキーでも、そのコマンドに固定されるので、その状態で左右に動かしてコマンドの一部を修正して再実行する、などで利用する。


**`history`**
```:historyと！の使い方
# さっき打ったコマンドなんだったっけなぁ～？
$ history | grep curl
  521  curl -sSL https://github.com/bashaway.keys
  916  man curl
  917  curl --help
  927  history | grep curl

# あ、これこれ
$ !521
curl -sSL https://github.com/bashaway.keys
ssh-rsa AAAAB(...省略...)sAh+f/lz
```

## よく使いそうなやつ

個人的に覚えておくと便利なコマンド。
トラブル時の調査によく利用される。

|コマンド|略|効果|
|:--:|:--:|:--:|
|`ps`|ProceSs|プロセス一覧を表示|
|`kill`|KILL|プロセスを殺す|
|`diff`|DIFFerence|ファイルの差分を表示|
|`file`|FILE|ファイルの種別を表示|
|`clear`, `Ctrl-l`|CLEAR|ターミナルの表示をクリア|


**`ps`**
```
$ ps aux
$ ps -ef
```

**`kill`**
`ps` で応答しないプロセスを `grep` して、`kill` する。などで使うケースが個人的には多い。
```
$ kill <PID>
```

**`diff`**
```
$ diff <file> <file>
```

**`file`**
```
$ file <file>
```

**`clear`**
ターミナルの表示をクリア
`Ctrl-l`も同じ。
```
$ clear
```



# ネットワーク関連コマンド

ちょっとした動作や疎通確認に使う。

## ping/arp/route

```:疎通確認
# 継続実施（Ctrl-cで終了）
$ ping <host>

# 回数指定
$ ping -c <num> <host>

# pingペイロードサイズを指定
$ ping -s <size> <host>
```

```:arpテーブル操作
# ARPテーブルを表示
$ arp

# ARPテーブルを削除（管理者権限が必要）
$ sudo arp -d
```

```:ルーティングテーブルを表示
# すべて表示
$ route
```


## curl

> curl - transfer a URL

指定したURLにアクセスする。
ちょっとしたアクセス正常性などに利用したり、ファイルのダウンロードに利用したりする。

```:基本コマンド
$ curl https://<FQDN>/
```

```:ヘッダ/ステータスの表示
# ヘッダ/ステータス「のみ」表示
$ curl -I https://<FQDN>/

# ヘッダ/ステータス「も」表示
$ curl -i https://<FQDN>/

# ステータスコードのみ表示
$ curl -s https://yesno.wtf/api -w '%{http_code}' -o /dev/null
```

```:リダイレクト
$ curl -L https://<FQDN>/
```

```:ファイルとしてダウンロード
$ curl https://<FQDN>/ -o <FILE>
```

```:証明書エラーの無視
$ curl -k https://<FQDN>/
```

```:アクセス状況を非表示
$ curl -s https://<FQDN>/
```

```:リクエストヘッダを付与
$ curl https://<FQDN>/ \
    -H '<HEADER> <HEADER CONTENTS>'
```

```:ボディを付与
$ curl https://<FQDN>/ \
    -d '{KEY: data}'
```

## openssl

> openssl - OpenSSL command line tool

SSL/TLS関連の操作/閲覧に利用する。
個人的には証明書やチェーンの確認に利用することが多い。

```:証明書の表示
$ openssl x509 -in <cert> -text
```

```:秘密鍵の表示
$ openssl rsa -in <privkey> -text
```

```:サーバ証明書を表示
$ openssl s_client -connect <FQDN>:443
```

```:TLSバージョンを指定
$ openssl s_client -connect windowsupdate.microsoft.com:443 -tls1
```

```:ヘルプ
$ openssl help
$ openssl x509 -help
```


# ちょっと応用


## 簡易的な処理の自動化

### xargs

> xargs - build and execute command lines from standard input

標準入力を読み込んでコマンドラインを作成し実行する
標準入力から空白や改行で区切られた一連の項目を読み込み、これを引数にして、指定した `command` を繰り返す。

```
cat <<'EOF' > list.fqdn
www.google.com
windowsupdate.microsoft.com
www.github.com
EOF
```

```
cat list.fqdn | xargs curl -I
```

`xargs` の引数として `-I<文字列>` とすると、後続コマンドの任意の位置に、直前コマンドの標準出力結果をはめ込むことができる。`{}`や`%`がよく利用される。

```
cat list.fqdn | xargs -I{} openssl s_client -connect {}:443 -tls1
```

```
cat list.fqdn | xargs -I{} nslookup {}
```

### while/done

GitBashなのでlinuxで使える`watch`は使えない。

```:繰り返すコマンドを指定（パイプなどは利用不可）
COMMAND="curl -sI https://yesno.wtf/api"
```

```:１秒おきに実行
while true; do $COMMAND; sleep 1s; done | grep HTTP
```



## シェル操作（応用）


### カーソル操作

|コマンド/操作|効果|
|:--:|:--:|
|`Ctrl-a` / `Ctrl-e`|カーソルを先頭/末尾に移動|
|`Ctrl-w`|カーソル位置から前方へ単語を削除|


### foreground/background

各コマンドはそのコマンドが終了するまで、シェルの操作が奪われる。これはそのコマンドがシェル上（＝ForeGround）で動作しているため。
コマンドを動作させたままで他のコマンドを発行したい場合は、「他のターミナルを起動する」か「コマンドをバックグラウンドに送る」ことで実施できる。

|コマンド/操作|効果|
|:--:|:--:|
|`fg` / `Ctrl-c`|コマンドをForeGroundに移動/強制終了|
|`bg` / `Ctrl-z`|コマンドをBackGroundに移動/実行中断|
|`command &`|コマンドをbgで実行|
|`jobs`|実行中のbgジョブ一覧を表示|


```:fg→中断→bg→fg→強制終了
# 1000秒待つコマンドをfgで発行
$ sleep 1000

# ここで Ctrl-z をタイプする
# と、実行が中断されてプロンプトが戻ってくる
[1]+  Stopped                 sleep 1000
$

# ここでbgをタイプする
# と、bgで処理が再開する
$ bg
[1]+ sleep 1000 &
$

# ここでfgをタイプする
# と、sleepがfgにもどってくる
$ fg
sleep 1000

# ここで Ctrl-c をタイプする
# と、sleepが終了してプロンプトが戻ってくる
$ 
```

```:bg→fg→強制終了
# 1000秒待つコマンドをbgで発行する
# と、bgで処理が開始する
$ sleep 1000 &
[1] 1140

# jobsでジョブの一覧を表示させる
$ jobs
[1]+  Running                 sleep 1000 &

# ここでfgをタイプする
# と、sleepがfgにもどってくる
$ fg
sleep 1000

# ここで Ctrl-c をタイプする
# と、sleepが終了してプロンプトが戻ってくる
$ 
```

# windowsコマンド

GitBashを利用している場合はこちら。

## ping/arp/route

```:疎通確認
# 継続実施
$ ping -t <host>

# 回数指定
$ ping -n <num> <host>

# pingペイロードサイズを指定
$ ping -l <size> <host>
```

```:arpテーブル操作
# ARPテーブルを表示
$ arp -a

# ARPテーブルを削除（管理者権限が必要）
$ arp -d
```

```:ルーティングテーブルを表示
# すべて表示
$ route print

# フィルタして表示
$ route print 10.*
```

## ファイル関連

```:エクスプローラーを表示
# カレントディレクトリを開く
$ explorer .

# 相対パスでディレクトリを開く
$ explorer tmp\\sampale
```


# さいごに
とある勉強会の用途でこの資料を作成しました。

コマンドの活用方法に唯一解は存在しません。

最初は基本のコマンドだけで、初歩のオプションだけで、自然に手が動くようになることが最初の一歩でいいのです。そこから「必要と感じたら」少しずつアレンジしていけばいいし、「それ、違うよ」と言われたらその時にちゃんと調べて使い方をなおせばいいのです。
と私は考えます。