【シェルスクリプト④】バックアップを世代管理するシェルスクリプト

# なぜこのシェルスクリプトを・・・？
バックアップを3世代で管理する必要があったため、作成しました。

動きとしては、下記です。
① 現在の世代管理状況を表示する。
② 引数でどの対象を再編処理するか決める。
③ 対象を世代管理する。
④ 再編処理後の状況を表示する。

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

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

```shell:gene.sh
#!/bin/bash

# 画面クリア
clear

# /*-------------------------------------------------------------------------*/
# /*変数定義                                                                 */
# /*-------------------------------------------------------------------------*/

GENE_DIR="/work/test/BackUp/"

# /*-------------------------------------------------------------------------*/
# /*関数定義                                                                 */
# /*-------------------------------------------------------------------------*/

# 再編処理用のシェル関数
gene() {

  # 再編処理の対象を判断(case分岐)
  case $1 in
    MAIN)
      gene1="${GENE_DIR}main/main_bk.tar.gz"
      gene2="${GENE_DIR}main/main_bk.tar.gz.ver1"
      gene3="${GENE_DIR}main/main_bk.tar.gz.ver2"
      ;;
    BRANCH)
      gene1="${GENE_DIR}branch/branch_bk.tar.gz"
      gene2="${GENE_DIR}branch/branch_bk.tar.gz.ver1"
      gene3="${GENE_DIR}branch/branch_bk.tar.gz.ver2"
      ;;
    *)
      echo "引数が間違っています。"
      return 1
  esac

  # 現在の世代管理状況表示
  echo "-------------------------------------------------------------"
  echo "--再編前-----------------------------------------------------"
  ls -l ${gene1%/*}*
  echo "-------------------------------------------------------------"
  echo "-------------------------------------------------------------"

  # 3世代目ファイル削除処理(ファイルの有無も確認)
  if [[ -e $gene3 ]]; then
    rm $gene3 > /dev/null 2>&1
    if [[ $? -eq 0 ]]; then
      echo "$gene3 --> 削除 "
    else
      echo "${gene3}の削除に失敗"
      return 1
    fi
  else
    echo "${gene3}は、存在しない為、再編をスキップします。"
  fi

  # 2世代目ファイル再編処理(ファイルの有無も確認)
  if [[ -e $gene2 ]]; then
    mv -f $gene2 $gene3 > /dev/null 2>&1
    if [[ $? -eq 0 ]]; then
      echo "$gene2 --> $gene3 "
    else
      echo "$gene2 --> ${gene3}の再編に失敗"
      return 1
    fi
  else
    echo "${gene2}は、存在しない為、再編をスキップします。"
  fi

  # 1世代目ファイル再編処理(ファイルの有無も確認)
  if [[ -e $gene1 ]]; then
    mv -f $gene1 $gene2 > /dev/null 2>&1
    if [[ $? -eq 0 ]]; then
      echo "$gene1 --> $gene2 "
    else
      echo "$gene1 --> ${gene2}の再編に失敗"
      return 1
    fi
  else
    echo "${gene1}は、存在しない為、再編をスキップします。"
  fi

  # 再編後の世代管理状況表示
  echo "-------------------------------------------------------------"
  echo "--再編後-----------------------------------------------------"
  ls -l ${gene1%/*}*
  echo "-------------------------------------------------------------"

  return 0
}


# /*-------------------------------------------------------------------------*/
# /* 再編処理開始(3世代ローテーション)                                       */
# /*-------------------------------------------------------------------------*/

echo "$1の再編処理を実施します。(３世代ローテーション)"

if gene $1; then
  echo "-------------------------------------------------------------"
  echo "$1の世代管理が正常終了しました。"
  exit 0
else
  echo "-------------------------------------------------------------"
  echo "$1の世代管理が異常終了しました。"
  exit 1
fi
```
<font color="Red">※ 下記は、改修前のシェル</font>
```shell:gene.sh
#!/bin/bash

# 画面クリア
clear

# /*-------------------------------------------------------------------------*/
# /*変数定義                                                                 */
# /*-------------------------------------------------------------------------*/

# リターンコード(変数)の初期化
RC1=""
RC2=""
RC3=""

# バックアップ階層を変数に代入
BACKUP_MAIN="/work/test/BackUp/main/"
BACKUP_BRANCH="/work/test/BackUp/branch/"

# /*-------------------------------------------------------------------------*/
# /* 世代管理(3世代管理)                                                     */
# /*-------------------------------------------------------------------------*/


echo ""$1"の再編処理を実施します。(３世代ローテーション)"
echo "-------------------------------------------------------------"

# 再編処理対象をパターンごとに分けて分岐させる(case文)
case $1 in

    # 再編処理対象が "MAIN" の場合
    "MAIN")

           # 再編前に状態を表示する
           echo "--再編前-----------------------------------------------------"
           ls -l "$BACKUP_MAIN"
           echo "-------------------------------------------------------------"
           echo "-------------------------------------------------------------"

           # 3世代目のファイルの有無を確認(if分岐)
           if [[ -f "$BACKUP_MAIN"main_bk.tar.gz.ver2 ]]; then

            # 3世代目が存在する場合、3世代目のファイルを削除
            rm "$BACKUP_MAIN"main_bk.tar.gz.ver2 > /dev/null 2>&1

            # 削除が正常終了したか判断する(if分岐)
            RC1=$?
             if [[ $RC1 -eq 0 ]]; then

              # 削除が正常終了ならば、ユーザーに削除通知
              echo "main_bk.tar.gz.ver2 --> 削除 "

             # 削除が異常終了ならば、ユーザーに失敗通知
             else
              echo "main_bk.tar.gz.ver2の削除に失敗"
             fi

           # 3世代目が存在しない場合、再編をスキップ
           else
            echo "main_bk.tar.gz.ver2は、存在しない為、再編をスキップします。"
            RC1=0
           fi
 
           # 2世代目のファイルの有無を確認(if分岐)
           if [[ -f "$BACKUP_MAIN"main_bk.tar.gz.ver1 ]]; then

            # 2世代目が存在する場合、2世代目ファイルを3世代目ファイルにリネーム
            mv -f "$BACKUP_MAIN"main_bk.tar.gz.ver1 "$BACKUP_MAIN"main_bk.tar.gz.ver2 > /dev/null 2>&1

            # リネームが正常終了したか判断する(if分岐)
            RC2=$?
             if [[ $RC2 -eq 0 ]]; then

              # リネームが正常終了ならば、ユーザーにリネーム通知
              echo "main_bk.tar.gz.ver1 --> main_bk.tar.gz.ver2 "

             # リネームが異常終了ならば、ユーザーに失敗を通知
             else
              echo "main_bk.tar.gz.ver1 --> main_bk.tar.gz.ver2の再編に失敗"
             fi

           # 2世代目が存在しない場合、再編をスキップ
           else
            echo "main_bk.tar.gz.ver1は、存在しない為、再編をスキップします。"
            RC2=0
           fi

           # 1世代目のファイルの有無を確認(if分岐)
           if [[ -f "$BACKUP_MAIN"main_bk.tar.gz ]]; then

            # 1世代目が存在する場合、1世代目ファイルを2世代目ファイルにリネーム
            mv -f "$BACKUP_MAIN"main_bk.tar.gz "$BACKUP_MAIN"main_bk.tar.gz.ver1 > /dev/null 2>&1

            # リネームが正常終了したか判断する(if分岐)
            RC3=$?
             if [[ $RC3 -eq 0 ]]; then

              # リネームが正常終了ならば、ユーザーにリネーム通知
              echo "main_bk.tar.gz --> main_bk.tar.gz.ver1 "

            # リネームが異常終了ならば、ユーザーに失敗を通知
            else
              echo "main_bk.tar.gz --> main_bk.tar.gz.ver1の再編に失敗"
             fi

           # 1世代目が存在しない場合、再編をスキップ
           else
            echo "main_bk.tar.gzは、存在しない為、再編をスキップします。"
            RC3=0 
           fi

           # 再編後に状態を表示する
           echo "-------------------------------------------------------------"
           echo "--再編後-----------------------------------------------------"
           ls -l "$BACKUP_MAIN"
           echo "-------------------------------------------------------------"
           ;;

  # 再編処理対象が "BRANCH" の場合
  "BRANCH")
           # 再編前に状態を表示する
           echo "--再編前-----------------------------------------------------"
           ls -l "$BACKUP_BRANCH"
           echo "-------------------------------------------------------------"
           echo "-------------------------------------------------------------"

           # 3世代目のファイルの有無を確認(if分岐)
           if [[ -f "$BACKUP_BRANCH"branch_bk.tar.gz.ver2 ]]; then

            # 3世代目が存在する場合、3世代目のファイルを削除
            rm "$BACKUP_BRANCH"branch_bk.tar.gz.ver2 > /dev/null 2>&1

            # 削除が正常終了したか判断する(if分岐)
            RC1=$?
             if [[ $RC1 -eq 0 ]]; then

              # 削除が正常終了ならば、ユーザーに削除通知
              echo "branch_bk.tar.gz.ver2 --> 削除 "

             # 削除が異常終了ならば、ユーザーに失敗通知
             else
              echo "branch_bk.tar.gz.ver2の削除に失敗"
             fi

           # 3世代目が存在しない場合、再編をスキップ
           else
            echo "branch_bk.tar.gz.ver2は、存在しない為、再編をスキップします。"
            RC1=0
           fi

           # 2世代目のファイルの有無を確認(if分岐)
           if [[ -f "$BACKUP_BRANCH"branch_bk.tar.gz.ver1 ]]; then

            # 2世代目が存在する場合、2世代目ファイルを3世代目ファイルにリネーム
            mv -f "$BACKUP_BRANCH"branch_bk.tar.gz.ver1 "$BACKUP_BRANCH"branch_bk.tar.gz.ver2 > /dev/null 2>&1

            # リネームが正常終了したか判断する(if分岐)
            RC2=$?
             if [[ $RC2 -eq 0 ]]; then

              # リネームが正常終了ならば、ユーザーにリネーム通知
              echo "branch_bk.tar.gz.ver1 --> branch_bk.tar.gz.ver2"

             # リネームが異常終了ならば、ユーザーに失敗を通知
             else
              echo "branch_bk.tar.gz.ver1 --> branch_bk.tar.gz.ver2の再編に失敗"
             fi

           # 2世代目が存在しない場合、再編をスキップ
           else
            echo "branch_bk.tar.gz.ver1は、存在しない為、再編をスキップします。"
            RC2=0
           fi

           # 1世代目のファイルの有無を確認(if分岐)
           if [[ -f "$BACKUP_BRANCH"branch_bk.tar.gz ]]; then

            # 1世代目が存在する場合、1世代目ファイルを2世代目ファイルにリネーム
            mv -f "$BACKUP_BRANCH"branch_bk.tar.gz "$BACKUP_BRANCH"branch_bk.tar.gz.ver1 > /dev/null 2>&1

            # リネームが正常終了したか判断する(if分岐)
            RC3=$?
             if [[ $RC3 -eq 0 ]]; then

              # リネームが正常終了ならば、ユーザーにリネーム通知
              echo "branch_bk.tar.gz --> branch_bk.tar.gz.ver1"

             # リネームが異常終了ならば、ユーザーに失敗を通知
             else
              echo "branch_bk.tar.gz --> branch_bk.tar.gz.ver1の再編に失敗"
             fi

           # 1世代目が存在しない場合、再編をスキップ
           else
            echo "branch_bk.tar.gzは、存在しない為、再編をスキップします。"
            RC3=0
           fi

           # 再編後に状態を表示する
           echo "--再編後-----------------------------------------------------"
           ls -l "$BACKUP_BRANCH"
           echo "-------------------------------------------------------------"
           ;;

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

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


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

 # 正常終了の場合、正常終了をユーザーにお知らせし、リターンコード０で終了
 echo "-------------------------------------------------------------"
 echo ""$1"の世代管理が正常終了しました。"
 exit 0

# 異常終了の場合、異常終了をユーザーにお知らせし、リターンコード１で終了
else
 echo "-------------------------------------------------------------"
 echo ""$1"の世代管理が異常終了しました。"
 exit 1
fi
```
# シェルスクリプトの実行結果

