【備忘録】シェルスクリプトについて学ぶ

## はじめに

[Linuxの基本操作](https://qiita.com/yuk1_sys/items/c03f77e516edbe9f6b32)、[シェルのカスタマイズ](https://qiita.com/yuk1_sys/items/e16555ee86d6e06ef0b9) について前回記事にしました。

今回は前回までで学んだ知識を使ってシェルスクリプトを実行する方法についてまとめます。

#### 対象読者

- シェルスクリプトの基礎を学びたい方
- bash によるシェルスクリプトの実行を試したい方


## シェルスクリプトとは

シェルスクリプトとは、Linux上で実行するために一連のコマンドが並んだプログラムを指し、コマンドと if 文、for 文などのプログラム文を組み合わせて処理を行います。

ただし、シェルの種類によってコマンドやプログラム文の書き方が異なる点は注意が必要です。（今回は bash の書き方でまとめています）

下記はシェルスクリプトの一例です。

```bash:例（拡張子は .sh）
#!/bin/bash

ls
cat file.txt
echo 'Hello'
date
```

1 行目の `#!` はシバンといい、どのシェルを利用するのかを指定することができます。
ここでは `/bin/bash` と指定されているので、bash を実行するコマンドということになります。

このファイルを指定して実行すると、/bin/bash ファイル名.sh が内部では実行され、上から順番に処理が行われます。



## プログラムの実行と停止

### プログラムの実行

プログラムを実行するには chmod を用いてファイルに実行権限をつけます。

```bash:実行例
# 所有ユーザに全権限を付与する
# 所有グループとその他グループには読み込み権限と実行権限を付与する
chmod 755 file.sh
```

また、実行するファイルを指定する際は、相対パスと絶対パスの 2 通りがあります。

実行する際どちらでファイル指定しても問題ありませんが、相対パスだと呼び出し元ファイルが移動した場合に機能しなくなるので、絶対パスにしておいた方が比較的安全かもしれません。

```text:実行例（相対パスで実行）
[root@localhost ~]$ ./test.sh
```

```text:実行例（絶対パスで実行）
[root@localhost ~]$ /home/user/test.sh
```


### プログラムの停止

プログラムを実行途中で停止するには、ctrl + c を用います。

```text:実行例（./test.sh を実行後 ctrl+c を押下）
[root@localhost ~]$ ./test.sh
^C
```



## プログラムが実行されたときのプロセスについて

`./test.sh` のようにシェルスクリプトを実行すると、ログインユーザが利用しているシェルが子プロセスであるシェルを作成し、そのシェル上でシェルスクリプトが実行されます。（シェルシェルうるさい ←）

そのため、親子のプロセスで値を共有する場合、シェル変数では値を引き継げないので環境変数として export する... といった作業が必要になってきます。
（くわしくは [シェル変数と環境変数について](https://qiita.com/drafts/82fe6386398eafad2e98/edit#シェル変数と環境変数について) に記述）


### . コマンド 、 source コマンド

子プロセスを立ち上げずに現在利用しているプロセス上でシェルスクリプトを立ち上げたい場合、`.` コマンド、もしくは `source` コマンドを利用します。

```text:実行例(. で実行)
[root@localhost ~]$ . ./test.sh
```

```text:実行例(source で実行)
[root@localhost ~]$ source ./test.sh
```





## シェル変数と環境変数について

シェル変数と環境変数は有効範囲が異なります。

### シェル変数

利用中のシェルでのみ有効な変数。

`VAR="sample text"` のように、変数に代入された値はシェル変数として扱われます。


### 環境変数

シェルから立ち上げられた子プロセスでもコピーして利用できる変数。

`export 変数名` とすることで、変数をシェル変数から環境変数にできます。

```text:実行例（定義された変数を export する）
[root@localhost ~]$ name="Taro"
[root@localhost ~]$ export name
```

```text:実行例（変数の宣言と同時に export する）
[root@localhost ~]$ export user="Jiro"
```


### シェル変数、環境変数の削除 （unset コマンド）

シェル変数、環境変数を削除するには、unset コマンドを用います。

```text:実行例
[test@localhost ~]$ name="test"
[test@localhost ~]$ echo $name
test
[test@localhost ~]$ unset name
[test@localhost ~]$ echo $name
[test@localhost ~]$ 
```


### 環境変数、シェル変数、関数などの一覧を表示（set コマンド）

環境変数、シェル変数、関数などの一覧を表示するには、set コマンドを用います。

set コマンドは実行すると膨大なテキストが表示されます。
そのため、less コマンドを合わせて実行して検索をかけると欲しい情報が見つけやすいと思います。

```text:実行例
[root@localhost ~]$ set | less
```


### 環境変数の一覧を表示（printenv コマンド）

環境変数の一覧を表示するには、printenv コマンドを用います。


### シェル実行前に環境変数を一時的に設定（env コマンド）

環境変数を一時的に設定した状態でシェルを実行するには、env コマンドを用います。

引数なしで env コマンドを実行すると、環境変数一覧が表示されます。

```text:実行例
[root@localhost ~]$ env number=12 ./a.sh
12
```



## さまざまな環境変数

デフォルトで定義されている環境変数について触れていきます。

| 環境変数 | 意味 |
|:-|:-|
| HOME | ホームディレクトリを表示 |
| LANG | 使用している言語を表示 |
| PWD | 現在ユーザがいるディレクトリ（カレントディレクトリ）を表示 |
| USER | ログインしているユーザ名 |
| PATH | コマンドの実行ファイルを格納するコマンド検索パス |


### PATH について

環境変数の PATH には、コマンドの実行ファイルが格納されているディレクトリのパスが定義されています。

PATH に定義されているディレクトリに格納されているファイルは、実行時にパスを指定する必要がなくなります。

```text:実行例（前提として、new_script.sh が PATH で定義されているディレクトリに格納されている状態）
[root@localhost ~]$ echo $PATH
/home/ec2-user/.local/bin:/home/ec2-user/bin: ...
[root@localhost ~]$ which new_script.sh
~/.local/bin/new_script.sh
[root@localhost ~]$ new_script.sh
new_script が起動しました。
```

また、以下のように PATH に新しいディレクトリを追加することも可能です。

```text:実行例
[root@localhost ~]$ PATH="$PATH:/home/ec2-user/new_dir"
```



## シェルスクリプトのコメント文

コメント文とは、説明のために記述するが実行はされない文のことを指します。

\# より右の部分は実行されないため、何を記述しても良いです。
下記の例だと echo コマンドと ls コマンド だけ実行されます。

```bash:例
#!/bin/bash

# Hello Worldと表示する
echo 'Hello World'

ls # ファイル一覧を表示する
```



## 変数

値を別名で格納するために利用します。
変数名 = ◯ ◯ として値を格納し、$変数名 でアクセスします。

下記では、name に Taro という文字列が格納され、$ でアクセスした結果、画面上に Taro と表示されます。

```bash:例
name=Taro
echo $name
```



## コマンド一覧

[Linuxの基本操作](https://qiita.com/yuk1_sys/items/c03f77e516edbe9f6b32)、[シェルのカスタマイズ](https://qiita.com/yuk1_sys/items/e16555ee86d6e06ef0b9) で触れたコマンド以外をこちらで扱います。


### less コマンド

ファイルの中身を編集はせずに表示だけして、画面操作するコマンド

##### less実行後のコマンドライン操作（man と同じ）

| 操作キー | 意味 |
|:-|:-|
| q | コマンドを終了する |
| d | 画面を半分進める |
| u | 画面を半分戻る |
| f | 1 画面進める |
| b | 1 画面戻る |
| g | 頭まで移動する |
| G | 末まで移動する |
| 100G | 100行目まで移動する |
| / | 下方向に検索（n:下方向に次のものを検索、N:上方向に次のものを検索） |
| ? | 上方向に検索（n:上方向に次のものを検索、N:下方向に次のものを検索） |


### 上記で触れたコマンド一覧

##### シェルスクリプト実行

- [. コマンド 、 source コマンド](https://qiita.com/drafts/82fe6386398eafad2e98/edit#-コマンド--source-コマンド)


##### 環境変数周り

- [シェル変数、環境変数の削除 （unset コマンド）](https://qiita.com/drafts/82fe6386398eafad2e98/edit#シェル変数環境変数の削除-unset-コマンド)
- [環境変数、シェル変数、関数などの一覧を表示（set コマンド）](https://qiita.com/drafts/82fe6386398eafad2e98/edit#環境変数シェル変数関数などの一覧を表示set-コマンド)



## おわりに

次回は if や for といった命令文を扱っていきます。
出来ることが増えてきて楽しいな 🤗