シェルスクリプト入門|Linuxの作業を自動化する基本の書き方【初心者向け】

kento_morota 14分で読めます

「毎日同じコマンドを手動で実行するのが面倒」「サーバーの定期メンテナンスを自動化したい」――こうした課題を解決するのがシェルスクリプトです。

シェルスクリプトとは、Linuxのコマンドを1つのファイルにまとめて連続実行できるようにしたものです。プログラミング経験がなくても、普段使っているコマンドの延長として始められるため、中小企業のIT担当者が最初に覚えるべき自動化技術と言えます。

本記事では、シェルスクリプトの基本構文から実務で使える実例まで、初心者向けにわかりやすく解説します。基本的なLinuxコマンドについてはLinuxコマンド一覧を事前に確認しておくとスムーズです。

シェルスクリプトとは何か

シェルスクリプトの概要と、なぜ業務効率化に有効なのかを理解しましょう。

シェルとシェルスクリプトの関係

シェル(Shell)とは、ユーザーがキーボードから入力したコマンドを解釈し、OSのカーネルに伝える仲介プログラムです。ターミナルでlsやcdなどのコマンドを入力して結果が返ってくるのは、シェルが仲介しているからです。

シェルスクリプトは、このシェルに対する命令をテキストファイルにまとめて記述したものです。手動で一つずつコマンドを入力する代わりに、ファイルを実行するだけで一連の処理が自動的に行われます。

シェルの種類

Linuxにはいくつかのシェルがありますが、最も広く使われているのはBash(Bourne Again Shell)です。

シェル 特徴
bash 最も一般的。多くのディストリビューションでデフォルト
sh POSIX準拠の基本シェル。互換性が高い
zsh 高機能シェル。macOSのデフォルト
fish ユーザーフレンドリーな対話型シェル

本記事ではBashを前提に解説します。

シェルスクリプトのメリット

  • 反復作業の自動化:毎日実行する手順をスクリプト化して時間を節約
  • ミスの防止:手動操作の人的ミスを排除
  • 手順の文書化:スクリプト自体が作業手順書になる
  • 再現性の確保:誰が実行しても同じ結果が得られる
  • 他のツールとの連携cronと組み合わせて定期実行が可能

シェルスクリプトの基本構文

まずはシェルスクリプトの基本的な書き方と実行方法を見ていきましょう。

最初のシェルスクリプト

Vimエディタやnanoで以下の内容のファイルを作成します。

#!/bin/bash
# これはコメントです
echo "Hello, World!"
echo "現在の日時: $(date)"
echo "ホスト名: $(hostname)"

1行目の#!/bin/bashシバン(shebang)と呼ばれ、このスクリプトをBashで実行することを宣言しています。「#」で始まる行はコメントとして無視されます。

実行方法

スクリプトを実行するには、まず実行権限を付与します。

# 実行権限を付与
chmod 755 hello.sh

# 実行
./hello.sh

または、bashコマンドで直接実行する方法もあります。

bash hello.sh

変数の使い方

変数を使うことで、値を保存して再利用できます。

変数の定義と参照

#!/bin/bash

# 変数の定義(=の前後にスペースを入れない)
NAME="田中"
AGE=30
WORK_DIR="/var/www/html"

# 変数の参照($をつける)
echo "名前: $NAME"
echo "年齢: ${AGE}歳"
echo "作業ディレクトリ: $WORK_DIR"

重要:変数定義の=の前後にスペースを入れるとエラーになります。これはシェルスクリプト初心者が最も多く遭遇するミスの一つです。

コマンドの実行結果を変数に格納

#!/bin/bash

# コマンド置換で結果を変数に格納
CURRENT_DATE=$(date +%Y-%m-%d)
DISK_USAGE=$(df -h / | tail -1 | awk '{print $5}')
FILE_COUNT=$(ls /var/log/ | wc -l)

echo "今日の日付: $CURRENT_DATE"
echo "ディスク使用率: $DISK_USAGE"
echo "ログファイル数: $FILE_COUNT"

特殊変数

変数 意味
$0 スクリプト自身のファイル名
$1, $2, ... 引数(1番目、2番目...)
$# 引数の数
$@ すべての引数
$? 直前のコマンドの終了ステータス(0=成功)
$$ 現在のプロセスID
#!/bin/bash
# 引数の使用例 - backup.sh server1 のように実行
echo "スクリプト名: $0"
echo "バックアップ対象: $1"
echo "引数の数: $#"

条件分岐(if文)

条件に応じて処理を分岐させるif文は、シェルスクリプトの基本構文です。

if文の基本構文

#!/bin/bash

FILE="/var/log/syslog"