バックアップの状況
```text:
[root@localhost：/work/test/BackUp]# ls -lR
.:
合計 0
drwxr-xr-x. 2 root root 30 10月 16 22:02 branch
drwxr-xr-x. 2 root root 28 10月 16 22:02 main

./branch:
合計 4
-rw-r--r--. 1 root root 189 10月 16 22:02 branch_bk.tar.gz

./main:
合計 4
-rw-r--r--. 1 root root 187 10月 16 22:02 main_bk.tar.gz
```
１回目の再編処理の実行結果（引数："MAIN" ）
```text
[root@localhost：/work/test]# ./gene.sh MAIN
```
```text
MAINの再編処理を実施します。(３世代ローテーション)
-------------------------------------------------------------
--再編前-----------------------------------------------------
合計 4
-rw-r--r--. 1 root root 187 10月 16 22:02 main_bk.tar.gz
-------------------------------------------------------------
-------------------------------------------------------------
/work/test/BackUp/main/main_bk.tar.gz.ver2は、存在しない為、再編をスキップします。
/work/test/BackUp/main/main_bk.tar.gz.ver1は、存在しない為、再編をスキップします。
/work/test/BackUp/main/main_bk.tar.gz --> /work/test/BackUp/main/main_bk.tar.gz.ver1 
-------------------------------------------------------------
--再編後-----------------------------------------------------
合計 4
-rw-r--r--. 1 root root 187 10月 16 22:02 main_bk.tar.gz.ver1
-------------------------------------------------------------
-------------------------------------------------------------
MAINの世代管理が正常終了しました。
```
２回目の再編処理の実行結果（引数："MAIN" ）
```text
MAINの再編処理を実施します。(３世代ローテーション)
-------------------------------------------------------------
--再編前-----------------------------------------------------
合計 4
-rw-r--r--. 1 root root 187 10月 16 22:02 main_bk.tar.gz.ver1
-------------------------------------------------------------
-------------------------------------------------------------
/work/test/BackUp/main/main_bk.tar.gz.ver2は、存在しない為、再編をスキップします。
/work/test/BackUp/main/main_bk.tar.gz.ver1 --> /work/test/BackUp/main/main_bk.tar.gz.ver2 
/work/test/BackUp/main/main_bk.tar.gzは、存在しない為、再編をスキップします。
-------------------------------------------------------------
--再編後-----------------------------------------------------
合計 4
-rw-r--r--. 1 root root 187 10月 16 22:02 main_bk.tar.gz.ver2
-------------------------------------------------------------
-------------------------------------------------------------
MAINの世代管理が正常終了しました。
```
３回目の再編処理の実行結果（引数："MAIN" ）
```text
MAINの再編処理を実施します。(３世代ローテーション)
-------------------------------------------------------------
--再編前-----------------------------------------------------
合計 4
-rw-r--r--. 1 root root 187 10月 16 22:02 main_bk.tar.gz.ver2
-------------------------------------------------------------
-------------------------------------------------------------
/work/test/BackUp/main/main_bk.tar.gz.ver2 --> 削除 
/work/test/BackUp/main/main_bk.tar.gz.ver1は、存在しない為、再編をスキップします。
/work/test/BackUp/main/main_bk.tar.gzは、存在しない為、再編をスキップします。
-------------------------------------------------------------
--再編後-----------------------------------------------------
合計 0
-------------------------------------------------------------
-------------------------------------------------------------
MAINの世代管理が正常終了しました。
```
シェルの引数が間違っている（失敗１）
```text
[root@localhost test]# ./gene.sh XXX
```
```text
XXXの再編処理を実施します。(３世代ローテーション)
引数が間違っています。
-------------------------------------------------------------
XXXの世代管理が異常終了しました。
```
再編処理が失敗した場合（失敗２）
```text
MAINの再編処理を実施します。(３世代ローテーション)
-------------------------------------------------------------
--再編前-----------------------------------------------------
合計 4
-rw-r--r--. 1 root root 187 10月 16 22:22 main_bk.tar.gz
-------------------------------------------------------------
-------------------------------------------------------------
/work/test/BackUp/main/main_bk.tar.gz.ver2は、存在しない為、再編をスキップします。
/work/test/BackUp/main/main_bk.tar.gz.ver1は、存在しない為、再編をスキップします。
/work/test/BackUp/main/main_bk.tar.gz --> /work/test/BackUp/main/main_bk.tar.gz.ver1の再編に失敗
-------------------------------------------------------------
MAINの世代管理が異常終了しました。
```
```
MAINの再編処理を実施します。(３世代ローテーション)
-------------------------------------------------------------
--再編前-----------------------------------------------------
合計 4
-rw-r--r--. 1 root root 187 10月 16 22:22 main_bk.tar.gz.ver1
-------------------------------------------------------------
-------------------------------------------------------------
/work/test/BackUp/main/main_bk.tar.gz.ver2は、存在しない為、再編をスキップします。
/work/test/BackUp/main/main_bk.tar.gz.ver1 --> /work/test/BackUp/main/main_bk.tar.gz.ver2の再編に失敗
-------------------------------------------------------------
MAINの世代管理が異常終了しました。
```
```
MAINの再編処理を実施します。(３世代ローテーション)
-------------------------------------------------------------
--再編前-----------------------------------------------------
合計 4
-rw-r--r--. 1 root root 187 10月 16 22:22 main_bk.tar.gz.ver2
-------------------------------------------------------------
-------------------------------------------------------------
/work/test/BackUp/main/main_bk.tar.gz.ver2の削除に失敗
-------------------------------------------------------------
MAINの世代管理が異常終了しました。
```
# 今回使用したコマンドや構文について
:::note warn
clear コマンド
画面上をクリアするコマンド

