【シェルスクリプト③】バックアップを取得するシェルスクリプト

# なぜこのシェルスクリプトを・・・？
モジュールを適用する前に、対象の階層を全てバックアップする必要があるため、作成しました。

動きとしては下記です。
① 引数でどの対象をバックアップするか決める。
② 対象をアーカイブ化する。
③ アーカイブ化したものをZIP化する。

引数は、別のシェルからユーザーに選択させる。（実質引数は、固定になる。）

# シェルスクリプトの内容
実行環境：CentOS Linux 7 (Core)

```shell:BackUp.sh
#!/bin/bash
# /*-------------------------------------------------------------------------*/
# /*変数定義                                                                 */
# /*-------------------------------------------------------------------------*/

# バックアップ先を変数に格納
BACKUP_MAIN="/work/test/BackUp/main/"
BACKUP_BRANCH="/work/test/BackUp/branch/"

# 定義場所を変数に格納
MAIN="/work/test/Def/main/"
BRANCH="/work/test/Def/branch/"

# リターンコード変数の初期設定
RC1=""
RC2=""

# /*-------------------------------------------------------------------------*/
# /*バックアップ取得                                                         */
# /*-------------------------------------------------------------------------*/

# シェルの第一引数を基にバックアップ対象を判断(引数は別シェルで選択させるようにする)
echo ""$1"のバックアップを取得します。"
echo "-------------------------------------------------------------"

# バックアップ対象をパターンごとに分けて分岐させる(case文)
case $1 in

    # バックアップ対象が "MAIN" の場合
    "MAIN")

           # バックアップ対象をアーカイブする（コマンド結果表示は、"/dev/null"で非表示）
           tar chf "$BACKUP_MAIN"main_bk.tar "$MAIN" > /dev/null 2>&1

           # リターンコードでアーカイブ処理が正常に行われたか判断（条件分岐(if文)で実施）
           RC1=$?
            if [[ $RC1 -eq 0 ]]; then

             # アーカイブ処理が正常終了ならば、ZIP化を実施（コマンド結果表示は、"/dev/null"で非表示）
             gzip -f "$BACKUP_MAIN"main_bk.tar > /dev/null 2>&1

             # リターンコードでZIP処理が正常に行われたか判断（条件分岐(if文)で実施）
             RC2=$?
              if [[ $RC2 -eq 0 ]]; then

               # ZIP処理が正常終了ならば、対象ZIPファイルを表示
               cd "$BACKUP_MAIN"
               ls -l main_bk.tar.gz

              # ZIP処理が異常終了ならば、失敗をユーザーにお知らせ
              else
               echo "(MAIN)-ZIP化に失敗"
              fi

            # アーカイブ処理が異常終了なら、ZIP処理を行わずに失敗をユーザーにお知らせ
            else
             echo "(MAIN)-アーカイブに失敗"  
            fi
           ;;

  # バックアップ対象が "BRANCH" の場合
  "BRANCH")

           # バックアップ対象をアーカイブする（コマンド結果表示は、"/dev/null"で非表示）
           tar chf "$BACKUP_BRANCH"branch_bk.tar "$BRANCH" > /dev/null 2>&1

           # リターンコードでアーカイブ処理が正常に行われたか判断（条件分岐(if文)で実施）
           RC1=$?
            if [[ $RC1 -eq 0 ]]; then

             # アーカイブ処理が正常終了ならば、ZIP化を実施（コマンド結果表示は、"/dev/null"で非表示）
             gzip -f "$BACKUP_BRANCH"branch_bk.tar > /dev/null 2>&1

             # リターンコードでZIP処理が正常に行われたか判断（条件分岐(if文)で実施）
             RC2=$?
              if [[ $RC2 -eq 0 ]]; then

               # ZIP処理が正常終了ならば、対象ZIPファイルを表示
               cd "$BACKUP_BRANCH"
               ls -l branch_bk.tar.gz

              # ZIP処理が異常終了ならば、失敗をユーザーにお知らせ
              else
               echo "(BRANCH)-ZIP化に失敗"
              fi

            # アーカイブ処理が異常終了なら、ZIP処理を行わずに失敗をユーザーにお知らせ
            else
             echo "(BRANCH)-アーカイブに失敗"  
            fi
           ;;

         # シェルの第一引数が想定外の引数だった場合、ユーザーにお知らせ
         *)
           echo "引数が間違っています。"
           RC1=1
           RC2=1
           ;;
esac

# /*-------------------------------------------------------------------------*/
# /* 終了処理                                                                */
# /*-------------------------------------------------------------------------*/

# リターンコードを基に処理が正常終了したか判断（条件分岐(if文)で実施）
if [[ $RC1 -eq 0 && $RC2 -eq 0 ]]; then

# 正常終了の場合、正常終了をユーザーにお知らせし、リターンコード０で終了
 echo "-------------------------------------------------------------"
 echo ""$1"のバックアップ取得がが正常終了しました。"
 exit 0

# 異常終了の場合、異常終了をユーザーにお知らせし、リターンコード１で終了
else
 echo "-------------------------------------------------------------"
 echo ""$1"のバックアップ取得が異常終了しました。"
 exit 1
fi
```
<font color="Red">修正参考：@ko1nksm 作</font>
```shell:BackUp.sh
#!/bin/bash

# バックアップ先ディレクトリ
BACKUP_DIR=/"work/test/BackUp"
# 定義ディレクトリ
DEF_DIR="/work/test/Def/"

backup() {
  case $1 in
    MAIN)
      archive="$BACKUP_DIR/main/main_bk"
      dest="$DEF_DIR/main"
      ;;
    BRANCH)
      archive="$BACKUP_DIR/branch/branch_bk"
      dest="$DEF_DIR/branch"
      ;;
    *)
      echo "引数が間違っています。"
      return 1
  esac

  if tar chf "${archive}.tar" "$dest" >/dev/null; then
    if gzip -f "${archive}.tar" >/dev/null; then
      cd "$dest"
      ls -l "${archive##*/}.tar.gz"
      return 0
    else
      echo "($1)-ZIP化に失敗"
    fi
  else
    echo "($1)-アーカイブに失敗"
  fi
  return 1
}

echo "$1のバックアップを取得します。"
echo "-------------------------------------------------------------"
if backup "$1"; then
  echo "-------------------------------------------------------------"
  echo "$1のバックアップ取得が正常終了しました。"
  exit 0
else
  echo "-------------------------------------------------------------"
  echo "$1のバックアップ取得が異常終了しました。"
  exit 1
fi
```
# シェルスクリプトの実行結果