if [ -f "$FILE" ]; then
    echo "$FILE は存在します"
else
    echo "$FILE は存在しません"
fi

注意[と条件式の間、条件式と]の間にはスペースが必要です。

よく使う条件式

条件式 意味
-f ファイル 通常ファイルが存在する
-d ディレクトリ ディレクトリが存在する
-e パス ファイルまたはディレクトリが存在する
-r ファイル 読み取り可能
-w ファイル 書き込み可能
-x ファイル 実行可能
-z 文字列 文字列が空
-n 文字列 文字列が空でない
数値 -eq 数値 等しい
数値 -ne 数値 等しくない
数値 -gt 数値 より大きい
数値 -lt 数値 より小さい
文字列 = 文字列 文字列が等しい
文字列 != 文字列 文字列が異なる

実用例:ディスク容量チェック

#!/bin/bash

THRESHOLD=80
USAGE=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')

if [ "$USAGE" -gt "$THRESHOLD" ]; then
    echo "警告: ディスク使用率が${USAGE}%です(閾値: ${THRESHOLD}%)"
    echo "不要なファイルの削除を検討してください"
else
    echo "ディスク使用率は${USAGE}%で正常です"
fi

ディスク管理の詳細はディスク管理ガイドをご覧ください。

ループ処理

同じ処理を繰り返し実行するためのループ構文を学びましょう。

forループ

#!/bin/bash

# リストを使ったループ
for SERVER in web01 web02 db01; do
    echo "サーバー $SERVER にping..."
    ping -c 1 "$SERVER" > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        echo "  → $SERVER: OK"
    else
        echo "  → $SERVER: 応答なし"
    fi
done
#!/bin/bash

# 数値の範囲でループ
for i in $(seq 1 5); do
    echo "処理 $i / 5"
done

