シェルを好きになりませんか？

# はじめに

本記事は、株式会社オズビジョンで 1/15 に実施した社内勉強会の資料です。
スライドモードにしようかと思いましたが、ちょっと使いにくい (スライドのサイズがうまく調整できず、画像を差し込んでも適切に表示するのが難しい) ため、通常記事として上げています。

元々は bash について LT を、というオーダーでしたが、そもそも bash というワードに夢を持ちすぎでは？と常々考えていたので、そもそもシェルとは何か、何のために学びたいのかによって道は変わる、ということをとりとめなく書きました。

# 目次

- bash とシェル
- シェルを好きになるメリット
- 社内環境の大半で使える bash のススメ
- 組み込みコマンド、標準コマンド
- 上達のために

# bash とシェル
## bash とは
### 質問
Q) bash とは何の略でしょうか？ (5s)
：
：
：
：
：
：
：
：
：
：

### 回答
A) **B**ourne **A**gain **SH**ell
`Bourne Again` という名前の付いたシェルの **一種** です。

### bash とシェル

bash ⊂ シェル

「シェル」というつもりで「bash」というと恥ずかしいことになるケースがあるので、2 つの違いは理解しよう。

## シェルとは

OS の周りをシェル (shell: 殻) のように包むプログラム群で、OS ユーザがカーネルレベルの機能を使えるようにするために提供している機能群のこと。

[Wikipedia - シェル](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%A7%E3%83%AB) には以下のように記載あり。

>シェル (英語: shell) はオペレーティングシステム (OS) のユーザーのためにインタフェースを提供するソフトウェアであり、カーネルのサービスへのアクセスを提供する。

## シェルにはほかにもこのようなものがある

※超マイナーなものは除く

- sh: UNIX 系でほぼ最古のシェル。bash の元になっている。
- csh: BSD 系でほぼ最古のシェル。
- tcsh: csh 拡張シェル。一部の maxOS デフォルト推奨シェル
- zsh: macOS Catalina からデフォルト推奨シェル
- Windows Powershell: Windows のコマンドプロンプトでシェルとして動いているもの

# シェルを好きになるメリット

OS の機能をコマンドラインベースで扱うことができるので、

- 何度でも全く同じ操作を行うことができ
- 行った内容を認識相違の発生することなく共有することができ
- 自分が行いたい操作を他者に同レベルで移管することもできる

更に、ターミナル上だけの利用では足りない場合、スクリプト化による自動化も行えるようになる。

# 社内環境の大半で使える bash のススメ

オズビジョンでは以下の環境のシェルとして bash を使える。

- 自社サービス AWS 上の EC2
- Git Bash を導入している Windows
- Mac (設定によってはデフォルトは zsh だが bash にも変更可能)

そのため、もし一つ、概念から個別シェルに踏み込むのであればまずは bash がおすすめ。

# 組み込みコマンド、標準コマンド

たとえば、監視アラート発砲内容の確認のため EC2 に ssh ログインし、特定のディレクトリの内容確認を行うとする場合。
mac なら terminal を、Windows なら putty や teraterm などでログインしたあと、以下のように作業をすると、画面上にも作業ログが出るし、指定したディレクトリにもログが出る。

※`${HOSTNAME}` は SRE が各サーバにつけてくれているタグのようなもの。

## 実行内容

```
(echo ${HOSTNAME}; date; df; date) | tee /tmp/operation_$( date +"%Y%m%d%H%M%S" ).txt
ls -l /tmp/operation*
exit
```

## ログの内容

勿論作業時に 1 行目のコマンド実行後に表示されるものと等しい。

```
+ echo ip-10-0-16-219
ip-10-0-16-219
+ date
2020年  1月 15日 水曜日 13:07:49 JST
+ cd /tmp
+ pwd
/tmp
+ ls --color=auto -l
合計 276
-rw-r--r-- 1 root   root       348  1月 15 12:21 1.txt
srwx------ 1 mongod mongod       0 11月  6 14:22 mongodb-27017.sock
-rw-r--r-- 1 root   root       353  1月 15 13:03 operation_20200115130308.txt
-rw-r--r-- 1 root   root       119  1月 15 13:05 operation_20200115130516.txt
-rw-r--r-- 1 root   root       541  1月 15 13:05 operation_20200115130523.txt
-rw-r--r-- 1 root   root       620  1月 15 13:05 operation_20200115130547.txt
-rw-r--r-- 1 root   root       699  1月 15 13:05 operation_20200115130551.txt
-rw-r--r-- 1 root   root       778  1月 15 13:05 operation_20200115130559.txt
-rw-r--r-- 1 root   root       857  1月 15 13:07 operation_20200115130716.txt
-rw------- 1 deploy xxxxxxx 249247  1月  7 11:34 release.zip
+ date
2020年  1月 15日 水曜日 13:07:49 JST
```

