はじめに#
日々の開発・運用業務では、同じコマンドを繰り返し実行したり、複数のコマンドを決まった順序で実行したりする場面が頻繁にあります。このような定型作業を手動で行うと、時間がかかるだけでなく、ヒューマンエラーの原因にもなります。
シェルスクリプトは、これらの定型作業を自動化するための強力なツールです。一連のコマンドをテキストファイルにまとめておけば、1つのコマンドで複雑な処理を実行できます。バックアップ、ログ解析、環境構築など、あらゆる場面でシェルスクリプトは活躍します。
本記事では、シェルスクリプトの基本構造から始め、変数の使い方、コマンドライン引数の処理、終了ステータスとエラーハンドリングまでを体系的に解説します。最後には実用的なスクリプト例を通じて、実際の自動化に役立つ知識を身につけていただきます。
動作確認環境#
本記事のシェルスクリプトは以下の環境で動作確認しています。
| 項目 |
内容 |
| OS |
Ubuntu 24.04 LTS |
| シェル |
bash 5.3 |
| カーネル |
Linux 6.8 |
WSL2、VirtualBox上のLinux環境、macOS(zsh互換モード)、その他の主要ディストリビューション(AlmaLinux、Debian等)でも同様に動作します。
シェルスクリプトとは#
シェルスクリプトとは、シェル(bashなど)が解釈・実行するコマンドをテキストファイルにまとめたものです。通常のコマンドライン操作と同じ構文を使用できるため、特別な言語を覚える必要がありません。
graph LR
A[シェルスクリプト<br/>script.sh] --> B[シェル<br/>bash]
B --> C[コマンド1]
B --> D[コマンド2]
B --> E[コマンド3]
C --> F[実行結果]
D --> F
E --> Fシェルスクリプトの用途#
シェルスクリプトは以下のような用途で広く使われています。
| 用途 |
具体例 |
| システム管理 |
バックアップ、ログローテーション、ディスク監視 |
| 環境構築 |
開発環境のセットアップ、パッケージインストール |
| デプロイ |
アプリケーションのビルド・デプロイ自動化 |
| データ処理 |
ログ解析、CSVファイル加工、レポート生成 |
| バッチ処理 |
定期的なデータ同期、メール送信 |
シェルスクリプトの基本構造#
シェルスクリプトを作成する際に理解しておくべき基本要素を解説します。
shebang(シバン)の役割#
シェルスクリプトの1行目には、通常 shebang(シバン)と呼ばれる特殊な行を記述します。
shebangは #! で始まり、その後にスクリプトを実行するインタープリタのパスを指定します。この行により、OSはスクリプトをどのプログラムで実行すべきかを判断します。
shebangがない場合、スクリプトは現在のシェルで実行されますが、予期しない動作の原因となることがあります。明示的にshebangを記述することをお勧めします。
shebangの書き方#
shebangにはいくつかの書き方があります。
| shebang |
説明 |
#!/bin/bash |
bashを直接指定。最も一般的 |
#!/usr/bin/env bash |
PATHからbashを検索。移植性が高い |
#!/bin/sh |
POSIX互換シェルを使用。移植性重視 |
/usr/bin/env を使う方法は、bashのインストール場所が環境によって異なる場合に有効です。
この書き方では、env コマンドがPATH環境変数からbashを探し出して実行します。
最初のシェルスクリプトを作成する#
実際にシェルスクリプトを作成してみましょう。
1
2
3
4
5
6
|
#!/bin/bash
# 最初のシェルスクリプト
echo "Hello, Shell Script!"
echo "現在の日時: $(date)"
echo "現在のディレクトリ: $(pwd)"
|
このスクリプトを hello.sh という名前で保存します。
# で始まる行(shebangを除く)はコメントとして扱われ、実行時には無視されます。コードの説明や注意事項を記述するために活用してください。
実行権限の付与#
シェルスクリプトを直接実行するには、実行権限を付与する必要があります。
1
2
3
4
5
|
# 実行権限を付与
chmod +x hello.sh
# 権限を確認
ls -l hello.sh
|
出力例:
1
|
-rwxr-xr-x 1 user user 142 Jan 8 10:00 hello.sh
|
x が表示されていれば、実行権限が付与されています。
スクリプトの実行方法#
シェルスクリプトを実行する方法は複数あります。
| 実行方法 |
コマンド例 |
説明 |
| 直接実行 |
./hello.sh |
実行権限が必要 |
| bashで実行 |
bash hello.sh |
実行権限不要 |
| sourceで実行 |
source hello.sh |
現在のシェルで実行 |
1
2
3
4
5
|
# 直接実行(推奨)
./hello.sh
# bashを指定して実行
bash hello.sh
|
出力例:
1
2
3
|
Hello, Shell Script!
現在の日時: 2026年 1月 8日 水曜日 10:00:00 JST
現在のディレクトリ: /home/user/scripts
|
シェルスクリプトの変数#
シェルスクリプトでは、変数を使用してデータを格納し、後から参照できます。
変数の定義と参照#
変数を定義するには、変数名の後に = を付け、値を代入します。= の前後にスペースを入れてはいけません。
1
2
3
4
5
6
7
8
9
10
11
|
#!/bin/bash
# 変数の定義(=の前後にスペースを入れない)
name="太郎"
age=25
current_date=$(date +%Y-%m-%d)
# 変数の参照($を付ける)
echo "名前: $name"
echo "年齢: $age"
echo "日付: $current_date"
|
出力例:
1
2
3
|
名前: 太郎
年齢: 25
日付: 2026-01-08
|
変数名の命名規則#
変数名には以下の規則があります。
| 規則 |
例 |
説明 |
| 英字・数字・アンダースコア |
file_name, count1 |
使用可能な文字 |
| 数字で開始不可 |
1file |
エラーになる |
| 大文字小文字を区別 |
Name と name は別変数 |
慣例として環境変数は大文字 |
1
2
3
4
5
6
7
8
9
|
# 有効な変数名
user_name="John"
fileName="test.txt"
_private_var="secret"
COUNT=10
# 無効な変数名(エラーになる)
# 1st_name="Error" # 数字で開始
# file-name="Error" # ハイフンを含む
|
変数の参照方法#
変数を参照する際は $ を付けます。文字列の中で変数を展開する場合は、波括弧 {} で囲むと安全です。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#!/bin/bash
prefix="file"
suffix="txt"
# 単純な参照
echo $prefix
# 波括弧を使った参照(推奨)
echo ${prefix}
# 文字列と連結する場合は波括弧が必須
echo "${prefix}_backup.${suffix}"
|
出力例:
1
2
3
|
file
file
file_backup.txt
|
波括弧を使わないと、意図しない変数名として解釈される場合があります。
1
2
3
4
5
|
# 波括弧なし - $prefix_backup という変数を参照しようとする
echo "$prefix_backup.txt" # 空になる
# 波括弧あり - 正しく $prefix を参照
echo "${prefix}_backup.txt" # file_backup.txt
|
読み取り専用変数#
readonly コマンドを使うと、変数を読み取り専用にできます。一度設定すると変更できなくなります。
1
2
3
4
5
6
7
|
#!/bin/bash
readonly PI=3.14159
echo "円周率: $PI"
# 以下はエラーになる
# PI=3.14
|
コマンド置換#
コマンドの実行結果を変数に格納するには、$() または バッククォート ` を使用します。
1
2
3
4
5
6
7
8
9
10
11
12
|
#!/bin/bash
# $() を使用(推奨)
current_user=$(whoami)
file_count=$(ls -1 | wc -l)
# バッククォートを使用(古い書き方)
current_dir=`pwd`
echo "ユーザー: $current_user"
echo "ファイル数: $file_count"
echo "ディレクトリ: $current_dir"
|
$() はネストが可能で可読性も高いため、こちらの使用を推奨します。
1
2
3
|
# ネストの例
result=$(echo "Files: $(ls -1 | wc -l)")
echo $result
|
コマンドライン引数の処理#
シェルスクリプトでは、実行時に引数を渡すことができます。これにより、スクリプトの汎用性が大幅に向上します。
位置パラメータ#
スクリプトに渡された引数は、位置パラメータと呼ばれる特殊な変数でアクセスできます。
| パラメータ |
説明 |
$0 |
スクリプト自身の名前 |
$1 |
1番目の引数 |
$2 |
2番目の引数 |
$3 ~ $9 |
3~9番目の引数 |
${10} |
10番目以降の引数(波括弧が必要) |
$# |
引数の個数 |
$@ |
すべての引数(個別に展開) |
$* |
すべての引数(1つの文字列として展開) |
1
2
3
4
5
6
7
8
|
#!/bin/bash
# args_demo.sh - 引数のデモ
echo "スクリプト名: $0"
echo "引数の個数: $#"
echo "1番目の引数: $1"
echo "2番目の引数: $2"
echo "すべての引数: $@"
|
実行例:
1
|
./args_demo.sh apple banana cherry
|
出力:
1
2
3
4
5
|
スクリプト名: ./args_demo.sh
引数の個数: 3
1番目の引数: apple
2番目の引数: banana
すべての引数: apple banana cherry
|
$@ と $* の違い#
$@ と $* はどちらもすべての引数を表しますが、ダブルクォートで囲んだときの動作が異なります。
1
2
3
4
5
6
7
8
9
10
11
12
|
#!/bin/bash
# diff_at_asterisk.sh
echo "--- \$@ の場合 ---"
for arg in "$@"; do
echo "引数: $arg"
done
echo "--- \$* の場合 ---"
for arg in "$*"; do
echo "引数: $arg"
done
|
実行例:
1
|
./diff_at_asterisk.sh "hello world" "foo bar"
|
出力:
1
2
3
4
5
|
--- $@ の場合 ---
引数: hello world
引数: foo bar
--- $* の場合 ---
引数: hello world foo bar
|
"$@" は各引数を個別の要素として保持しますが、"$*" はすべての引数を1つの文字列として結合します。ループ処理では "$@" を使用するのが一般的です。
引数のバリデーション#
スクリプトの堅牢性を高めるため、引数の検証を行うことが重要です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#!/bin/bash
# backup.sh - ファイルバックアップスクリプト
# 引数チェック
if [ $# -lt 1 ]; then
echo "使用方法: $0 <ファイル名>" >&2
exit 1
fi
source_file=$1
# ファイルの存在チェック
if [ ! -f "$source_file" ]; then
echo "エラー: ファイル '$source_file' が見つかりません" >&2
exit 1
fi
# バックアップ実行
backup_file="${source_file}.bak"
cp "$source_file" "$backup_file"
echo "バックアップを作成しました: $backup_file"
|
shiftコマンドによる引数処理#
shift コマンドを使うと、位置パラメータを左にシフトできます。これは多数の引数を順番に処理する際に便利です。
1
2
3
4
5
6
7
8
9
10
11
12
|
#!/bin/bash
# process_files.sh - 複数ファイルの処理
echo "処理対象ファイル数: $#"
while [ $# -gt 0 ]; do
echo "処理中: $1"
# ここでファイルに対する処理を実行
shift # $2が$1に、$3が$2に...とシフト
done
echo "すべてのファイルを処理しました"
|
実行例:
1
|
./process_files.sh file1.txt file2.txt file3.txt
|
出力:
1
2
3
4
5
|
処理対象ファイル数: 3
処理中: file1.txt
処理中: file2.txt
処理中: file3.txt
すべてのファイルを処理しました
|
終了ステータスとエラーハンドリング#
シェルスクリプトでは、コマンドの成功・失敗を終了ステータス(exit status)で判断します。適切なエラーハンドリングは、信頼性の高いスクリプトを作成するために不可欠です。
終了ステータスの基本#
すべてのコマンドは終了時に終了ステータス(0~255の整数)を返します。
| 終了ステータス |
意味 |
| 0 |
成功 |
| 1~125 |
一般的なエラー |
| 126 |
コマンドが実行できない(権限なし等) |
| 127 |
コマンドが見つからない |
| 128+N |
シグナルNで終了 |
直前のコマンドの終了ステータスは、特殊変数 $? で取得できます。
1
2
3
4
5
6
7
8
9
|
#!/bin/bash
# 成功するコマンド
ls /tmp > /dev/null
echo "ls の終了ステータス: $?"
# 失敗するコマンド
ls /nonexistent_directory 2> /dev/null
echo "ls(存在しないディレクトリ)の終了ステータス: $?"
|
出力:
1
2
|
ls の終了ステータス: 0
ls(存在しないディレクトリ)の終了ステータス: 2
|
exitコマンドによる終了#
exit コマンドを使用すると、スクリプトを任意の終了ステータスで終了できます。
1
2
3
4
5
6
7
8
9
10
|
#!/bin/bash
# check_root.sh - root権限チェック
if [ "$(id -u)" -ne 0 ]; then
echo "エラー: このスクリプトはroot権限で実行してください" >&2
exit 1
fi
echo "root権限で実行中です"
exit 0
|
引数なしで exit を呼び出すと、直前のコマンドの終了ステータスでスクリプトが終了します。
条件分岐での終了ステータスの活用#
終了ステータスは条件分岐で直接使用できます。
1
2
3
4
5
6
7
8
9
10
11
12
|
#!/bin/bash
# コマンドの成功・失敗で分岐
if grep -q "error" /var/log/syslog; then
echo "エラーログが見つかりました"
else
echo "エラーログはありません"
fi
# &&(AND)と ||(OR)を使った条件実行
mkdir -p /tmp/test && echo "ディレクトリを作成しました"
rm /nonexistent_file 2>/dev/null || echo "ファイルの削除に失敗しました"
|
&& は左側のコマンドが成功した場合のみ右側を実行し、|| は左側のコマンドが失敗した場合のみ右側を実行します。
set -e によるエラー時の自動終了#
set -e を設定すると、コマンドがエラー(終了ステータスが0以外)を返した時点でスクリプトが自動的に終了します。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#!/bin/bash
set -e # エラー時に即座に終了
echo "処理1: ディレクトリ作成"
mkdir /tmp/myapp
echo "処理2: ファイル作成"
touch /tmp/myapp/config.txt
echo "処理3: 存在しないコマンド(ここでスクリプトが終了)"
nonexistent_command
echo "この行は実行されない"
|
set -u による未定義変数のチェック#
set -u を設定すると、未定義の変数を参照した際にエラーになります。
1
2
3
4
5
6
7
8
|
#!/bin/bash
set -u # 未定義変数の参照をエラーにする
name="Alice"
echo "名前: $name"
# 未定義変数の参照(エラーになる)
echo "年齢: $age"
|
set -o pipefail によるパイプラインエラーの検出#
通常、パイプラインの終了ステータスは最後のコマンドの終了ステータスになります。set -o pipefail を設定すると、パイプライン中のいずれかのコマンドが失敗した場合、その終了ステータスが返されます。
1
2
3
4
5
6
|
#!/bin/bash
set -o pipefail
# パイプライン中のエラーを検出
cat /nonexistent_file | grep "pattern"
echo "終了ステータス: $?" # pipefailがない場合は0、ある場合は1
|
推奨される安全なスクリプトのテンプレート#
堅牢なシェルスクリプトを書くための推奨テンプレートを紹介します。
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
|
#!/bin/bash
set -euo pipefail
# スクリプトの説明
# 使用方法: ./script.sh <引数>
# 定数の定義
readonly SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
readonly SCRIPT_NAME="$(basename "$0")"
# エラーハンドリング関数
error_exit() {
echo "エラー: $1" >&2
exit "${2:-1}"
}
# メイン処理
main() {
# 引数チェック
if [ $# -lt 1 ]; then
error_exit "使用方法: $SCRIPT_NAME <引数>"
fi
# 処理内容をここに記述
echo "処理を開始します: $1"
}
# スクリプトのエントリーポイント
main "$@"
|
trapによるシグナルハンドリング#
trap コマンドを使用すると、シグナルを受け取った際やスクリプト終了時に特定の処理を実行できます。
trapの基本構文#
よく使用されるシグナルは以下のとおりです。
| シグナル |
説明 |
| EXIT |
スクリプト終了時 |
| INT |
Ctrl+C(SIGINT) |
| TERM |
終了要求(SIGTERM) |
| ERR |
コマンドエラー時(set -eと併用) |
一時ファイルのクリーンアップ#
trap の典型的な使用例として、一時ファイルのクリーンアップがあります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#!/bin/bash
set -euo pipefail
# 一時ファイルの作成
TEMP_FILE=$(mktemp)
echo "一時ファイル: $TEMP_FILE"
# スクリプト終了時に一時ファイルを削除
trap 'rm -f "$TEMP_FILE"; echo "クリーンアップ完了"' EXIT
# 一時ファイルを使用した処理
echo "データを書き込み中..." > "$TEMP_FILE"
cat "$TEMP_FILE"
# ここで Ctrl+C を押しても、一時ファイルは削除される
echo "処理完了"
|
複数のシグナルをハンドリング#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#!/bin/bash
cleanup() {
echo "クリーンアップを実行中..."
# リソースの解放処理
rm -f /tmp/myapp_*.tmp
echo "クリーンアップ完了"
}
# 複数のシグナルに対して同じ関数を設定
trap cleanup EXIT INT TERM
echo "処理を開始します(Ctrl+Cで中断可能)"
sleep 10
echo "処理が完了しました"
|
実用的なシェルスクリプト例#
学んだ内容を活用した実用的なスクリプト例を紹介します。
ファイルバックアップスクリプト#
指定したディレクトリを日付付きでバックアップするスクリプトです。
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
|
#!/bin/bash
set -euo pipefail
# バックアップスクリプト
# 使用方法: ./backup.sh <バックアップ対象ディレクトリ> [バックアップ先]
readonly SCRIPT_NAME="$(basename "$0")"
readonly DATE_SUFFIX=$(date +%Y%m%d_%H%M%S)
# ヘルプメッセージ
show_help() {
cat << EOF
使用方法: $SCRIPT_NAME <バックアップ対象> [バックアップ先]
オプション:
-h, --help このヘルプを表示
例:
$SCRIPT_NAME /home/user/documents
$SCRIPT_NAME /var/www /backup
EOF
}
# エラー終了関数
error_exit() {
echo "エラー: $1" >&2
exit 1
}
# メイン処理
main() {
# ヘルプオプションのチェック
if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
show_help
exit 0
fi
# 引数チェック
if [ $# -lt 1 ]; then
show_help
exit 1
fi
local source_dir="$1"
local backup_dir="${2:-/tmp/backup}"
# ソースディレクトリの存在確認
if [ ! -d "$source_dir" ]; then
error_exit "ディレクトリが見つかりません: $source_dir"
fi
# バックアップディレクトリの作成
mkdir -p "$backup_dir"
# バックアップファイル名の生成
local source_name=$(basename "$source_dir")
local backup_file="${backup_dir}/${source_name}_${DATE_SUFFIX}.tar.gz"
# バックアップの実行
echo "バックアップを開始します..."
echo " 対象: $source_dir"
echo " 出力: $backup_file"
tar -czf "$backup_file" -C "$(dirname "$source_dir")" "$source_name"
# 結果の表示
local backup_size=$(ls -lh "$backup_file" | awk '{print $5}')
echo "バックアップが完了しました(サイズ: $backup_size)"
}
main "$@"
|
実行例:
1
|
./backup.sh /home/user/documents /backup
|
出力:
1
2
3
4
|
バックアップを開始します...
対象: /home/user/documents
出力: /backup/documents_20260108_100000.tar.gz
バックアップが完了しました(サイズ: 2.5M)
|
システム情報収集スクリプト#
システムの基本情報を収集して表示するスクリプトです。
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
|
#!/bin/bash
set -euo pipefail
# システム情報収集スクリプト
print_section() {
echo ""
echo "===== $1 ====="
}
get_os_info() {
print_section "OS情報"
if [ -f /etc/os-release ]; then
. /etc/os-release
echo "ディストリビューション: $NAME"
echo "バージョン: $VERSION"
else
echo "OS: $(uname -s)"
fi
echo "カーネル: $(uname -r)"
echo "アーキテクチャ: $(uname -m)"
}
get_cpu_info() {
print_section "CPU情報"
if [ -f /proc/cpuinfo ]; then
local cpu_model=$(grep "model name" /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)
local cpu_cores=$(grep -c "processor" /proc/cpuinfo)
echo "モデル: $cpu_model"
echo "コア数: $cpu_cores"
else
echo "CPU情報を取得できません"
fi
}
get_memory_info() {
print_section "メモリ情報"
if command -v free > /dev/null 2>&1; then
free -h | grep -E "^(Mem|Swap):"
else
echo "メモリ情報を取得できません"
fi
}
get_disk_info() {
print_section "ディスク使用量"
df -h --output=source,size,used,avail,pcent,target | grep -E "^(/dev/|Filesystem)"
}
get_network_info() {
print_section "ネットワーク情報"
if command -v ip > /dev/null 2>&1; then
ip -4 addr show | grep -E "inet " | awk '{print $NF": "$2}'
else
echo "ネットワーク情報を取得できません"
fi
}
main() {
echo "システム情報レポート"
echo "生成日時: $(date '+%Y-%m-%d %H:%M:%S')"
echo "ホスト名: $(hostname)"
get_os_info
get_cpu_info
get_memory_info
get_disk_info
get_network_info
echo ""
echo "===== レポート終了 ====="
}
main
|
ログ監視スクリプト#
特定のキーワードを含むログエントリを監視し、検出時にアラートを出すスクリプトです。
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
|
#!/bin/bash
set -euo pipefail
# ログ監視スクリプト
# 使用方法: ./log_monitor.sh <ログファイル> <検索キーワード>
readonly SCRIPT_NAME="$(basename "$0")"
# 使用方法の表示
usage() {
echo "使用方法: $SCRIPT_NAME <ログファイル> <キーワード>" >&2
exit 1
}
# アラート出力
alert() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] ALERT: $1"
}
# メイン処理
main() {
if [ $# -lt 2 ]; then
usage
fi
local log_file="$1"
local keyword="$2"
# ログファイルの存在確認
if [ ! -f "$log_file" ]; then
echo "エラー: ログファイルが見つかりません: $log_file" >&2
exit 1
fi
echo "ログ監視を開始します"
echo " ファイル: $log_file"
echo " キーワード: $keyword"
echo " 終了するには Ctrl+C を押してください"
echo ""
# tail -f でログを監視し、キーワードを含む行を検出
tail -F "$log_file" 2>/dev/null | while read -r line; do
if echo "$line" | grep -qi "$keyword"; then
alert "キーワード '$keyword' を検出: $line"
fi
done
}
main "$@"
|
実行例:
1
|
./log_monitor.sh /var/log/syslog error
|
シェルスクリプトのベストプラクティス#
信頼性が高く保守しやすいシェルスクリプトを書くためのベストプラクティスをまとめます。
安全なスクリプトの基本設定#
1
2
|
#!/bin/bash
set -euo pipefail
|
| オプション |
効果 |
-e |
コマンドエラー時に即座に終了 |
-u |
未定義変数の参照をエラーにする |
-o pipefail |
パイプライン中のエラーを検出 |
変数の取り扱い#
- 変数はダブルクォートで囲む
1
2
3
4
5
6
7
|
# 良い例
echo "$variable"
cp "$source" "$destination"
# 悪い例(スペースや特殊文字で問題が発生)
echo $variable
cp $source $destination
|
- デフォルト値を設定する
1
2
3
|
# 変数が未定義または空の場合にデフォルト値を使用
name="${1:-default_name}"
config_file="${CONFIG_FILE:-/etc/myapp/config}"
|
- 変数の展開には波括弧を使用
1
2
3
4
5
|
# 推奨
echo "${prefix}_${suffix}"
# 非推奨(意図しない動作の原因になりうる)
echo "$prefix_$suffix"
|
コメントとドキュメント#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#!/bin/bash
#
# スクリプト名: deploy.sh
# 説明: アプリケーションのデプロイを自動化するスクリプト
# 使用方法: ./deploy.sh <環境名> [オプション]
# 作成者: Your Name
# 作成日: 2026-01-08
#
# 関数の説明コメント
# 引数:
# $1 - ファイルパス
# 戻り値:
# 0 - 成功, 1 - 失敗
process_file() {
local file="$1"
# 処理内容
}
|
エラーメッセージは標準エラー出力へ#
1
2
3
4
5
6
7
|
# エラーメッセージは >&2 で標準エラー出力へ
echo "エラー: ファイルが見つかりません" >&2
# 関数化すると便利
error() {
echo "エラー: $*" >&2
}
|
まとめ#
本記事では、シェルスクリプトの基礎から実践的な使い方までを解説しました。
学習した主な内容:
- シェルスクリプトの基本構造: shebang、実行権限、スクリプトの実行方法
- 変数の定義と参照: 命名規則、コマンド置換、変数の安全な参照方法
- コマンドライン引数: 位置パラメータ(
$1、$2、$@)、引数のバリデーション
- 終了ステータスとエラーハンドリング:
$?、exit、set -euo pipefail
- シグナルハンドリング:
trap によるクリーンアップ処理
シェルスクリプトは、一度基本を身につければ、日々の作業効率を大幅に向上させる強力なツールになります。小さなスクリプトから始めて、徐々に複雑な自動化に挑戦してみてください。
次のステップとして、条件分岐(if/case)やループ処理(for/while)、関数定義などの制御構文を学ぶと、より柔軟なスクリプトが作成できるようになります。
参考リンク#