シェルスクリプト

安全なスクリプトと定期実行

失敗を見逃さず、入力を確認し、ログを残すスクリプトの考え方を学びます。

シェルスクリプト入門の講座一覧

01

setで失敗を扱う

自動実行するスクリプトでは、途中のコマンドが失敗したのに最後だけ成功してしまう状態を避けたいことがあります。代表的な設定を確認します。

設定意味注意点
set -e失敗したコマンドの後で終了ifの条件など、失敗が想定内の処理もある
set -u未定義変数をエラーにする任意の変数には初期値やデフォルト値を用意する
set -o pipefailパイプ途中の失敗も検出検索結果が空になる処理の終了コードを確認する
基本設定BASH
#!/usr/bin/env bash
set -Eeuo pipefail

printf 'チェックを開始します。\n'
実行結果OUTPUT
チェックを開始します。

便利な設定ですが、意味を理解せずに追加すると、検索結果がない場合など正しい分岐まで失敗扱いにすることがあります。小さな例で挙動を確かめてから使います。

02

入力値と対象を検証する

ユーザーが渡したパスやオプションは、存在、種類、読み書き権限を確認します。バックアップ元と保存先が同じでないかも、実務では確認したい条件です。

check.shBASH
source_dir="${1:-}"
if [[ -z "$source_dir" || ! -d "$source_dir" ]]; then
    printf 'ディレクトリを指定してください。\n' >&2
    printf '使い方: %s ディレクトリ\n' "$0" >&2
    exit 2
fi
printf '対象: %s\n' "$source_dir"
実行コマンドCOMMAND
bash check.sh data
実行結果OUTPUT
対象: data

${1:-}は1番目の引数がなければ空文字にする書き方です。未定義変数をエラーにするset -uと組み合わせるときに役立ちます。

03

trapで後処理を登録する

一時ファイルを作った場合、成功時だけでなく途中で失敗した場合も削除したいことがあります。trapに終了時の処理を登録します。

一時ファイルを片付けるBASH
temp_file=$(mktemp)
cleanup() {
    rm -f "$temp_file"
}
trap cleanup EXIT

printf 'temporary data\n' > "$temp_file"
cat "$temp_file"
実行結果OUTPUT
temporary data

mktempは一時ファイルを作り、そのパスを返します。trap cleanup EXITを登録したあとなら、処理が終わるときにcleanupが呼ばれます。削除対象は固定値にせず、作成したファイルだけを変数で指定します。

04

ログと標準エラーを分ける

定期実行では、いつ何をしたかを後から確認できるようにログを残します。通常の結果とエラーを分け、日時も一緒に記録します。

ログ関数BASH
log_file='script.log'
log() {
    printf '[%s] %s\n' "$(date '+%F %T')" "$*" | tee -a "$log_file"
}
fail() {
    printf '[%s] ERROR: %s\n' "$(date '+%F %T')" "$*" >&2
    exit 1
}

log '処理を開始しました。'
[[ -d data ]] || fail 'dataがありません。'
ログ例OUTPUT
[2026-10-09 10:00:00] 処理を開始しました。

ログへ個人情報や秘密情報をそのまま書かないようにします。パスワードやアクセストークンは、コマンドライン引数やログへ出さない設計にします。

05

ShellCheckで静的に確認する

ShellCheckは、シェルスクリプトのよくある問題を静的に指摘するツールです。未引用の変数や、意図しない代入などを実行前に発見できます。

backup.shBASH
#!/usr/bin/env bash
source="source file.txt"
target="backup.txt"
cp $source $target
ShellCheckを実行COMMAND
shellcheck backup.sh
ShellCheckの出力例OUTPUT
In backup.sh line 4:
  cp $source $target
     ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting.
             ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting.

指摘は必ず理由を読んでから直します。すべての警告を機械的に無視するのではなく、引用符を付けることで何が安全になるのかを理解します。

06

定期実行の前に確認する

cronなどで定期実行すると、対話シェルと環境変数や現在地が異なります。相対パスに頼らず、実行ファイル内で作業場所やログの場所を明示します。

スクリプト自身の場所を基準にするBASH
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
log_file="$script_dir/cron.log"
printf '[%s] started\n' "$(date '+%F %T')" >> "$log_file"
cat "$log_file"
実行結果OUTPUT
[2026-10-09 23:04:20] started

登録前に、手動で何度も実行し、入力がない環境でも動くか、終了ステータスが適切か、ログだけで原因を追えるかを確認します。実行間隔やタイムゾーンも運用環境で確認します。

07

練習:安全な確認スクリプト

引数で受け取ったディレクトリについて、存在確認、ファイル数表示、ログ保存を行うスクリプトを作ってください。

inspect.shBASH
#!/usr/bin/env bash
set -u

target="${1:-}"
if [[ -z "$target" || ! -d "$target" ]]; then
    printf '使い方: %s ディレクトリ\n' "$0" >&2
    exit 2
fi

count=$(find "$target" -type f | wc -l)
printf '[%s] %s のファイル数: %s\n' \
    "$(date '+%F %T')" "$target" "$count"
実行例COMMAND / OUTPUT
bash inspect.sh data
[2026-10-09 10:10:00] data のファイル数: 2

次は総合練習問題で、これまでの内容を組み合わせます。