シンプルな管理用スクリプトの作成

ShellBeginner
オンラインで実践に進む

はじめに

システム管理者は、繰り返し行うチェック作業を小さなシェルスクリプトにまとめることがよくあります。RHCSA スタイルのスクリプト作成において重要なのは、巨大なプログラムを書くことではありません。Bash を安全に活用して、一般的なタスクの自動化、入力の検証、ターゲットに対するループ処理、適切な終了コードの返却、そして他の管理者が理解できる形式での出力を行うことです。

この実験では、ディレクトリの概要をまとめるスクリプトを段階的に作成します。このスクリプトは、ディレクトリパスを受け取り、各パスが使用可能かを確認し、基本的なファイル情報を収集して読みやすい形式で出力し、さらにその内容をログファイルに保存するようにします。

実行可能なスクリプトの作成

このステップでは、サンプルディレクトリを確認し、管理用スクリプトの最初の実行可能なバージョンを作成します。スクリプトは、システムがどのインタープリタを使用すべきかを認識できるように、シバン(shebang)から始める必要があります。

プロジェクトディレクトリに移動します。

cd /home/labex/project

サンプルツリーを確認します。find コマンドでファイルとディレクトリをリストアップし、sort で順序を整えます。

find /home/labex/project/script-practice -maxdepth 2 -print | sort

admin-summary.sh の最初のバージョンを作成します。#!/bin/bash という行は、Linux に対してこのファイルを Bash で実行するように指示します。set -u オプションは、未定義の変数が使用された場合にスクリプトを停止させるため、多くのタイピングミスを防ぐことができます。

cat > /home/labex/project/admin-summary.sh <<'EOF'
#!/bin/bash
set -u

echo "RHCSA admin summary"
echo "RUN_AS=$(id -un)"
echo "HOST=$(hostname -s)"
EOF

スクリプトに実行権限を付与します。実行権限がない場合、ファイルは単なるテキストとして扱われます。

chmod 755 /home/labex/project/admin-summary.sh

スクリプトを実行します。

/home/labex/project/admin-summary.sh

スクリプトのタイトル、現在のユーザー、および短いホスト名が表示されるはずです。正確なホスト名は環境によって異なる場合があります。

ディレクトリ引数の受け取り

このステップでは、位置パラメータを追加します。スクリプトでは $# を使用して引数の数をカウントし、"$@" を使用して渡されたすべての引数をそのまま表現します。

少なくとも 1 つのディレクトリ引数を必須とするバージョンにスクリプトを書き換えます。

cat > /home/labex/project/admin-summary.sh <<'EOF'
#!/bin/bash
set -u

if [ "$#" -eq 0 ]; then
  echo "Usage: $0 DIRECTORY [DIRECTORY...]"
  exit 2
fi

echo "RHCSA admin summary"
echo "RUN_AS=$(id -un)"
echo "HOST=$(hostname -s)"

for target in "$@"; do
  echo "TARGET=$target"
done
EOF

スクリプトの実行権限を維持します。

chmod 755 /home/labex/project/admin-summary.sh

引数なしで実行します。コマンドは使用方法を表示し、終了ステータス 2 を返すはずです。|| 演算子は、左側のスクリプトが失敗したときにのみ右側のコマンドを実行するため、意図的に非ゼロのステータスを表示させることができます。

/home/labex/project/admin-summary.sh || echo "exit status: $?"

次に、2 つのディレクトリ引数を指定して実行します。

/home/labex/project/admin-summary.sh /home/labex/project/script-practice/app /home/labex/project/script-practice/logs

出力には、各引数に対する TARGET= の行が含まれているはずです。

各ターゲットのテストと適切なステータスの返却

このステップでは、各引数に対して条件付きテストを追加します。[ -d "$target" ] というテストは、パスが存在し、かつそれがディレクトリである場合にのみ成功します。

ディレクトリであれば OK を、それ以外であれば MISSING と報告するバージョンにスクリプトを書き換えます。

cat > /home/labex/project/admin-summary.sh <<'EOF'
#!/bin/bash
set -u

if [ "$#" -eq 0 ]; then
  echo "Usage: $0 DIRECTORY [DIRECTORY...]"
  exit 2
fi

echo "RHCSA admin summary"
echo "RUN_AS=$(id -un)"
echo "HOST=$(hostname -s)"

