メインコンテンツへスキップ
レッスン 9 / 12推定時間:

エラーハンドリングとデバッグ

シェルスクリプトのエラー処理とデバッグ技術を習得します

このレッスンで学ぶこと

堅牢なシェルスクリプトを作成するには、適切なエラーハンドリングとデバッグ技術が不可欠です。このレッスンでは:

  • 終了ステータスの理解と活用
  • エラートラップとシグナル処理
  • デバッグモードの使い方
  • ログ出力とエラーメッセージ

終了ステータスの基本

終了ステータスの確認

#!/bin/bash

# コマンドの実行と終了ステータスの確認
ls /etc/passwd
echo "終了ステータス: $?"

ls /nonexistent/file
echo "終了ステータス: $?"

# 条件分岐での使用
if grep -q "root" /etc/passwd; then
    echo "rootユーザーが見つかりました"
else
    echo "rootユーザーが見つかりません"
fi
CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$

ファイルツリー

/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log

カスタム終了ステータス

#!/bin/bash

# 関数での終了ステータス
validate_age() {
    local age=$1
    
    if [ -z "$age" ]; then
        echo "エラー: 年齢が指定されていません"
        return 1
    fi
    
    if ! [[ "$age" =~ ^[0-9]+$ ]]; then
        echo "エラー: 数値ではありません"
        return 2
    fi
    
    if [ "$age" -lt 0 ] || [ "$age" -gt 120 ]; then
        echo "エラー: 有効な範囲外です"
        return 3
    fi
    
    echo "年齢 $age は有効です"
    return 0
}

# スクリプト全体の終了
if ! validate_age "$1"; then
    exit $?
fi

エラーハンドリングのベストプラクティス

set オプションの活用

#!/bin/bash

# エラー時に即座に終了
set -e

# 未定義変数の使用をエラーに
set -u

# パイプラインのエラーを検出
set -o pipefail

# すべてを一度に設定
set -euo pipefail

# 実行例
echo "スクリプト開始"
ls /nonexistent/file  # ここでスクリプトが終了
echo "この行は実行されません"
CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$

ファイルツリー

/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log

エラートラップ

#!/bin/bash

# エラー発生時の処理を定義
error_handler() {
    local line_no=$1
    echo "エラーが発生しました (行: $line_no)"
    echo "スタックトレース:"
    local i=0
    while caller $i; do
        ((i++))
    done
    exit 1
}

# ERRシグナルをトラップ
trap 'error_handler $LINENO' ERR

# クリーンアップ処理
cleanup() {
    echo "クリーンアップ処理を実行..."
    rm -f /tmp/tempfile.$$
}

# 終了時の処理
trap cleanup EXIT

# メイン処理
echo "処理を開始します"
touch /tmp/tempfile.$$
ls /nonexistent/file  # エラーが発生
echo "この行は実行されません"

デバッグ技術

デバッグモード

#!/bin/bash

# デバッグモードを有効化
set -x  # 実行するコマンドを表示

# または
#!/bin/bash -x

# 部分的なデバッグ
set +x  # デバッグモードを無効化
echo "通常の実行"
set -x  # デバッグモードを有効化
echo "デバッグ対象の処理"
set +x  # デバッグモードを無効化
CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$

ファイルツリー

/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log

ログ出力関数

#!/bin/bash

# ログレベルの定義
readonly LOG_LEVEL_ERROR=1
readonly LOG_LEVEL_WARN=2
readonly LOG_LEVEL_INFO=3
readonly LOG_LEVEL_DEBUG=4

# 現在のログレベル
LOG_LEVEL=${LOG_LEVEL:-$LOG_LEVEL_INFO}

# ログ出力関数
log() {
    local level=$1
    shift
    local message="$@"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    case $level in
        $LOG_LEVEL_ERROR)
            [ $LOG_LEVEL -ge $LOG_LEVEL_ERROR ] && echo "[$timestamp] ERROR: $message" >&2
            ;;
        $LOG_LEVEL_WARN)
            [ $LOG_LEVEL -ge $LOG_LEVEL_WARN ] && echo "[$timestamp] WARN: $message" >&2
            ;;
        $LOG_LEVEL_INFO)
            [ $LOG_LEVEL -ge $LOG_LEVEL_INFO ] && echo "[$timestamp] INFO: $message"
            ;;
        $LOG_LEVEL_DEBUG)
            [ $LOG_LEVEL -ge $LOG_LEVEL_DEBUG ] && echo "[$timestamp] DEBUG: $message"
            ;;
    esac
}

# 使用例
log $LOG_LEVEL_INFO "スクリプトを開始しました"
log $LOG_LEVEL_DEBUG "変数の値: VAR=$VAR"
log $LOG_LEVEL_ERROR "ファイルが見つかりません"

実践的なエラーハンドリング

CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$

ファイルツリー

/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log

デバッグのヒントとコツ

変数の内容を確認

#!/bin/bash

# 変数の値を表示
debug_var() {
    local var_name=$1
    local var_value=${!var_name}
    echo "[DEBUG] $var_name='$var_value'" >&2
}

# 使用例
MY_VAR="test value"
debug_var MY_VAR

# 配列の内容を表示
debug_array() {
    local array_name=$1
    local array_ref="${array_name}[@]"
    echo "[DEBUG] $array_name=(${!array_ref})" >&2
}

MY_ARRAY=(one two three)
debug_array MY_ARRAY

アサーション

#!/bin/bash

# アサーション関数
assert() {
    local condition="$1"
    local message="${2:-Assertion failed}"
    
    if ! eval "$condition"; then
        echo "ASSERTION ERROR: $message" >&2
        echo "Condition: $condition" >&2
        caller 0 >&2
        exit 1
    fi
}

# 使用例
value=10
assert "[ $value -gt 0 ]" "値は正の数である必要があります"
assert "[ -f /etc/passwd ]" "/etc/passwdファイルが存在する必要があります"

まとめ

このレッスンでは、シェルスクリプトのエラーハンドリングとデバッグについて学びました:

  • 終了ステータス: コマンドの成功/失敗を判定
  • エラーハンドリング: set オプション、トラップ、エラー処理
  • デバッグ技術: デバッグモード、ログ出力、変数確認
  • 堅牢な実装: 入力検証、クリーンアップ、エラーメッセージ

これらの技術により、信頼性の高いプロダクションレベルのスクリプトを作成できます。

次のステップ

次のレッスンでは、これまでに学んだ知識を活用して、実践的なバックアップスクリプトを作成します。

さらに学習を続けるには

素晴らしい学習ペースです!次のレッスンに進むには、無料会員登録をお願いします。無料会員では各コース3レッスンまで学習できます。

無料で続きを学ぶ

各コース3レッスンまで学習可能

学習進捗の自動保存

コース修了証明書の発行