バックアップ対象ファイル一覧
```text:
[root@localhost：/work/test/Def]# ls -lR
.:
合計 0
drwxr-xr-x. 2 root root 42 10月 15 11:38 branch
drwxr-xr-x. 2 root root 42 10月 15 11:39 main

./branch:
合計 0
-rw-r--r--. 1 root root 0 10月 15 11:38 test.file1
-rw-r--r--. 1 root root 0 10月 15 11:38 test.file2

./main:
合計 0
-rw-r--r--. 1 root root 0 10月 15 11:38 test.file3
-rw-r--r--. 1 root root 0 10月 15 11:39 test.file4

```

バックアップ先
```text:
[root@localhost：/work/test/BackUp]# ls -lR
.:
合計 0
drwxr-xr-x. 2 root root 6 10月 15 14:32 branch
drwxr-xr-x. 2 root root 6 10月 15 14:33 main

./branch:
合計 0

./main:
合計 0

```

シェルを実行（試しに引数を "MAIN" にする）
```text:
[root@localhost：/work/test]# ./BackUp.sh MAIN
```

結果（バックアップ取得）
```text:
MAINのバックアップを取得します。
-------------------------------------------------------------
-rw-r--r--. 1 root root 187 10月 15 14:43 main_bk.tar.gz
-------------------------------------------------------------
MAINのバックアップ取得がが正常終了しました。
```

取得したバックアップファイルの中身を確認（ちゃんと取得できている）
```text:
[root@localhost：/work/test/BackUp]# ls -lR
.:
合計 0
drwxr-xr-x. 2 root root  6 10月 15 14:32 branch
drwxr-xr-x. 2 root root 28 10月 15 14:43 main

./branch:
合計 0

./main:
合計 4
-rw-r--r--. 1 root root 187 10月 15 14:43 main_bk.tar.gz

[root@localhost：/work/test/BackUp]# gzip -cd ./main/main_bk.tar.gz | tar tf -
work/test/Def/main/
work/test/Def/main/test.file3
work/test/Def/main/test.file4

```

アーカイブが失敗した場合（失敗１）
```test:BackUp.sh
MAINのバックアップを取得します。
-------------------------------------------------------------
(MAIN)-アーカイブに失敗
-------------------------------------------------------------
MAINのバックアップ取得が異常終了しました。
```

ZIP化が失敗した場合（失敗２）
```test:
MAINのバックアップを取得します。
-------------------------------------------------------------
(MAIN)-ZIP化に失敗
-------------------------------------------------------------
MAINのバックアップ取得が異常終了しました。
```

引数が想定外の値だった場合（失敗３）
```test:
xxxのバックアップを取得します。
-------------------------------------------------------------
引数が間違っています。
-------------------------------------------------------------
xxxのバックアップ取得が異常終了しました。
```

# 今回使用したコマンドや構文について
:::note warn
clear コマンド
画面上をクリアするコマンド

\~~参考リンク~~
[【 clear 】コマンド――端末をクリアする](https://atmarkit.itmedia.co.jp/ait/articles/1903/14/news026.html)
:::

:::note warn
case文
文字列をパターンごとに場合分けして、処理を分岐させる。

\~~参考リンク~~
[【シェルスクリプト】（条件分岐）case文](https://www.server-memo.net/shellscript/case.html)
:::

:::note warn
tar コマンド
複数のファイルを1つにまとめて "アーカイブファイル" を作成／展開するコマンド

\~~参考リンク~~
[【 tar 】コマンド――アーカイブファイルを作成する／展開する](https://atmarkit.itmedia.co.jp/ait/articles/1608/15/news015.html)
:::

:::note warn
gzip コマンド
ファイルを圧縮/解凍するコマンドであり、１つのファイルに対し実行する。

\~~参考リンク~~
[【 gzip 】コマンド／【 gunzip 】コマンド――ファイルを圧縮する／伸張する](https://atmarkit.itmedia.co.jp/ait/articles/1608/09/news018.html)
:::

:::note warn
if文(条件分岐)
条件によって処理を分岐する構文

\~~参考リンク~~
[if 文と test コマンド](https://shellscript.sunone.me/if_and_test.html)
:::

:::note warn
条件式の評価 [[~]]
条件式を評価し、その結果によって終了ステータスを返す。
testコマンドとは若干違う。

\~~参考リンク~~
[シェルスクリプト[[]]のススメ](https://blog.denet.co.jp/post/#if%E6%96%87%E3%81%8A%E4%BE%9B_%E3%81%A8)
:::