exit_status=0

for target in "$@"; do
  if [ -d "$target" ]; then
    echo "OK $target"
  else
    echo "MISSING $target"
    exit_status=1
  fi
done

exit "$exit_status"
EOF

有効なディレクトリを指定してスクリプトを実行します。最終的な終了ステータスは 0 になるはずです。

/home/labex/project/admin-summary.sh /home/labex/project/script-practice/app
echo "exit status: $?"

存在しないディレクトリを指定して再度実行します。今度はスクリプトが MISSING と表示し、終了ステータス 1 を返すはずです。

/home/labex/project/admin-summary.sh /home/labex/project/script-practice/missing || echo "exit status: $?"

実用的なディレクトリ情報の収集

このステップでは、コマンド置換を追加します。コマンド置換は $() 内のコマンドを実行し、その出力を変数に格納します。

有効なディレクトリごとに、ファイル数、見かけのサイズ、所有者を報告するバージョンにスクリプトを書き換えます。

cat > /home/labex/project/admin-summary.sh <<'EOF'
#!/bin/bash
set -u

if [ "$#" -eq 0 ]; then
  echo "Usage: $0 DIRECTORY [DIRECTORY...]"
  exit 2
fi

echo "RHCSA admin summary"
echo "RUN_AS=$(id -un)"
echo "HOST=$(hostname -s)"

exit_status=0

for target in "$@"; do
  if [ -d "$target" ]; then
    file_count="$(find "$target" -type f | wc -l)"
    size="$(du -sh "$target" | awk '{print $1}')"
    owner="$(stat -c '%U:%G' "$target")"
    echo "OK $target FILES=$file_count SIZE=$size OWNER=$owner"
  else
    echo "MISSING $target"
    exit_status=1
  fi
done

exit "$exit_status"
EOF

用意された 3 つのディレクトリに対してスクリプトを実行します。

/home/labex/project/admin-summary.sh /home/labex/project/script-practice/app /home/labex/project/script-practice/logs /home/labex/project/script-practice/cache

app ディレクトリは FILES=3、logs は FILES=2、cache は FILES=1 と表示されるはずです。

出力のログファイルへの保存

このステップでは、小さなヘルパー関数とログファイルを追加します。関数を使用することでコードの重複を防ぎ、tee -a を使用して出力を表示しながら同じ行をファイルに追記します。

最終バージョンにスクリプトを書き換えます。

cat > /home/labex/project/admin-summary.sh <<'EOF'
#!/bin/bash
set -u

LOG="/home/labex/project/admin-summary.log"
: > "$LOG"

emit() {
  echo "$*" | tee -a "$LOG"
}

if [ "$#" -eq 0 ]; then
  emit "Usage: $0 DIRECTORY [DIRECTORY...]"
  exit 2
fi

emit "RHCSA admin summary"
emit "RUN_AS=$(id -un)"
emit "HOST=$(hostname -s)"

exit_status=0

for target in "$@"; do
  if [ -d "$target" ]; then
    file_count="$(find "$target" -type f | wc -l)"
    size="$(du -sh "$target" | awk '{print $1}')"
    owner="$(stat -c '%U:%G' "$target")"
    emit "OK $target FILES=$file_count SIZE=$size OWNER=$owner"
  else
    emit "MISSING $target"
    exit_status=1
  fi
done

exit "$exit_status"
EOF

2 つの有効なディレクトリと 1 つの存在しないディレクトリを指定して、最終的なスクリプトを実行します。

/home/labex/project/admin-summary.sh /home/labex/project/script-practice/app /home/labex/project/script-practice/logs /home/labex/project/script-practice/missing || echo "exit status: $?"

保存されたログを確認します。

sed -n '1,8p' /home/labex/project/admin-summary.log

ターミナルの出力とログファイルには、同じ概要行が含まれているはずです。ターゲットが 1 つ存在しないため、終了ステータスは 1 になります。

まとめ

実用的な Bash 管理スクリプトを作成しました。シバン、実行権限、位置パラメータ、引数のカウント、ループ、ディレクトリテスト、コマンド置換、明示的な終了ステータス、ヘルパー関数、そしてログファイルの使用方法を学びました。これらは、小規模な RHCSA スタイルの管理タスクにおいて最も役立つスクリプト作成のパターンです。