## 利用コマンド

この 3 行でいろいろなコマンドを使っているが、実際にはそれらは以下の 2 つに分けられる。

- 組み込み機能
- その他コマンド

コマンド|組み込み機能 or その他
:--|:--
echo|組み込み機能
date|その他
df|その他
tee|その他
ls|その他
exit|組み込み機能

組み込みコマンドかそうでないかは基本的には `type <コマンド名>` で判別可能。
ただしエイリアスが張られている場合にはうまく確認できないこともあるので、その場合は `help` で表示されるものかどうかを確認するとよい。

```terminal
$ type echo
echo はシェル組み込み関数です
$ type date
date は /bin/date です
$ help | grep -w echo; echo $?
 echo [-neE] [arg ...]                                                                                time [-p] pipeline
0

$ type ls
ls は `ls --color=auto' のエイリアスです
$ help | grep -w ls; echo $?
1
```

## 組み込みコマンドとその他の違い
### 組み込みコマンド
bash そのものに組み込まれているので、環境変数の PATH に依存しない。
bash のバージョンにより動作が変わる。

### その他コマンド
提供元も配置場所もバラバラ。自作することもできる。(ex. remoteexe など)
環境変数 PATH に含まれる先に配置することで、名称指定で呼び出せるようにしている。
PATH が通っていない環境ではフルパスで指定しないと動かすことが出来ない。また、対象バイナリに実行権限も必要になる。

どこでも使われているようなもの (date とか) なら良いが、マイナーコマンドや自作コマンドを前提に業務を組み立てると、現場を移動したときとかに泣くことになる。(オズビジョンではあまり該当しないかも。)

中で組み込みコマンドが使われることも多い (バイナリの場合でも C とかでシステムコールが使われて結局組み込みコマンドと同じところが参照されていたりすることもある) ので、結局 bash やカーネルバージョンに影響を受けることも多い。

# 上達のために
## まず自分が何のためにシェルを使うのか考える

以下のようなレベル・分野に応じて求められることも知る必要があることも変わる

- ターミナル上での作業の効率化
- 開発・デバッグ作業の効率化
- インフラのメンテナンス
- コアコマンドのコミッタになるために知識を付けたい
- OS コントリビュータになりたい

## 伸ばせる分野
### 組み込みコマンド
(頻出するものだけで良いとは思う) ので知る、覚える　※独断と偏見

- cd
- echo
- exit
- `.`
- time
- set
- history
- kill
- read
- `:`

### その他コマンド
特に自業務で頻出するその他コマンドを覚える、知る、調べられるようになる　※独断と偏見

- ls
- date
- grep, egrep
- ssh
- aws
- vi, vim, view
- cat
- jq
- cut
- awk, sed

### 特別枠：勉強会 FB

- man
    - 困ったら引きましょう

### 変数展開

- ブレース展開
- 変数内文字列置換

### 構文 - ワンライナーとして使うレベル

- test
- if-then-[elif-then-]fi
- while-do-done
- for-do-done

### 構文 - スクリプト言語として使うレベル

- Shebang 行
- 簡単な構文(実際にはこれらも組み込みコマンド)　※独断と偏見
    - case-esac
    - function

### 開発・デバッグに使えるその他コマンドを知る

- curl
- wget
- ps

### インフラ面の情報を得るためのその他コマンドを知る

- 再掲だけど aws であれば aws (aws cli) は外せない
- df, vmstat, sar, lsof, top, uptime, free など
- netstat, iostat, nm キリなし

### コアコマンド、OS への貢献レベル

- 定義ファイルの切り出し、リモートシェル、サブシェル、プロセス管理
- ロック機構 (trap や flock)、init 処理の仕組み、daemon の作り方...

など踏み込む場所は増えていく

## 機会があれば

簡単な組み込みコマンドとその他コマンドの勉強会などまたやろうと思います。


# 謝辞

- [Bashの邪悪なコマンド9選](https://qiita.com/rana_kualu/items/be32f8302017b7aa2763)
    - 本記事が社内エンジニアの間でちょっとバズり、Bash について LT してほしいというオーダーがあったため。