6.3 関数と実践

Functions and Practical Scripts

関数を使ってコードを再利用可能にする。実践的なスクリプトパターンを紹介する。

関数定義

#!/bin/bash

# 関数定義(2つの書き方)
function greet() {
    echo "Hello, $1!"
}

say_bye() {
    echo "Goodbye, $1!"
}

# 呼び出し
greet "World"
say_bye "World"
# 引数と戻り値
add() {
    local result=$(($1 + $2))
    echo $result  # 出力で値を返す
}

# 呼び出し
sum=$(add 3 5)
echo "Sum: $sum"

# return は終了ステータス(0-255)
check_file() {
    if [ -f "$1" ]; then
        return 0
    else
        return 1
    fi
}

if check_file "test.txt"; then
    echo "File exists"
fi
関数内変数 説明
$1, $2... 関数への引数
$# 引数の数
$@ すべての引数
local var ローカル変数

実践:スクリプトテンプレート

#!/bin/bash
set -euo pipefail  # エラー時停止

# 設定
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
LOG_FILE="/var/log/myscript.log"

# ログ関数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

# エラー処理
error_exit() {
    log "ERROR: $1"
    exit 1
}

# 使用方法
usage() {
    cat << EOF
Usage: $(basename "$0") [OPTIONS] COMMAND

Commands:
    start   Start the service
    stop    Stop the service

Options:
    -h      Show this help
    -v      Verbose mode
EOF
    exit 0
}

# 引数解析
VERBOSE=false
while getopts "hv" opt; do
    case $opt in
        h) usage ;;
        v) VERBOSE=true ;;
        *) usage ;;
    esac
done
shift $((OPTIND - 1))

# メイン処理
main() {
    log "Script started"
    
    case "${1:-}" in
        start)
            log "Starting..."
            ;;
        stop)
            log "Stopping..."
            ;;
        *)
            error_exit "Unknown command: ${1:-}"
            ;;
    esac
    
    log "Script completed"
}

main "$@"

実践例

バックアップスクリプト

#!/bin/bash
SRC="/home/user/data"
DEST="/backup"
DATE=$(date +%Y%m%d)

tar -czf "${DEST}/backup_${DATE}.tar.gz" "$SRC"
find "$DEST" -name "backup_*.tar.gz" -mtime +7 -delete

ログ監視

#!/bin/bash
LOGFILE="/var/log/app.log"
PATTERN="ERROR"

tail -F "$LOGFILE" | while read line; do
    if echo "$line" | grep -q "$PATTERN"; then
        echo "Alert: $line" | mail -s "Error Alert" admin@example.com
    fi
done

一括処理

#!/bin/bash
# すべてのJPGを圧縮
for img in *.jpg; do
    [ -f "$img" ] || continue
    convert "$img" -quality 80 "compressed_$img"
    echo "Processed: $img"
done

デバッグ

# デバッグモード
bash -x script.sh

# スクリプト内で有効化
set -x  # トレース開始
set +x  # トレース終了

# 変数チェック
set -u  # 未定義変数でエラー

# エラー時停止
set -e  # コマンド失敗で停止
set -o pipefail  # パイプ内エラーも検出
出典
[1] Bash Reference Manual - Shell Functions.
[2] Google Shell Style Guide.
[3] Wooledge Bash Guide.