\~~参考リンク~~
[【 clear 】コマンド――端末をクリアする](https://atmarkit.itmedia.co.jp/ait/articles/1903/14/news026.html)
:::
:::note warn
関数名 () { ~ ;}
一定の処理を関数としてまとめる構文

\~~参考リンク~~
[【Linux】シェルスクリプトの関数の使い方！一通りまとめ](https://eng-entrance.com/linux-shellscript-function)
:::
:::note warn
${パラメータ%パラメータ}
パラメータ値の文字列の右側から伊庭のパターンを取り除く構文

\~~参考リンク~~
[【シェル芸人への道】Bashの変数展開と真摯に向き合う](https://qiita.com/t_nakayama0714/items/80b4c94de43643f4be51)
:::
:::note warn
case文
文字列をパターンごとに場合分けして、処理を分岐させる。

\~~参考リンク~~
[【シェルスクリプト】（条件分岐）case文](https://www.server-memo.net/shellscript/case.html)
:::
:::note warn
if文(条件分岐)
条件によって処理を分岐する構文

\~~参考リンク~~
[if 文と test コマンド](https://shellscript.sunone.me/if_and_test.html)
:::
:::note warn
rm コマンド
ファイルを削除するコマンド

\~~参考リンク~~
[【 rm 】コマンド――ファイルを削除する](https://atmarkit.itmedia.co.jp/ait/articles/1606/06/news013.html)
:::
:::note warn
mv コマンド
ファイルやディレクトリを移動する／名前を変更するコマンド

\~~参考リンク~~
[【 mv 】コマンド――ファイルやディレクトリを移動する／名前を変更する](https://atmarkit.itmedia.co.jp/ait/articles/1606/13/news024.html)
:::
:::note warn
${} ドル波括弧、ドルブレース
変数名の区切りがうまく処理できない場合に使用する。

\~~参考リンク~~
[[シェル] カッコの意味と役割まとめ [Bash, Linux]](https://webbibouroku.com/Blog/Article/shell-paren-brace-bracket#outline__9)
:::