# ファイルを対象にループ
for FILE in /var/log/*.log; do
    SIZE=$(du -h "$FILE" | awk '{print $1}')
    echo "$FILE: $SIZE"
done

whileループ

#!/bin/bash

# カウンター付きループ
COUNT=1
while [ $COUNT -le 5 ]; do
    echo "カウント: $COUNT"
    COUNT=$((COUNT + 1))
done

# ファイルを1行ずつ読み込む
while IFS= read -r LINE; do
    echo "処理中: $LINE"
done < /etc/hosts

関数の定義と活用

処理をまとめて再利用可能にする関数の書き方です。

関数の基本構文

#!/bin/bash

# 関数の定義
log_message() {
    local TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
    echo "[$TIMESTAMP] $1"
}

check_service() {
    local SERVICE_NAME=$1
    if systemctl is-active --quiet "$SERVICE_NAME"; then
        log_message "$SERVICE_NAME は稼働中です"
        return 0
    else
        log_message "警告: $SERVICE_NAME が停止しています"
        return 1
    fi
}

# 関数の呼び出し
log_message "サービスチェックを開始します"
check_service "nginx"
check_service "mysql"
log_message "サービスチェックが完了しました"

localキーワードを使うと、関数内のみで有効なローカル変数を定義できます。グローバル変数との名前の衝突を防ぐため、関数内の変数にはlocalをつける習慣をつけましょう。

サービス管理に関する詳細はsystemdサービス管理ガイドをご覧ください。

実務で使えるシェルスクリプト実例

中小企業のIT運用で役立つ実践的なスクリプト例を紹介します。

ログファイルの自動ローテーション

#!/bin/bash
# log_rotate.sh - 古いログファイルを圧縮・削除するスクリプト

LOG_DIR="/var/log/myapp"
KEEP_DAYS=30

log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

log_message "ログローテーションを開始します"

# 指定日数より古いログを圧縮
find "$LOG_DIR" -name "*.log" -mtime +7 -not -name "*.gz" -exec gzip {} \;
log_message "7日以上前のログを圧縮しました"

# 指定日数より古い圧縮ログを削除
find "$LOG_DIR" -name "*.gz" -mtime +$KEEP_DAYS -delete
log_message "${KEEP_DAYS}日以上前の圧縮ログを削除しました"

log_message "ログローテーションが完了しました"

このスクリプトをcronに登録すれば、毎日自動でログ管理が行えます。ログ管理の詳細はログ管理ガイドを参照してください。

サーバーヘルスチェック

#!/bin/bash
# health_check.sh - サーバーの状態を確認するスクリプト

REPORT_FILE="/tmp/health_report_$(date +%Y%m%d).txt"

{
    echo "===== サーバーヘルスチェックレポート ====="
    echo "日時: $(date)"
    echo "ホスト名: $(hostname)"
    echo ""

    # CPU使用率
    echo "--- CPU使用率 ---"
    top -bn1 | head -5
    echo ""

    # メモリ使用状況
    echo "--- メモリ使用状況 ---"
    free -h
    echo ""

    # ディスク使用状況
    echo "--- ディスク使用状況 ---"
    df -h
    echo ""

    # 主要サービスの状態
    echo "--- サービス状態 ---"
    for SERVICE in nginx mysql ssh; do
        STATUS=$(systemctl is-active "$SERVICE" 2>/dev/null || echo "未インストール")
        echo "  $SERVICE: $STATUS"
    done
    echo ""

    # 直近のエラーログ
    echo "--- 直近のエラーログ(10件) ---"
    if [ -f /var/log/syslog ]; then
        grep -i "error" /var/log/syslog | tail -10
    fi

} > "$REPORT_FILE"

echo "レポートを $REPORT_FILE に出力しました"

パフォーマンス監視の詳細についてはパフォーマンス監視ガイドをご覧ください。

簡易バックアップスクリプト

#!/bin/bash
# backup.sh - 指定ディレクトリのバックアップ

BACKUP_SOURCE="/var/www/html"
BACKUP_DEST="/backup"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DEST}/web_backup_${DATE}.tar.gz"

# バックアップ先ディレクトリがなければ作成
if [ ! -d "$BACKUP_DEST" ]; then
    mkdir -p "$BACKUP_DEST"
fi

# バックアップ実行
echo "バックアップを開始: $BACKUP_SOURCE → $BACKUP_FILE"
tar czf "$BACKUP_FILE" -C "$(dirname $BACKUP_SOURCE)" "$(basename $BACKUP_SOURCE)"

if [ $? -eq 0 ]; then
    SIZE=$(du -h "$BACKUP_FILE" | awk '{print $1}')
    echo "バックアップ完了: $BACKUP_FILE ($SIZE)"
else
    echo "エラー: バックアップに失敗しました"
    exit 1
fi

# 古いバックアップを削除(30日以上前)
find "$BACKUP_DEST" -name "web_backup_*.tar.gz" -mtime +30 -delete
echo "30日以上前のバックアップを削除しました"

バックアップ戦略の詳細はバックアップ・リストアガイドで解説しています。

シェルスクリプト作成のベストプラクティス

品質の高いシェルスクリプトを書くためのベストプラクティスをまとめます。

エラーハンドリング

#!/bin/bash
set -euo pipefail

# set -e: エラーが発生したら即座にスクリプトを終了
# set -u: 未定義変数の使用をエラーにする
# set -o pipefail: パイプラインのエラーを検知する

スクリプトの先頭にset -euo pipefailを記述することで、予期しないエラーを早期に検知できます。

その他の推奨事項

  • コメントを適切に記述する:処理の意図や前提条件をコメントで残す
  • 変数はダブルクォートで囲む"$VAR"のように囲み、空白を含む値のエラーを防ぐ
  • マジックナンバーは変数化する:設定値はスクリプト先頭で変数として定義する
  • 絶対パスを使うディレクトリ構造を理解し、常に絶対パスで指定する
  • テストしてからcronに登録する:手動実行で動作確認後に自動化する

Claude Codeとの連携

AIコーディングアシスタントのClaude Codeを使えば、シェルスクリプトの作成を効率化できます。「サーバーのヘルスチェックスクリプトを作って」のように自然言語で指示するだけで、実用的なスクリプトのベースを生成できます。コマンドの詳細はClaude Codeコマンド一覧をご覧ください。

まとめ

シェルスクリプトは、Linuxの作業を自動化するための強力なツールです。プログラミング初心者でも、普段使っているコマンドの組み合わせから始められます。

本記事のポイントを振り返ります。

  • シェルスクリプトはコマンドをファイルにまとめて自動実行する仕組み
  • 変数、条件分岐(if)、ループ(for/while)、関数が基本構文
  • ログローテーション、ヘルスチェック、バックアップなど実務での活用範囲が広い
  • set -euo pipefailでエラーハンドリングを強化する
  • cronと組み合わせることで定期実行が可能になる

まずは簡単な処理からスクリプト化を始め、徐々に複雑な自動化に挑戦してみましょう。Linuxの基礎を体系的に学びたい方はLinuxとは?初心者向け解説もあわせてご覧ください。

#シェルスクリプト#Linux#自動化
共有:
無料メルマガ

週1回、最新の技術記事をお届け

AI・クラウド・開発の最新記事を毎週月曜にメールでお届けします。登録は無料、いつでも解除できます。

プライバシーポリシーに基づき管理します

AI活用のヒントをお探しですか?お気軽にご相談ください。

まずは話だけ聞いてもらう