共通関数定義クラスの概要と役割
共通関数定義クラス(utils.shrc)は、シェルスクリプト開発において頻繁に使用される汎用的な関数をまとめたスクリプトです。これを活用することで、スクリプトごとに重複したコードを書く必要がなくなり、開発の効率化や保守性の向上を実現できます。
特に、シェルスクリプトはプロジェクトが大規模になるにつれて管理が複雑になりがちです。utils.shrcを導入することで、スクリプト間の一貫性を保ちつつ、共通機能を統一した形式で提供できます。
共通関数定義クラスの目的
共通関数定義クラスの主な目的は、以下の3つに集約されます。
目的
- コードの再利用性向上
頻繁に使用する関数を集約し、各スクリプトで共通化することで、コードの重複を削減します - 保守性の向上
修正が必要な場合、共通関数定義クラスを更新するだけで全スクリプトに適用されるため、保守作業を簡素化できます。 - 可読性の向上
共通関数を利用することで、各スクリプトがシンプルになり、他の開発者がスクリプトを理解しやすくなります。
共通関数定義クラスの適用範囲
共通関数定義クラスは、以下のような用途で活用できます。
活用用途
- ログ処理の統一
メッセージの出力を標準化し、ログの記録方法を統一する。 - エラーハンドリング
予期しないエラー発生時に適切なメッセージを出力し、スクリプトの異常終了を制御する。 - ファイル操作の簡素化
一時ファイルの作成・削除、ディレクトリの作成・移動といった操作を統一する。 - プロセス管理
プロセスの状態チェックや重複実行の防止機能を提供する。 - 環境変数の管理
必要な環境変数の初期化や取得を一元管理し、スクリプトごとの設定ミスを防ぐ。
このように、システム管理やバッチ処理など、さまざまなシェルスクリプトに適用できます。
共通関数定義クラスの設計の基本方針
共通関数定義クラスは、以下の基本方針に基づいて設計されています。
基本方針
- シンプルで汎用的な関数の提供
- 特定のスクリプト専用の関数ではなく、複数のスクリプトで再利用可能な設計を重視。
- 依存関係の最小化
- 外部ツールや特定の環境に依存しないようにし、ポータビリティを確保。
- エラーハンドリングの標準化
- すべての関数で適切なエラーハンドリングを実装し、異常時の動作を統一。
- パフォーマンスを考慮した設計
- シェルスクリプトの特性を活かし、無駄なプロセスの生成や処理の遅延を最小限に抑える。
- 一貫した命名規則の適用
- 変数や関数名の命名規則を統一し、可読性と保守性を向上。
これらの方針に基づいて設計することで、utils.shrcは柔軟かつ堅牢な共通関数クラスとして機能します。
設計書の構成と設計要素
共通関数定義クラス(utils.shrc)は、シェルスクリプトにおける汎用的な処理をまとめた関数群を提供するものです。本章では、その設計の前提条件、関数のスコープ管理、そして実装されている主要な関数について解説します。
クラス設計の前提条件
共通関数定義クラスは、シェルスクリプトの汎用的な処理を統一するために設計されています。そのため、以下のような前提条件を設定しています。
前提条件
- 関数ベースの設計
- 共通関数定義クラス は、単体で実行するスクリプトではなく、他のスクリプトから source で読み込まれる ことを前提としています。
- すべての処理は関数として定義されており、直接スクリプトに影響を与えることはありません。
- スコープの明確化(グローバル変数なし)
- グローバル変数は一切使用しない 設計となっています。
- 各関数の内部で local を利用し、関数外に影響を与えないように管理。
- エラーハンドリングと戻り値の統一
- すべての関数は 0(成功)、1(失敗) など統一された戻り値を持つ。
- 標準エラー出力(stderr)へエラーメッセージを出力する場合は、logOut 関数を利用。
- 外部依存の最小化
- OSに依存しないよう、可能な限り POSIX準拠 のコマンドを使用。
- grep, awk, sed, find など、シェルスクリプトで一般的なツールの利用は許容
- 排他制御とプロセス管理
- acquireLock と releaseLock の関数を用意し、同時実行を制限できる設計。
- ロックファイルの所有権を適切に管理する。
関数のスコープ管理と設計方針
utils.shrc では、すべての関数において ローカルスコープ(local 変数) を徹底し、グローバル変数の使用を避ける方針を採用しています。
スコープ管理の基本ルール
- すべての関数で
local
を使用する
関数内でのみ有効な変数として local
を明示的に使用し、他の関数やスクリプトに影響を与えないようにする。
sampleFunction() {
local var="This is a local variable"
echo "$var"
}
- 関数間の影響を最小限にする
必要なデータは関数の引数で受け渡し、戻り値で結果を返す設計を採用。
isEmpty() {
[[ -z "$1" ]]
}
- ロックファイルの利用
排他制御を適切に管理するために、関数内でのみロックファイルを参照し、不要になったら適切に解放する。
releaseLock() {
if [ -f "$LOCK_FILE" ]; then
local locker=$(cat "$LOCK_FILE" 2>/dev/null)
if [ "$locker" = "$$" ]; then
rm -f "$LOCK_FILE"
logOut "INFO" "Lock released: [$LOCK_FILE]"
else
logOut "WARN" "Lock file exists, but owned by PID [$locker], not [$$]."
fi
fi
}
実装されている関数の詳細
共通関数定義クラス(utils.shrc)には、シェルスクリプトの開発を効率化するための汎用的な関数が実装されています。以下に、関数の一覧を示します。
関数名 | 概要 | 引数 | 戻り値 |
---|---|---|---|
releaseLock | スクリプトの多重実行を防ぐためにロックを解除する。 | なし | 0 : 成功(ロック解除)1 : 失敗(ロックが存在しない) |
acquireLock | スクリプトの多重実行を防ぐためにロックを取得する。 | なし | 0 : 成功(ロック取得)1 : 失敗(他のプロセスがロック中) |
setUTF8 | 言語環境変数(LANG)を UTF-8 に設定する。 | なし | なし |
setSJIS | 言語環境変数(LANG)を Shift-JIS に設定する。 | なし | なし |
setLANG | スクリプトを特定のユーザーで実行する。 | $1: 設定する LANG の値(デフォルト: C) | なし |
runAs | root ユーザーでスクリプトを実行する。 | $1: 実行ユーザー(デフォルト: root) $2-: スクリプトに渡す引数 | なし(指定ユーザーで再実行) |
runAsRoot | スクリプトを root ユーザーとして実行する。 | なし | なし(root ユーザーで実行) |
abort | エラーメッセージを記録し、スクリプトを終了する。 | $1 : エラーメッセージ | なし(exit 1 で終了) |
getMd5Sum | 指定したファイルの MD5 ハッシュ値を取得する。 | $1 : ファイルパス | MD5 ハッシュ値(標準出力へ出力) |
getProcessCount | 指定したプロセスの数をカウントする。 | $1 : プロセス名 | プロセス数(標準出力へ出力) |
isAlphaNum | 文字列が英数字のみで構成されているかを判定する。 | $1 : チェック対象の文字列 | 0 : 英数字 / 1 : 非英数字 |
isNumeric | 文字列が数値であるかを判定する。 | $1 : チェック対象の文字列 | 0 : 数値 / 1 : 非数値 |
isPortAlive | 指定したポートがリスニング状態にあるかを確認する。 | $1 : ポート番号 | 0 : LISTEN / 1 : 非LISTEN |
checkProcessCount | 指定したプロセスの実行数が指定範囲内であるかを確認する。 | $1 : プロセス名$2 : 最小数$3 : 最大数 | 0 : 範囲内 / 1 : 少なすぎ / 2 : 多すぎ |
backupFile | ファイルをバックアップする(タイムスタンプ付き)。 | $1 : バックアップ対象ファイル | なし |
deleteOldFiles | 指定したディレクトリ内の古いファイルを削除する。 | $1 : ディレクトリパス$2 : 保持日数 | なし |
isHostAlive | 指定したホストがネットワーク上で到達可能かを確認する。 | $1 : ホスト名 | 0 : 到達可能 / 1 : 不可 |
confirmAction | 重要な操作の前にユーザーへ確認を求める。 | $1 : 確認メッセージ | 0 : 承諾 / 1 : 拒否 |
checkCommandExists | スクリプトで必要なコマンドがシステムに存在するかを確認する。 | $1 : コマンド名 | 0 : 存在 / 1 : 不存在 |
isKeywordInProcess | 指定したキーワードがプロセス一覧に含まれているかを確認する。 | $1 : キーワード | 0 : 発見 / 1 : 未発見 |
getCurrentTimestamp | 現在のタイムスタンプを取得する(YYYY-MM-DD_HH-MM-SS)。 | なし | タイムスタンプ(標準出力へ出力) |
formatDate | 指定した日時をフォーマット変換する。 | $1 : 日時(YYYYMMDD-HHMMSS) | フォーマット済み日時(標準出力へ出力) |
共通関数定義クラスの導入手順
共通関数定義クラス(utils.shrc
)を使用するための手順について説明します。これにより、シェルスクリプトにおける汎用的な関数を再利用し、効率的な開発が可能になります。
前提となる実行環境
Beエンジニアでシェルスクリプトを実行する環境は下記の通りとします。
実行環境
BASE_DIR(任意のディレクトリ)
- scripts
- bin(実行スクリプト格納領域)
- <<各種実行スクリプト>>.sh (実行ファイル)
- com(共通スクリプト格納領域)
- logger.shrc(共通ログ出力ファイル)
- utils.shrc(共通関数定義ファイル)
- etc(設定ファイル等の格納領域)
- infraMessage.conf(メッセージ定義ファイル)
- log(スクリプト実行ログの格納領域)
- スクリプト名.log
- tmp(テンポラリ領域)
- rep(レポート出力領域)
- bin(実行スクリプト格納領域)
共通関数定義クラス(utils.shrc
) を正常に動作させるためには、以下の実行環境が整っている必要があります。
- シェル環境: Bash 4.x 以上を推奨。
utils.shrc
は Bash を前提として設計されています。 - ファイルシステムへの書き込み権限: スクリプトがロックファイルや一時ファイルを操作するため、実行するディレクトリへの書き込み権限が必要です。
- 依存ツール: 一部の関数は
grep
、awk
、sed
などの標準的なツールを使用します。これらのツールがシステムにインストールされていることを確認してください。
※ 本スクリプトの利用により生じた、いかなる損害についても一切の責任を負わないものとします。また、損害賠償等の義務ついても、一切責任を負いません。
共通関数定義クラスの導入方法
共通関数定義クラス(utils.shrc
)は、以下のコードをプロジェクトにコピーし、シェルスクリプトで使用できるように設定します。
まず、下記のコードを utils.shrc
としてファイルに保存してください。
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 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 | # Common Utilities resource file #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # # logger.sh ver.1.0.0 2025.01.24 # # Usage: # Utils.shrc # # Description: # 各種スクリプトより呼び出される共通機能を提供する。 # # 設計書 # none # #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # <変更履歴> # Ver. 変更管理No. 日付 更新者 変更内容 # 1.0 PR-0001 2025/01/16 Bepro 新規作成 #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # -------------------------------------------------- # Release the acquired lock # -------------------------------------------------- # Purpose: # Removes the lock file to allow other instances to run. # Arguments: # None # Returns: # None # Notes: # - This function should be called before exiting the script. # - It verifies the lock file exists before removing. # -------------------------------------------------- releaseLock() { if [ -n "$LOCK_FILE" ]; then locker=$(cat "$LOCK_FILE" 2>/dev/null) if [ "$locker" = "$$" ]; then rm -f "$LOCK_FILE" logOut "INFO" "Lock released: [$LOCK_FILE]" else logOut "WARN" "Lock file exists, but owned by PID [$locker], not [$$]." logOut "WARN" "Lock file [$LOCK_FILE] is left untouched." fi fi } # -------------------------------------------------- # Acquire process lock using a lock file # -------------------------------------------------- # Purpose: # Prevent multiple instances of the script from running simultaneously. # Arguments: # None # Returns: # 0: Success (lock acquired) # !0: Failure (another instance is already running) # Notes: # - Uses a lock file instead of a directory. # - Relies on `flock` for safe locking. # - Writes the process ID to the lock file. # -------------------------------------------------- acquireLock() { LOCK_FILE="${TMP_PATH}/${SCRIPT_NAME%.*}.lock" exec 200>"$LOCK_FILE" # File descriptor 200 をロックファイルに関連付け # flock コマンドを使用してロックを試みる if flock -n 200; then echo $$ > "$LOCK_FILE" # プロセスIDを書き込む logOut "INFO" "Lock acquired on [$LOCK_FILE]." export LOCK_FILE return 0 else logOut "ERROR" "Another instance is already running. Lock file [$LOCK_FILE] exists." return 1 fi } # -------------------------------------------------- # Set LANG environment variable to UTF-8 encoding # -------------------------------------------------- # Purpose: # Configures the LANG environment variable for UTF-8 encoding # based on the operating system. This ensures compatibility # with applications and scripts requiring UTF-8. # Arguments: # None # Returns: # None # Notes: # - For AIX: LANG is set to "JA_JP" # - For Linux/FreeBSD: LANG is set to "ja_JP.UTF-8" # - For unsupported OS: LANG defaults to "C" # - Ensure the specified locale is installed on the system. # -------------------------------------------------- setUTF8() { case $(uname -s) in AIX) LANG=JA_JP ;; Linux|FreeBSD) LANG=ja_JP.UTF-8 ;; *) LANG=C ;; esac export LANG logOut "INFO" "LANG set to ${LANG} based on operating system." } # -------------------------------------------------- # Set LANG environment variable to SJIS encoding # -------------------------------------------------- # Purpose: # Configures the LANG environment variable for SJIS encoding # based on the operating system. This ensures compatibility # with software or scripts requiring SJIS encoding. # Arguments: # None # Returns: # None # Notes: # - For AIX: LANG is set to "Ja_JP" # - For Linux: LANG is set to "ja_JP.sjis" # - For FreeBSD: LANG is set to "ja_JP.SJIS" # - For unsupported OS: LANG defaults to "C" # -------------------------------------------------- setSJIS() { case $(uname -s) in AIX) LANG=Ja_JP ;; Linux) LANG=ja_JP.sjis ;; FreeBSD) LANG=ja_JP.SJIS ;; *) LANG=C ;; esac export LANG logOut "INFO" "LANG set to ${LANG} based on operating system." } # -------------------------------------------------- # Set LANG # -------------------------------------------------- # Purpose: # Sets the language environment variable (LANG). # Arguments: # $1: The LANG value (default: C) # Returns: # None # Notes: # - Supports UTF-8, Shift-JIS, and C/POSIX locales. # - Logs the LANG setting for debugging. # -------------------------------------------------- setLANG() { case "$1" in UTF-8|utf-8|UTF8|utf8|UTF) LANG="en_US.UTF-8" ;; SJIS|sjis|Shift-JIS) LANG="ja_JP.SJIS" ;; C|POSIX) LANG="C" ;; *) LANG="C" ;; esac export LANG logOut "INFO" "LANG has been set to [$LANG]" } # -------------------------------------------------- # Ensure the script runs as a specific user # -------------------------------------------------- # Purpose: # Ensures the script is executed as a specific user. # If the current user is not the specified user, the script # switches to the target user and re-executes itself. # Arguments: # param1: Target user (default: root) # param2-: Command line arguments to pass to the script # Returns: # None (the script exits upon switching users or continues execution) # Notes: # - Uses `sudo` to switch users instead of `su`. # - If the specified user does not exist, the script aborts. # -------------------------------------------------- runAs() { local target_user=${1:-"root"} # デフォルトは root shift local script_path # 現在のユーザーの取得 local current_user current_user=$(id -un) # ユーザーの存在確認(getent passwd を使用) if ! getent passwd "$target_user" > /dev/null; then abort "User [$target_user] does not exist on this system." fi # 絶対パスを取得 script_path=$(realpath "$0") # 実行ユーザーが異なれば sudo で再実行 if [ "$current_user" != "$target_user" ]; then logOut "INFO" "Switching to user [$target_user] to execute [$script_path]" exec sudo -u "$target_user" -- "$script_path" "$@" fi logOut "INFO" "Executing as user [$current_user]" } # -------------------------------------------------- # Ensure the script runs as root # -------------------------------------------------- # Purpose: # Ensures the script is executed with root privileges. # If not, it either aborts with an error or re-executes with sudo. # Arguments: # None # Returns: # None (exits or re-executes the script as root) # Notes: # - Automatically retries with 'sudo' if not root. # - This enhances usability while maintaining security. # -------------------------------------------------- runAsRoot() { local uid uid=$(id -u) if [ "$uid" -ne 0 ]; then logOut "WARN" "Permission denied. Re-executing as root..." exec sudo "$0" "$@" fi } # -------------------------------------------------- # Abort script execution with an error message. # -------------------------------------------------- # Purpose: # Logs an abort message and terminates the script with exit code 1. # Arguments: # param1-: Error message to log. # Example: "Critical failure in configuration loading." # Returns: # None (terminates script with exit code 1) # Notes: # - All output is sent to standard error (stderr). # - Includes stack trace information for easier debugging. # -------------------------------------------------- abort() { local caller_info log_msg caller_info=$(caller 0 2>/dev/null) # どこで呼ばれたか取得 log_msg="ABORT [$caller_info]: $*" # `formatLog` の代わりに直接メッセージ生成 echo "$log_msg" 1>&2 # stderr にログ出力 sync # ログを確実にディスクに書き込む exit 1 # スクリプトを異常終了 } # ------------------------------------------------------------ # Obtain the MD5 hash value of a file. # ------------------------------------------------------------ # Purpose: # Computes and returns the MD5 hash value of the specified file. # Arguments: # $1: Path to the file (absolute or relative) # Returns: # MD5 hash value (printed to stdout) # Notes: # - If the file does not exist or is not accessible, the function # logs an error and returns 1. # - Compatible with both Linux (`md5sum`) and macOS (`md5`). # ------------------------------------------------------------ getMd5Sum() { local file="$1" # Check if the file path is provided if [ -z "$file" ]; then logOut "ERROR" "No file specified for MD5 calculation." return 1 fi # Check if the file exists and is readable if [ ! -f "$file" ]; then logOut "ERROR" "File not found or not accessible: $file" return 1 fi # Determine the correct MD5 command based on OS if command -v md5sum > /dev/null 2>&1; then md5sum "$file" | awk '{print $1}' elif command -v md5 > /dev/null 2>&1; then md5 -q "$file" else logOut "ERROR" "No suitable MD5 command found on this system." return 1 fi } # ------------------------------------------------------------ # Count the number of running processes matching a pattern. # ------------------------------------------------------------ # Purpose: # Counts the number of running processes that match the specified pattern. # Arguments: # $1: Pattern to search for (e.g., process name or part of a command line) # Returns: # Process count (printed to stdout) # Notes: # - Excludes the current script and the `grep` commands themselves from the count. # - Ensure that the pattern does not unintentionally match unrelated processes. # ------------------------------------------------------------ getProcessCount() { local pattern="$1" # Check if the pattern is provided if [ -z "$pattern" ]; then echo "0" return fi # Count matching processes, excluding this script and grep itself local count count=$(ps auxw | grep -F "$pattern" | grep -v "grep" | grep -v "$SCRIPT_NAME" | wc -l) echo "$count" } # -------------------------------------------------- # Check if the value contains only alphanumeric characters. # -------------------------------------------------- # Purpose: # Determines whether a given value consists solely of alphanumeric characters. # Arguments: # $1: Value to check # Returns: # 0: Alphanumeric 1: Not Alphanumeric # Notes: # - Uses `sed` to remove non-alphanumeric characters and compares with original value. # - Does not rely on external tools other than `sed` for matching. # -------------------------------------------------- isAlphaNum() { val="$(echo $1 | sed -e 's/[^[:alnum:]]//g')" if [ "$val" != "$1" ]; then return 1 # Not Alphanumeric fi return 0 # Alphanumeric } # ------------------------------------------------------------ # Check if the given value is numeric. # ------------------------------------------------------------ # Purpose: # Determines whether the provided value is a valid numeric value. # Arguments: # $1: The value to check (string or number) # Returns: # 0: The value is numeric (integer) # 1: The value is not numeric # Notes: # - A numeric value is defined as an integer (positive or negative). # - This function does not handle floating-point numbers or other non-integer values. # - Leading or trailing spaces are not allowed. # - Uses `expr` to check if the value is a valid integer. # ------------------------------------------------------------ isNumeric() { expr "$1" + 1 >/dev/null 2>&1 if [ $? -ge 2 ]; then return 1 fi return 0 } # ------------------------------------------------------------ # Check if a specified port is in LISTEN state. # ------------------------------------------------------------ # Purpose: # Verifies whether the specified port is actively listening # on the system. # Arguments: # $1: Port number (e.g., 80, 443) # Returns: # 0: The port is listening # 1: The port is not listening # Notes: # - This function uses the `netstat` command to check the port state. # - Ensure that the `netstat` command is available in your environment. # - Invalid or empty input will cause the function to return 1. # ------------------------------------------------------------ isPortAlive() { local port="$1" # Validate input if [[ -z "$port" || ! "$port" =~ ^[0-9]+$ ]]; then logOut "ERROR" "Invalid port number: $port" return 1 fi # Check if the port is in LISTEN state local count count=$(netstat -tan 2>/dev/null | grep ":$port" | grep -w "LISTEN" | wc -l) if [ "$count" -eq 0 ]; then return 1 # Port is not listening fi return 0 # Port is listening } # ------------------------------------------------------------ # Check if the specified keyword is present in the process table. # ------------------------------------------------------------ # Purpose: # Verifies whether the given keyword is present in the system's # process table. # Arguments: # $1: Keyword to search for (e.g., process name or part of a command line) # Returns: # 0: The keyword is found in the process table # 1: The keyword is not found in the process table # Notes: # - Excludes the `grep` process itself from the search. # - If no keyword is provided, the function logs an error and returns 1. # - Ensure that the keyword does not unintentionally match unrelated processes. # ------------------------------------------------------------ isKeywordInProcess() { local keyword="$1" # Validate input if [ -z "$keyword" ]; then logOut "ERROR" "No keyword specified for process search." return 1 fi # Check for the keyword in the process table if ps auxw | grep -F "$keyword" | grep -v grep >/dev/null; then return 0 # Keyword found else return 1 # Keyword not found fi } # ------------------------------------------------------------ # Check the process count against a specified range. # ------------------------------------------------------------ # Purpose: # Verifies whether the number of running processes for the # specified process name is within the given range. # Arguments: # $1: process_name (string) - The name of the process to check. # $2: min_count (integer) - Minimum allowed process count. # $3: max_count (integer) - Maximum allowed process count. # Returns: # 0: Process count is within range. # 1: Process count is below the minimum. # 2: Process count exceeds the maximum. # 3: Invalid argument (e.g., min_count > max_count or invalid process count). # Notes: # - For single process requirements, set min_count and max_count to 1. # - Logs an error message if the process count is invalid or if the arguments are incorrect. # ------------------------------------------------------------ checkProcessCount() { local process_name="$1" local min_count="$2" local max_count="$3" local process_count # プロセス数を数値として取得 process_count=$(ps aux | grep "$process_name" | grep -v grep | wc -l) # プロセス数が空でないことを確認 if [ -z "$process_count" ] || ! [[ "$process_count" =~ ^[0-9]+$ ]]; then echo "[ ERROR ] Invalid process count: $process_count" return 3 # 無効な値が返された場合 fi # 引数のチェック: min_count が max_count より大きい場合、エラーを返す if [ "$min_count" -gt "$max_count" ]; then return 3 # 無効な引数 fi # プロセス数が範囲内か確認 if [ "$process_count" -ge "$min_count" ] && [ "$process_count" -le "$max_count" ]; then return 0 # プロセス数は範囲内 elif [ "$process_count" -lt "$min_count" ]; then return 1 # プロセス数が最小値より少ない elif [ "$process_count" -gt "$max_count" ]; then return 2 # プロセス数が最大値を超えている fi } # ------------------------------------------------------------ # Get the current timestamp in a specific format. # ------------------------------------------------------------ # Purpose: # Returns the current date and time in the format YYYY-MM-DD HH:MM:SS. # Arguments: # None # Returns: # Current timestamp (printed to stdout). # ------------------------------------------------------------ getCurrentTimestamp() { # シングルクォートを含まない形式で日付を取得 echo "$(date +"%Y-%m-%d_%H-%M-%S")" } # ------------------------------------------------------------ # Format a given timestamp or current time. # ------------------------------------------------------------ # Purpose: # Converts a given timestamp into a specified format. # Arguments: # $1: Format (e.g., "%Y-%m-%d", "%H:%M:%S"). # Returns: # Formatted timestamp (printed to stdout). # ------------------------------------------------------------ formatDate() { local format="${1:-"%Y-%m-%d"}" date +"$format" } # ------------------------------------------------------------ # Create a backup of a specified file. # ------------------------------------------------------------ # Purpose: # Copies the file to a backup location with a timestamp appended. # Arguments: # $1: File to back up. # Returns: # None. # Notes: # - Logs an error if the file does not exist or cannot be backed up. # ------------------------------------------------------------ backupFile() { local file="$1" if [ ! -f "$file" ]; then logOut "ERROR" "File not found: $file" return 1 fi local timestamp timestamp=$(getCurrentTimestamp) # 共通関数でタイムスタンプ取得 # バックアップファイル名を生成 local backup="${file}_${timestamp}.bak" # バックアップを作成 cp "$file" "$backup" && logOut "INFO" "Backup created: $backup" || logOut "ERROR" "Failed to create backup: $file" } # ------------------------------------------------------------ # Delete files older than a specified number of days. # ------------------------------------------------------------ # Purpose: # Cleans up files in a directory that exceed a retention period. # Arguments: # $1: Directory to clean up. # $2: Retention period in days. # Returns: # None. # Notes: # - Logs the result of the cleanup operation. # ------------------------------------------------------------ deleteOldFiles() { local dir="$1" local days="$2" if [ ! -d "$dir" ]; then logOut "ERROR" "Directory not found: $dir" return 1 fi find "$dir" -type f -mtime +"$days" -exec rm -f {} \; && logOut "INFO" "Old files in $dir older than $days days deleted." || logOut "ERROR" "Failed to delete files in $dir." } # ------------------------------------------------------------ # Check if a host is reachable. # ------------------------------------------------------------ # Purpose: # Verifies whether the specified host is reachable via ping. # Arguments: # $1: Hostname or IP address. # Returns: # 0: Host is reachable. # 1: Host is not reachable. # ------------------------------------------------------------ isHostAlive() { local host="$1" if ping -c 1 -W 1 "$host" >/dev/null 2>&1; then return 0 else logOut "WARN" "Host $host is not reachable." return 1 fi } # ------------------------------------------------------------ # Prompt the user for confirmation. # ------------------------------------------------------------ # Purpose: # Asks the user for confirmation before proceeding with a critical operation. # Arguments: # $1: Message to display (e.g., "Are you sure?") # Returns: # 0: User confirmed. # 1: User declined. # ------------------------------------------------------------ confirmAction() { local message="${1:-"Are you sure? [y/N]"}" read -r -p "$message " response case "$response" in [yY][eE][sS]|[yY]) return 0 ;; *) return 1 ;; esac } # ------------------------------------------------------------ # Check if a command exists in the environment. # ------------------------------------------------------------ # Purpose: # Ensures that a required command is available before executing the script. # Arguments: # $1: Command name to check (e.g., "curl"). # Returns: # 0: Command exists. # 1: Command does not exist. # ------------------------------------------------------------ checkCommandExists() { command -v "$1" >/dev/null 2>&1 # コマンドが存在するか確認 return $? # 成功なら0、失敗なら1を返す } |
※ 本スクリプトの利用により生じた、いかなる損害についても一切の責任を負わないものとします。また、損害賠償等の義務ついても、一切責任を負いません。
utils.shrc
を取得するutils.shrc
ファイルをプロジェクトディレクトリにコピーします。通常はscripts/com/
ディレクトリに配置します。cp utils.shrc /path/to/your/project/scripts/com/
- 他のシェルスクリプトから
source
で読み込む
他のシェルスクリプト内で共通関数を利用するためには、source
コマンドを使用してutils.shrc
を読み込みます。source /path/to/your/project/scripts/com/utils.shrc
- 関数を利用する
utils.shrc
内の関数は、スクリプト内でそのまま呼び出すことができます。例えば、getCurrentTimestamp
関数を使用するには次のように記述します。timestamp=$(getCurrentTimestamp)
echo "Current timestamp: $timestamp" - 動作確認
導入後、シェルスクリプトを実行して関数が正常に動作するかを確認します。エラーハンドリングやログ出力が適切に機能していることをチェックしてください。
この手順を参考にして、共通関数定義クラスをプロジェクトに導入し、スクリプト開発を効率化してください。
実践的な利用方法とサンプルコード
utils.shrcは、シェルスクリプトでよく使われる便利な機能を集めた共通関数集です。これにより、日常的に行うタスクを簡素化し、効率的なスクリプト作成が可能になります。このセクションでは、utils.shrcの関数を実際にどのように活用するかを示すため、いくつかの実践的な利用方法とサンプルコードを紹介します。
utils.shrcには、ファイルバックアップやポートの状態確認、プロセス数の管理など、システム管理で役立つ多くの関数が含まれています。例えば、定期的なバックアップを自動化したり、ネットワークサービスが正常に稼働しているかどうかを簡単にチェックすることができます。これにより、手動で行う作業を減らし、エラーのリスクを低減することができます。
次に、utils.shrcを利用した具体的な使用例を紹介し、どのようにしてシェルスクリプト内でこれらの関数を活用できるかを見ていきましょう。
基本的な使い方
共通関数定義クラス(utils.shrc
)を使用するには、まずそのファイルをプロジェクトに取り込み、source
コマンドで読み込みます。その後、クラス内で定義された関数を簡単に利用することができます。
よくある利用ケース
共通関数定義クラスは、システム管理やバッチ処理など、さまざまな場面で活用できます。以下は、よくある利用ケースの一例です。
- プロセス管理
getProcessCount
を使用して、指定したプロセスが実行中かどうかを確認することができます。例えば、バックグラウンドで実行しているプロセスの数をカウントする場合に便利です。 - ファイル操作
backupFile
関数を使って、ファイルのバックアップを作成することができます。例えば、重要な設定ファイルをバックアップする際に役立ちます。
共通関数定義クラスを導入するメリット
共通関数定義クラスを導入することで、以下のようなメリットがあります。
- コードの再利用性が向上
同じ処理を複数のスクリプトで繰り返し記述する必要がなくなり、コードの再利用性が高まります。例えば、ファイル操作やプロセス管理などの汎用的な処理を共通化できます。 - 保守性が向上
処理を一元管理することができるため、スクリプトが増えてもメンテナンスが容易になります。もし変更が必要になった場合、utils.shrc
を更新するだけで、全スクリプトに反映されます。 - コードの可読性が向上
共通関数を使うことで、各スクリプトがシンプルになり、他の開発者がコードを理解しやすくなります。また、汎用関数の利用によって、スクリプトのロジックが明確に分かりやすくなります。 - エラーハンドリングの標準化
エラーハンドリングを一元管理できるため、異常が発生した場合に適切な対応を統一的に行えます。utils.shrc
では、エラー時にログを記録する機能を提供しており、異常を簡単にトラッキングできます。
トラブルシューティングとFAQ
共通関数定義クラス(utils.shrc
)を利用する中で発生する可能性があるエラーとその対処方法、また、utils.shrc
の拡張方法について説明します。
よくあるエラーと対処方法
- エラー: "Command not found"
原因:utils.shrc
内で使用しているコマンドがシステムにインストールされていない。
対処法: 必要なツール(ps
、grep
、wc
など)がインストールされているかを確認し、インストールしてください。RHEL系の場合:
sudo yum install procps
または、`dnf` を使用する場合(RHEL 8 以降):sudo dnf install procps
- エラー: "Permission denied"
原因: スクリプトを実行する権限が不足している。
対処法: スクリプトに実行権限を付与します。chmod +x /path/to/your/script.sh
- エラー: "No such file or directory"
原因: 指定されたファイルやディレクトリが存在しない。
対処法: ファイルパスが正しいかを再確認し、存在することを確認してください。 - エラー: ロックファイルが削除されていない
原因: 他のプロセスがロックを保持したまま終了した場合。
対処法: 手動でロックファイルを削除するか、スクリプトを修正して適切にロック解除を行うようにします。
共通関数定義クラスの拡張方法
utils.shrc
は汎用的な関数を定義していますが、必要に応じて独自の関数を追加することも可能です。以下の手順で拡張できます。
- 新しい関数を追加する
utils.shrc
に新しい関数を追加することで、特定の用途に合わせた機能を追加できます。# 新しい関数の例
myFunction() {
echo "This is my custom function"
} - 関数をグローバルで使用できるようにする
関数を追加した後、source
コマンドでutils.shrc
を読み込むことで、すべてのシェルスクリプトでその関数を使用できるようにします。source /path/to/your/project/scripts/com/utils.shrc
- エラーハンドリングを追加する
自作の関数にもエラーハンドリングを追加することで、予期しない問題が発生した際にも適切に対応できるようになります。myFunction() {
if [ ! -f "$1" ]; then
echo "Error: File not found!"
exit 1
fi # 関数の処理
} - 既存の関数をカスタマイズする
utils.shrc
にすでに存在する関数を変更して、自分のプロジェクトに合わせた動作をさせることもできます。ただし、他のスクリプトとの互換性を保つために慎重に変更を加えることが重要です。