シェルスクリプトを作成する際、毎回似たような処理を記述することが多く、手間がかかります。特に、スクリプトのエラーハンドリングやログ出力の統一、環境変数の設定など、繰り返し発生する作業が多いのが現実です。
実際にサーバ構築の現場では、ベテランと新人エンジニアの間で、コードの品質以前に「作成に取り掛かるまでの時間」に大きな差があることがわかっています。これは単に面倒くさいからなのか、どこから手を付ければいいのか分からないのか、明確な理由は不明ですが、とにかく「着手するまでの時間」が驚くほど違うのが実情です。
中には、どう書き始めればよいか分からず、トイレにこもってしまうエンジニアも多く、その後必ず「何か参考になるスクリプトがあれば見せてください」と聞いてくる—— これはもはやコーダーあるある。様式美のようなものです。しかし、中には何もせずに考え続けたまま1日が終わってしまうケースも少なくありません。
このような状況を打破するために考えたのが、シェルスクリプト作成のテンプレート化です。スクリプトの骨組みを事前に準備することで、書き始める際の心理的ハードルを下げ、エンジニアが素早く作業に取り掛かれるようになります。
こうした無駄な時間を削減し、より効率的にスクリプトを開発できるのが「テンプレートファイル作成スクリプト (template.sh)」 です。本記事では、この template.sh を活用することで、スクリプト作成の手間を大幅に省き、一貫性のあるスクリプトを効率的に作成する方法を解説します。
テンプレートファイル作成スクリプトクラスの概要
テンプレートファイル作成スクリプトは、単独で使用するのではなく、共通ログ出力クラスやユーティリティ関数クラス と組み合わせることで、より洗練されたスクリプト開発を実現できます。
テンプレートファイル作成スクリプトの目的
テンプレートファイル作成スクリプトの目的は、シェルスクリプトの初期セットアップを自動化し、統一されたフォーマットで作成できるようにすることです。
これにより、エンジニアはゼロからスクリプトを書く必要がなくなり、スクリプトの品質や一貫性を向上させることが可能になります。
さらに、共通ログ出力クラスによる標準化されたログ出力や ユーティリティ関数クラスによる共通関数の活用と組み合わせることで、より実用的なスクリプトの作成が可能になります。
テンプレートの重要性と課題解決のポイント
テンプレートファイル作成スクリプトを活用することで、以下のような課題を解決できます。
ポイント
- エンジニアの作業を効率化:毎回ゼロから作成するのではなく、既存のテンプレートを活用することで作業時間を短縮。
- 「毎回ゼロから作らない」ための工夫:標準的な構成を持つテンプレートを利用することで、作業の抜け漏れを防止。
- シェルスクリプトの品質向上:例えば、set -e を導入することでスクリプトの異常終了を防ぎ、安全性を向上。
テンプレートスクリプトの設計の基本方針
テンプレートファイル作成スクリプト template.sh の設計は、以下の基本方針に基づいています。
基本方針
- スクリプト名のバリデーション
template という名前のスクリプト作成を禁止し、明確な命名規則を推奨。 - ログ出力 (logger.shrc) の組み込み
ログ出力を標準化し、エラー発生時のデバッグを容易に。 - ユーティリティ関数 (utils.shrc) の活用
便利な共通関数を活用することで、スクリプトの記述量を削減。 - ロック機構を用いた並行実行の制御
競合を防ぎ、スクリプトの安全な実行を保証。
このように テンプレートファイル作成スクリプトは、スクリプトの標準化と作業効率化を目的とし、実用的なシェルスクリプトの作成を支援するために設計されています。
設計書の構成と設計要素
テンプレートファイル作成スクリプト は、新しいシェルスクリプトを作成するためのスクリプトであり、統一されたフォーマットのスクリプトを自動生成する役割を持ちます。
このスクリプトの設計を明確にすることで、作成されるスクリプトの品質を維持し、運用の一貫性を確保することができます。
クラス設計の前提条件
テンプレートファイル作成スクリプトの設計において、以下の点を考慮する必要があります。
設計項目 | 説明 |
---|---|
動作環境 | RHEL 系 Linux 環境(CentOS, Rocky Linux, AlmaLinux など) |
依存ファイル | logger.shrc , utils.shrc を読み込む設計 |
スクリプトの役割 | 統一フォーマットのスクリプトを生成するための作成ツール |
作成対象 | システム運用・管理向けのシェルスクリプト |
使用する変数一覧
テンプレートファイル作成スクリプト で使用される主要な変数は以下の通りです。
変数名 | 説明 |
---|---|
SCRIPT_NAME | 作成するスクリプトの名前(引数として指定) |
SCRIPT_FILE | 作成されるスクリプトのファイルパス |
JOB_OK , JOB_WR , JOB_ER | ジョブのステータス管理用の定数(正常終了・警告・エラー) |
作成されるスクリプトの構成
テンプレートファイル作成スクリプトによって生成されるスクリプトのフォーマットは以下のような構成を持ちます。
構成要素 | 説明 |
---|---|
ヘッダー | スクリプトの説明、変更履歴、利用方法など |
共通関数の読み込み | logger.shrc や utils.shrc を . ./com/logger.shrc の形式で読み込む |
ジョブ管理変数 | 処理成功・失敗を管理するための変数定義(JOB_OK など) |
メイン処理 | 作成されたスクリプトが実際に実行する処理(テンプレートにはプレースホルダーが含まれる) |
ログ出力 | logOut を利用したログ管理 |
エラーハンドリング | エラー時に exitLog を使い適切に終了処理を行う |
実装されている関数の詳細
作成されたテンプレートファイルには、以下の関数が実装されています。環境に合わせて自由にヒアドキュメントないをカスタマイズして作成してください。
関数名 | 説明 |
---|---|
checkArgs() | 引数チェックを行い、不足している場合はエラーを出力 |
checkConf() | 設定ファイルの存在確認と適切な構成のチェック |
terminate() | スクリプトの終了処理としてロック解除とログ出力を行う |
logOut() | logger.shrc を利用してログ出力を統一し、デバッグしやすくする |
acquireLock() | 同時実行を防ぐためのロック処理を実装 |
このように、明確な設計ルールに基づいた テンプレートファイル作成スクリプト
を活用することで、より堅牢でメンテナンスしやすいスクリプト開発が可能になります。
以下はテンプレートファイル作成スクリプトクラスのソースコードになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | #!/bin/sh #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # # Usage: # template.sh [ 作成スクリプト名 ] # # sh template.sh test # Description: # 引数で指定されたShellスクリプトのテンプレートを作成する。l # # Design documents # None # #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # <変更履歴> # Ver. 変更管理No. 日付 更新者 変更内容 # 1.0 PR-0001 2019/01/16 Bepro 新規作成 #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # 引数チェック if [ $# -lt 1 ]; then echo "[ERROR] Missing argument: Please specify the name of the script to create." echo "Usage: $0 <script_name>" exit 1 fi # スクリプト名の取得 SCRIPT_NAME=$1 # "template" を含む名前は禁止 if echo "$SCRIPT_NAME" | grep -q -e 'template'; then echo "[ERROR] Invalid script name: The name cannot contain the word 'template'." exit 1 fi # スクリプトファイルのパス SCRIPT_FILE="./${SCRIPT_NAME}.sh" # カレントディレクトリの書き込み権限を確認 if [ ! -w . ]; then echo "[ERROR] The current directory is not writable. Cannot create files here." exit 1 fi # スクリプトファイルの重複チェック if [ -f "$SCRIPT_FILE" ]; then echo "[ERROR] The file '$SCRIPT_FILE' already exists." exit 1 fi # ---------------------------------------------------------- # テンプレート内容をスクリプトファイルに書き込む # ---------------------------------------------------------- cat << EOF > "$SCRIPT_FILE" #!/bin/sh #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # # Usage: # SCRIPT_NAME.sh # # Description: # This script is auto-generated by template.sh. # # Design documents # None # #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # <変更履歴> # Ver. 変更管理No. 日付 更新者 変更内容 #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ . "\$(dirname "\$0")/../com/logger.shrc" . "\$(dirname "\$0")/../com/utils.shrc" #runAs root \$* #setLANG utf-8 # Job status codes JOB_OK=0 # Normal exit JOB_WR=1 # Warning exit JOB_ER=2 # Error exit rc=JOB_ER # ---------------------------------------------------------- # functions terminate # ---------------------------------------------------------- terminate() { releaseLock } # ---------------------------------------------------------- # functions checkArgs # ---------------------------------------------------------- checkArgs() { : } # ---------------------------------------------------------- # functions checkConf # ---------------------------------------------------------- checkConf() { : } # ====== サンプルテンプレート設定ファイルの作成 ====== # ETC_PATH が未設定ならデフォルトパスを設定 if [ -z "\$ETC_PATH" ]; then ETC_PATH="/etc" fi # 必要ならディレクトリを作成 mkdir -p "\$ETC_PATH" # サンプル設定ファイルの作成(既存のものはバックアップ) TEMPLATE_FILE="\$ETC_PATH/template.cfg" if [ -f "\$TEMPLATE_FILE" ]; then mv "\$TEMPLATE_FILE" "\${TEMPLATE_FILE}.bak_\$(date +%Y%m%d%H%M%S)" fi cat <<EOT > "\$TEMPLATE_FILE" # テンプレート設定ファイル テンプレート設定ファイル1 # サンプル テンプレート設定ファイル2 # サンプル EOT # ---------------------------------------------------------- # pre-process # ---------------------------------------------------------- scope="pre" hostname=$(hostname -s) os=$(uname -s) temp_list="\$TEMPLATE_FILE" # 作成された設定ファイルを temp_list にセット startLog logOut "INFO" args: ["\$@"] if acquireLock; then logOut "INFO" successfully locked. else abort could not acquire lock. fi trap "terminate" 0 1 2 3 15 checkArgs \$* # ---------------------------------------------------------- # main-routine # ---------------------------------------------------------- scope="main" # 設定ファイルが存在するか確認 if [ ! -f "\$temp_list" ]; then logOut "ERROR" "Configuration file not found: \$temp_list" exitLog \$JOB_ER fi # Loop processing of target worth. sed '/^#/d;/^[[:blank:]]*$/d' "\$temp_list" | while IFS= read -r line; do echo "DEBUG: Line read - [\$line]" logOut "DEBUG" "Loop started turn of [ \$line ]." if [ \$? -ne 0 ]; then logOut "ERROR" "Failed to [ \$line ]." exitLog \$JOB_ER fi done if [ \$? -eq 0 ]; then rc=\$JOB_OK fi # ---------------------------------------------------------- # post-process # ---------------------------------------------------------- scope="post" exitLog \$rc EOF # 作成後にスクリプト名を置換 sed -i "s/SCRIPT_NAME/${SCRIPT_NAME}/g" "$SCRIPT_FILE" # ---------------------------------------------------------- # テンプレートの書き込み終了 # ---------------------------------------------------------- # ファイル作成の成功判定 if [ $? -ne 0 ]; then echo "[ERROR] Failed to create the template file '$SCRIPT_FILE'." exit 1 fi # ファイルの存在確認(念のため) if [ ! -f "$SCRIPT_FILE" ]; then echo "[ERROR] Template file '$SCRIPT_FILE' does not exist after creation." exit 1 fi # ファイルの実行権限を付与 chmod +x "$SCRIPT_FILE" # 実行権限の付与に失敗した場合 if [ $? -ne 0 ]; then echo "[ERROR] Failed to set executable permissions on '$SCRIPT_FILE'." exit 1 fi # 成功メッセージ echo "Template script '$SCRIPT_FILE' has been created successfully." |
※ 本スクリプトの利用により生じた、いかなる損害についても一切の責任を負わないものとします。また、損害賠償等の義務ついても、一切責任を負いません。
処理詳細
テンプレートファイル作成スクリプト は、新しいシェルスクリプトを作成するためのテンプレート生成スクリプトであり、統一されたフォーマットのスクリプトを効率的に作成する役割を持ちます。この処理詳細では、テンプレートファイル作成スクリプトの実行フロー と 作成されるスクリプトの動作フロー を明確に整理し、それぞれの処理の流れを説明します。
- 引数の検証(作成側スクリプトの処理)
- `template.sh` が適切な引数(作成するスクリプト名)を受け取っているかをチェックする。
- 引数が不足している場合は、エラーメッセージを出力してスクリプトを終了する。
- スクリプト名のバリデーション(作成側スクリプトの処理)
- 指定されたスクリプト名が適切であるかを検証する。
- スクリプト名に "template" を含む場合、エラーメッセージを出力してスクリプトを終了する。
- スクリプトファイルの存在チェック(作成側スクリプトの処理)
- 指定されたスクリプト名のファイルが既に存在するかを確認する。
- 既に存在する場合、エラーメッセージを出力してスクリプトを終了する。
- カレントディレクトリの書き込み権限を確認し、権限がない場合はエラーメッセージを出力して終了する。
<作成されるスクリプトの処理(ヒアドキュメント内の処理)>
- テンプレートスクリプトの作成(作成されるスクリプトの処理)
- `cat << EOF > "$SCRIPT_FILE"` を使用し、作成されるスクリプトの標準フォーマットを記述する。
- この時点で、作成されるスクリプトに以下の処理を自動生成する。
- `#!/bin/sh` でシェルスクリプトとしてのヘッダーを定義する。
- `logger.shrc` や `utils.shrc` を読み込む設定を含める。
- `startLog` などのログ記録処理を含める。
- スクリプトのメイン処理(引数チェック、設定ファイルチェック、ループ処理、エラーハンドリング)を含める。
<作成側スクリプトの後処理>
- テンプレートスクリプトの変数置換(作成側スクリプトの処理)
- `sed -i "s/SCRIPT_NAME/${SCRIPT_NAME}/g" "$SCRIPT_FILE"` を実行し、作成されたスクリプト内の `SCRIPT_NAME` プレースホルダーを指定されたスクリプト名に置換する。
- スクリプトの実行権限設定(作成側スクリプトの処理)
- `chmod +x "$SCRIPT_FILE"` を実行し、作成されたスクリプトに実行権限を付与する。
- 実行権限の設定に失敗した場合、エラーメッセージを出力し終了する。
- 作成完了メッセージの出力(作成側スクリプトの処理)
- 作成が正常に完了したことを示すメッセージを出力する。
実践的な利用方法とサンプルコード
シェルスクリプトの作成は、環境設定や共通処理の組み込みなど、毎回似たような作業が発生しがちです。template.sh を活用することで、スクリプトの雛形を統一し、開発効率を向上させることができます。
本章では、template.sh の基本的な使い方 から 作成されたスクリプトのカスタマイズ方法、具体的な利用ケースや導入によるメリット について詳しく解説します
基本的な使い方
template.sh は、新しいシェルスクリプトを作成するためのテンプレートスクリプトです。このスクリプトを利用することで、共通のフォーマットを適用し、エラーハンドリングやログ出力の標準化が可能になります。
ここでは、template.sh を実行して 新しいスクリプトを作成する手順 と、作成されたスクリプトの構成を理解し、どのようにカスタマイズすればよいのか を説明します。
作成側スクリプトの実行
template.sh
を使用して新しいスクリプトを作成するには、以下のコマンドを実行します。
$ ./template.sh my_script
このコマンドを実行すると、カレントディレクトリに my_script.sh
というスクリプトが作成されます。
作成側スクリプトの処理
この処理では、template.sh
によって以下の手順でスクリプトが作成されます。
- 指定されたスクリプト名のバリデーションを行う(適切な名前かチェック)。
- 既に同名のスクリプトが存在する場合、エラーを出力して終了する。
- ヒアドキュメントを使用して、スクリプトの雛形(テンプレート)を作成する。
sed
コマンドを利用し、作成されたスクリプト内のプレースホルダー(例:SCRIPT_NAME
)を指定したスクリプト名に置換する。- 作成されたスクリプトに実行権限を付与し、作成完了のメッセージを出力する。
作成されたスクリプトの内容
作成後の my_script.sh
の中身は以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | #!/bin/sh #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # # Usage: # my_script.sh # # Description: # This script is auto-generated by template.sh. # # Design documents # None # #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # <変更履歴> # Ver. 変更管理No. 日付 更新者 変更内容 #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ . "$(dirname "$0")/../com/logger.shrc" . "$(dirname "$0")/../com/utils.shrc" #runAs root $* #setLANG utf-8 # Job status codes JOB_OK=0 # Normal exit JOB_WR=1 # Warning exit JOB_ER=2 # Error exit rc=JOB_ER # ---------------------------------------------------------- # functions terminate # ---------------------------------------------------------- terminate() { releaseLock } # ---------------------------------------------------------- # functions checkArgs # ---------------------------------------------------------- checkArgs() { : } # ---------------------------------------------------------- # functions checkConf # ---------------------------------------------------------- checkConf() { : } # ====== サンプルテンプレート設定ファイルの作成 ====== # ETC_PATH が未設定ならデフォルトパスを設定 if [ -z "$ETC_PATH" ]; then ETC_PATH="/etc" fi # 必要ならディレクトリを作成 mkdir -p "$ETC_PATH" # サンプル設定ファイルの作成(既存のものはバックアップ) TEMPLATE_FILE="$ETC_PATH/template.cfg" if [ -f "$TEMPLATE_FILE" ]; then mv "$TEMPLATE_FILE" "${TEMPLATE_FILE}.bak_$(date +%Y%m%d%H%M%S)" fi cat <<EOT > "$TEMPLATE_FILE" # テンプレート設定ファイル テンプレート設定ファイル1 # サンプル テンプレート設定ファイル2 # サンプル EOT # ---------------------------------------------------------- # pre-process # ---------------------------------------------------------- scope="pre" hostname=localhost os=Linux temp_list="$TEMPLATE_FILE" # 作成された設定ファイルを temp_list にセット startLog logOut "INFO" args: ["$@"] if acquireLock; then logOut "INFO" successfully locked. else abort could not acquire lock. fi trap "terminate" 0 1 2 3 15 checkArgs $* # ---------------------------------------------------------- # main-routine # ---------------------------------------------------------- scope="main" # 設定ファイルが存在するか確認 if [ ! -f "$temp_list" ]; then logOut "ERROR" "Configuration file not found: $temp_list" exitLog $JOB_ER fi # Loop processing of target worth. sed '/^#/d;/^[[:blank:]]*$/d' "$temp_list" | while IFS= read -r line; do echo "DEBUG: Line read - [$line]" logOut "DEBUG" "Loop started turn of [ $line ]." if [ $? -ne 0 ]; then logOut "ERROR" "Failed to [ $line ]." exitLog $JOB_ER fi done if [ $? -eq 0 ]; then rc=$JOB_OK fi # ---------------------------------------------------------- # post-process # ---------------------------------------------------------- scope="post" exitLog $rc |
※ 本スクリプトの利用により生じた、いかなる損害についても一切の責任を負わないものとします。また、損害賠償等の義務ついても、一切責任を負いません。
作成されたスクリプトのカスタマイズ
作成された直後のスクリプト内部には、このままでは何も機能しません。また、内部ロジックとしてサンプルのソースが記載されていますが、実際に使用する際に正しいソースコードに書き換えて使用してください。こんな感じという体で記載しているだけです。
1 2 3 4 5 6 7 8 9 10 | [root@localhost bin]# sh template.sh my_script Template script './my_script.sh' has been created successfully. [root@localhost bin]# sh my_script.sh 2025-01-30 21:15:28 [ INFO ] SCRIPT:[my_script.sh] PID:[331462] STARTED LOG. 2025-01-30 21:15:28 [ INFO ] args: [] 2025-01-30 21:15:28 [ INFO ] Lock acquired on [/work/scripts//tmp/my_script.lock]. 2025-01-30 21:15:28 [ INFO ] successfully locked. DEBUG: Line read - [テンプレート設定ファイル1 # サンプル] DEBUG: Line read - [テンプレート設定ファイル2 # サンプル] 2025-01-30 21:15:28 [ INFO ] Lock released: [/work/scripts//tmp/my_script.lock] |
それらしく実行結果が出ていますが、サンプルソースのため何も機能は実施されません。