シェルスクリプトの基礎

※本記事はプロモーションを含みます。
シェルスクリプト(とくにBash)は、インフラエンジニアの日常業務を大きく効率化できるスキルとされています。サーバー監視・バックアップ・ログ管理など、繰り返し行う作業をスクリプト化することで、ヒューマンエラーを減らし、夜間・休日の自動運用も実現できます。本記事では、基礎文法から実務スクリプトの書き方・cronによる自動実行まで、段階的に解説します。読了目安は約20分です。
シェルスクリプトの基礎
まずは「シェルとは何か」から確認します。シェルはユーザーの入力をOSカーネルに橋渡しするプログラムです。複数のコマンドをテキストファイルにまとめたものが「シェルスクリプト」で、実行するたびに同じ処理を再現できます。
代表的なシェルの種類
| シェル | 特徴 | 主な利用場面 |
|---|---|---|
| bash | Linuxの標準。機能が豊富 | ほぼすべてのLinuxサーバー |
| sh | 互換性重視。機能は限定的 | 移植性が必要なスクリプト |
| zsh | 補完機能が強力 | macOS・開発者の対話的利用 |
LPIC試験でも頻出なのがbashです。本記事ではbashを前提として解説します。
最初のスクリプト作成
スクリプトファイルを作成する手順は以下の通りです。
- ファイルを作成:viやnanoなどのエディタで新規ファイルを開く
- シバン行を1行目に記述:
#!/bin/bash— このファイルをbashで実行することを指定する重要な行 - コマンドを記述:実行したい処理を順番に並べる
- 実行権を付与:
chmod +x script.sh - 実行:
./script.sh
変数と文字列操作
変数はデータを一時的に格納する領域です。変数名=値の形式で定義し、参照するときは$変数名と書きます。
#!/bin/bash
SERVER_NAME="web-server-01"
PORT=8080
BACKUP_PATH="/var/backups"
echo "サーバー: $SERVER_NAME"
echo "ポート: $PORT"
# コマンド置換でファイル名を動的生成
FULL_PATH="${BACKUP_PATH}/${SERVER_NAME}-$(date +%Y%m%d).tar.gz"
echo "バックアップ先: $FULL_PATH"
$(コマンド)のように書くとコマンド置換が使えます。コマンドの実行結果を変数や文字列に埋め込む際に頻用されるテクニックとされています。
制御構文の書き方
変数とともに制御構文(条件分岐・ループ・関数)を覚えることで、実用的なスクリプトが書けるようになります。
条件分岐(if文)
ディスク使用率の閾値チェックや、ファイルの存在確認など、実務でよく使うパターンを紹介します。
#!/bin/bash
# ファイル存在チェック
if [ -f "/etc/passwd" ]; then
echo "/etc/passwd が見つかりました"
else
echo "/etc/passwd が見つかりません"
fi
# ディスク使用率の警告
DISK_USAGE=85
if [ $DISK_USAGE -gt 80 ]; then
echo "警告:ディスク使用率 ${DISK_USAGE}%"
elif [ $DISK_USAGE -gt 60 ]; then
echo "注意:ディスク使用率 ${DISK_USAGE}%"
else
echo "正常:ディスク使用率 ${DISK_USAGE}%"
fi
条件判定でよく使うオプションをまとめます。
| オプション | 意味 |
|---|---|
-f | 通常ファイルとして存在するか |
-d | ディレクトリとして存在するか |
-e | ファイル・ディレクトリのいずれかとして存在するか |
-gt / -lt / -eq | 数値の大小・等値比較 |
-z | 文字列が空か |
ループ処理の書き方
複数のサーバーに同じ処理を繰り返す場合、forループが効果的です。$?は直前のコマンドの終了ステータス(成功:0、失敗:0以外)を格納する特殊変数です。
#!/bin/bash
SERVERS=("web01" "web02" "web03" "db01")
for server in "${SERVERS[@]}"; do
ping -c 1 "$server" > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "OK: $server は応答中"
else
echo "NG: $server は応答なし"
fi
done
# whileループ:カウンター例
COUNT=1
while [ $COUNT -le 5 ]; do
echo "カウント: $COUNT"
COUNT=$((COUNT + 1))
done
関数の定義と活用
処理のまとまりを「関数」として定義すると、コードの再利用性が高まり、メンテナンスも容易になります。関数は呼び出す前に定義する必要があります。
#!/bin/bash
# ログ出力関数
log_info() {
echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') $1"
}
log_error() {
echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $1" >&2
}
# バックアップ処理を関数化
backup_directory() {
local src_dir="$1"
local dest_dir="$2"
if [ ! -d "$src_dir" ]; then
log_error "ソースディレクトリが存在しません: $src_dir"
return 1
fi
tar -czf "${dest_dir}/backup-$(date +%Y%m%d%H%M%S).tar.gz" "$src_dir"
log_info "バックアップ完了: $src_dir → $dest_dir"
}
# 関数を呼び出す
log_info "スクリプト開始"
backup_directory "/var/www/html" "/var/backups"
log_info "スクリプト終了"
localを使うと変数のスコープを関数内に限定できます。グローバル変数との衝突を避けるために積極的に活用することが推奨されています。
実務スクリプト実例集
基礎文法を押さえたら、実際の業務を想定したスクリプトに取り組むと習得が加速します。ここでは現場でよく使われるパターンを3つ紹介します。
サーバー監視スクリプト
複数サーバーのディスク使用率をSSH経由で収集し、閾値超過時にメール通知するスクリプトです。
#!/bin/bash
SERVERS=("192.168.1.10" "192.168.1.11" "192.168.1.12")
ALERT_EMAIL="admin@example.com"
THRESHOLD=80
for server in "${SERVERS[@]}"; do
# SSH接続確認(タイムアウト5秒)
ssh -o ConnectTimeout=5 "$server" exit > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "接続不可: $server"
continue
fi
# ディスク使用率を取得
DISK=$(ssh "$server" 'df / | awk "NR==2 {gsub(/%/,\"\"); print \$5}"')
if [ "$DISK" -gt "$THRESHOLD" ]; then
MSG="$server のディスク使用率が ${DISK}% に達しています"
echo "$MSG"
echo "$MSG" | mail -s "[Alert] Disk: $server" "$ALERT_EMAIL"
else
echo "正常: $server ${DISK}%"
fi
done
ログバックアップスクリプト
30日以上更新のないログファイルを圧縮・保存します。findコマンドの-mtimeオプションで古いファイルを絞り込めます。
#!/bin/bash
LOG_DIR="/var/log/application"
BACKUP_DIR="/var/backups/logs"
RETENTION_DAYS=30
# バックアップ先がなければ作成
[ ! -d "$BACKUP_DIR" ] && mkdir -p "$BACKUP_DIR"
find "$LOG_DIR" -name "*.log" -type f -mtime +"$RETENTION_DAYS" | while read -r logfile; do
BASENAME=$(basename "$logfile")
ARCHIVE="${BACKUP_DIR}/${BASENAME%.log}-$(date +%Y%m%d).log.gz"
gzip -c "$logfile" > "$ARCHIVE"
if [ $? -eq 0 ]; then
echo "圧縮完了: $ARCHIVE"
else
echo "エラー: $logfile の圧縮に失敗" >&2
fi
done
echo "バックアップ総容量: $(du -sh "$BACKUP_DIR" | awk '{print $1}')"
エラーハンドリングの実装
本番環境で使うスクリプトには、エラー発生時の処理が必須とされています。set -eとtrapを組み合わせることで、途中でエラーが起きても後処理を実行できます。
#!/bin/bash
# エラーが発生したら即座に終了
set -e
# 未定義変数をエラーとして扱う
set -u
TMPFILE=$(mktemp)
# 終了時(正常・異常どちらでも)に一時ファイルを削除
cleanup() {
rm -f "$TMPFILE"
echo "後処理を実行しました"
}
trap cleanup EXIT
echo "処理中..." > "$TMPFILE"
# ここで何かエラーが発生しても cleanup が呼ばれる
cat "$TMPFILE"
echo "処理完了"
set -eはスクリプト全体に適用されるため、個別にエラーを無視したいコマンドには コマンド || true のように書くことが推奨されています。
cronで自動実行する
作成したスクリプトを決まった時刻に自動実行するには、cronデーモンを使います。インフラエンジニアの日常業務で欠かせない設定のひとつとされています。
crontabの書き方
crontab -eコマンドで設定ファイルを編集します。記述形式は以下の通りです。
# 分 時 日 月 曜日 コマンド 0 2 * * * /usr/local/bin/backup.sh
各フィールドの範囲は次の通りです。
| フィールド | 範囲 | 説明 |
|---|---|---|
| 分 | 0〜59 | 実行時刻の分 |
| 時 | 0〜23 | 実行時刻の時 |
| 日 | 1〜31 | 月の日付 |
| 月 | 1〜12 | 月 |
| 曜日 | 0〜7 | 0と7が日曜日 |
よく使うcron設定例
# 毎日午前2時にバックアップ 0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1 # 毎週日曜の午前3時にメンテナンス 0 3 * * 0 /usr/local/bin/weekly_maintenance.sh # 毎月1日の午前1時にレポート生成 0 1 1 * * /usr/local/bin/monthly_report.sh # 平日(月〜金)午前9時に死活監視 0 9 * * 1-5 /usr/local/bin/daily_check.sh # 15分ごとに実行 */15 * * * * /usr/local/bin/frequent_task.sh
>> /var/log/backup.log 2>&1のようにリダイレクトを付けると、標準出力と標準エラー出力の両方をログファイルに書き出せます。cronはメール送信環境が整っていないとエラーに気づきにくいため、ログ出力を設定することが強く推奨されています。
実行ログの確認方法
# cronの実行ログを確認(Debian/Ubuntu系) grep CRON /var/log/syslog # RHEL/CentOS系 tail -f /var/log/cron # 登録済みのcronジョブ一覧 crontab -l
よくある質問と解答
スクリプト実行時の権限エラーが出ます
よくあるのが「Permission denied」エラーです。原因としては、ファイルに実行権がないことが考えられます。chmod +x スクリプト名で実行権を追加してください。また、スクリプト内の#!/bin/bashの記述が間違っていないか確認も重要です。
シェルスクリプトとは別の環境で実行したい
Linuxサーバーはもちろん、macOS・Windows(WSL2経由)でも同じスクリプトが使えます。ポータビリティが求められる場合は、#!/bin/shで記述し、POSIX互換性を確保することが推奨されています。ただし、bash固有の機能(配列・拡張正規表現など)は使えなくなるため、互換性と機能のバランスを取ることが大切です。
実行結果をログに残したい
cronジョブや自動化スクリプトはログ出力が必須です。コマンド >> /var/log/mylog.log 2>&1>(追記)を使うと、複数回実行時に履歴が保持されます。2>&1は標準エラー出力も一緒に記録するための指定です。
複数行の入力をスクリプトに渡す方法
ヒアドキュメント(here document)という機能を使うことで実現できます。<< EOFとEOFで囲まれた部分がコマンドへの入力になります。SQLコマンドやAPIリクエストなどで頻用されるテクニックです。
トラブルシューティング実例
スクリプトが想定と異なる動作をする場合
デバッグモードを有効にすることで、実行される各コマンドを確認できます。bash -x スクリプト.shとすると、各行の実行内容とその結果が表示されるため、問題箇所を特定しやすくなります。
環境変数が読み込まれていない
cronで実行するスクリプトは、対話的シェルの環境変数が引き継がれないことがあります。解決策としては、スクリプト内で環境変数を明示的に指定する、またはsourceコマンドで設定ファイルを読み込むことが考えられます。
学習ロードマップと活用場面
シェルスクリプトは「書いた量」に比例してスキルが上がるとされています。段階的に取り組むことで、無理なくレベルアップできます。
習得ステップの目安
- 初級(1〜2ヶ月):変数・if文・forループ・簡単なファイル操作スクリプトの作成
- 中級(2〜3ヶ月):while・関数・パイプライン・コマンド置換を活用した実務的スクリプト
- 上級(3ヶ月以降):set -e/trap によるエラー処理・複数サーバー展開・cronによる完全自動化
セキュリティ上の注意点
本番環境でスクリプトを運用する際は、以下の点に配慮することが推奨されています。
- 入力値の検証:外部から受け取る引数は必ずバリデーションを行う。特にユーザー入力をコマンドラインに直接渡さない
- ファイル権限の制限:スクリプトへのアクセスは
chmod 750などで必要最小限に絞る。機密情報を含む場合はchmod 700(所有者のみ実行可)を推奨 - 絶対パスの使用:
/bin/rmのように絶対パスを指定することで意図しないコマンド実行を防ぐ。PATHの操作に依存しない - 機密情報の管理:パスワードや鍵情報はスクリプト内に直書きせず、環境変数や専用の設定ファイルから読み込む
- 入出力のサニタイズ:特に
evalやexecを使う場合は、入力値の検証を厳密に行う
本番運用での実装例
以下は、セキュリティ対策を施した本番環境対応スクリプトの実装例です。
#!/bin/bash
# セキュリティオプション
set -euo pipefail
# 未定義変数を検出
IFS=$'\n\t'
# ログ関数(タイムスタンプ付き)
readonly LOG_FILE="/var/log/secure_script.log"
log_info() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1" | tee -a "$LOG_FILE"
}
log_error() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1" | tee -a "$LOG_FILE" >&2
}
# 入力値の検証
validate_input() {
local input="$1"
# 英数字とハイフン・アンダースコアのみ許可
if ! [[ "$input" =~ ^[a-zA-Z0-9_-]+$ ]]; then
log_error "無効な入力: $input"
exit 1
fi
echo "$input"
}
# 使用例
SERVER_NAME=$(validate_input "${1:-}")
log_info "処理開始: $SERVER_NAME"
# 機密情報は環境変数から読み込む
DB_PASS="${DB_PASSWORD:-}"
if [ -z "$DB_PASS" ]; then
log_error "DB_PASSWORD環境変数が設定されていません"
exit 1
fi
# 処理実行
# ...(本処理)...
log_info "処理完了: $SERVER_NAME"
実務での応用範囲
シェルスクリプトは単なる学習対象ではなく、現場での様々なシーンで活躍するスキルです。バックアップの自動化・サーバーメトリクス収集・システムパッチの一括適用・アプリケーション起動スクリプトなど、運用業務のあらゆる場面で応用できます。また、Terraformなどのインフラコード管理ツールのプロビジョニング後のセットアップスクリプトとしても活躍するため、クラウドインフラ構築を行う際にも欠かせないスキルとされています。
他システムとの連携
シェルスクリプトは単体で完結するのではなく、監視ツール(Nagios・Zabbix・Prometheus)や構成管理ツール(Ansible・Chef・Puppet)の実行エンジンとしても機能します。これらのツールから呼び出されるカスタム制御スクリプトを書く能力があれば、より複雑な自動化シーンに対応できることが知られています。
資格学習との相乗効果
LPIC Level1(試験101・102)ではシェルスクリプトの基礎構文が出題範囲に含まれます。資格学習でコマンドの仕組みを理解しながらスクリプトを書く練習を組み合わせると、相乗効果が得られるとされています。また、CI/CDパイプラインやクラウド自動化(AWS Lambda・Azure Functions)にもシェルスクリプトの知識が応用できるため、DevOpsやSREを目指すエンジニアにとっても重要なスキルと位置づけられています。
本記事のまとめ
シェルスクリプト(Bash)はインフラエンジニアの日常業務を大幅に効率化し、ヒューマンエラーを削減する上で欠かせないスキルです。本記事では以下の内容をカバーしました。
- 基礎知識:シェルの概要・最初のスクリプト作成・変数・文字列操作
- 制御構文:if文・forループ・whileループ・関数定義
- 実務的な実装例:サーバー監視・ログバックアップ・エラーハンドリング
- 自動実行の設定:cronデーモンを使った定期実行・ログ確認
- セキュリティ対策:入力検証・ファイル権限・機密情報管理・本番運用スクリプト例
- トラブルシューティング:よくあるエラーと対処法・デバッグモード・FAQ
これらの知識は「知っているだけ」では役に立ちません。実際にサーバーに接続して、スクリプトを書き、エラーに直面して、解決していくというプロセスを繰り返すことで初めてスキルになると考えられています。
次のステップ
本記事で学んだ基礎的な文法を定着させたら、以下の実践的な課題に挑戦することをお勧めします。
- 自分が日常的に行っている作業をスクリプト化し、実際に自動化してみる
- 既存のシェルスクリプトを読む訓練を積み、プロのコードから学ぶ
- 複数のシェルスクリプトを組み合わせた複合的な処理の実装に取り組む
- LPIC試験の対策として、標準化された文法(POSIX sh対応)の習得を深める
インフラエンジニアとしてのキャリアを築く過程で、シェルスクリプトのスキルは確実に仕事の質と効率を大きく左右する要素になるでしょう。今すぐスクリプトを書き始め、着実なレベルアップを目指してください。
著者プロフィール
吉田たかし|現役ITエンジニア・IT講師
- インフラエンジニアとして14年以上の現場経験
- 資格:CCNP・CCNA・LPIC-1・Azure Fundamentals保有
- 複数のSES現場でシステム構築・運用・保守に従事
- 2026年7月よりフリーランスIT講師として本格始動予定
Infra Academy からのメッセージ
Infra Academy では、インフラ系ITエンジニアを目指す方・キャリアアップを検討している現役エンジニアの方を対象に、実務直結の学習サポートを提供しています。
- CCNA・LPIC・AWS認定などの資格取得サポート
- システム構築・運用スキルの実践指導
- 転職・フリーランス独立の相談支援
「何から始めればいいかわからない」「現在のスキルレベルを確認したい」という方は、まず無料相談をご利用ください。オンラインで全国対応しています。
免責事項
本記事の情報は執筆時点のものです。資格試験の合格・年収は個人差があります。
この記事で学んだスキルをさらに深めたい方へ
Linuxの知識をさらに深めたい方はこちらの技術書がおすすめです。コマンドラインからサーバー管理まで網羅しています。
Amazonアソシエイトプログラムを利用しています。
本記事はRoute Bloom編集部が公式ドキュメント・技術仕様書の一次情報をもとに作成しています。ITインフラ・技術情報は急速に変化するため、実装前に最新の公式ドキュメントをご確認ください。情報の正確性には万全を期していますが、最新情報は各公式サイトをご確認ください。
本記事はRoute Bloom編集部が各ベンダー公式ドキュメント・エンジニア監修をもとに作成しています。インフラ・クラウド構築は環境により異なります。本番環境への適用前に必ずテストを実施してください。情報の正確性には万全を期していますが、最新情報は各公式ドキュメントをご確認ください。
本記事はRoute Bloom編集部が各ベンダー・技術標準の公式ドキュメントをもとに作成しています。 インフラ・クラウド技術に関する最終判断は実際の環境・バージョンで検証のうえ実施してください。 情報の正確性には万全を期していますが、最新情報は各公式ドキュメントをご確認ください。
編集ポリシー:この記事は、Route Bloom の編集チームが最新情報を元に執筆・監修しています。情報の正確性を保つために定期的な見直しを行っています。




