📄

Linuxで、複数コマンドを一つずつ確認しながら実行するスクリプト

2024/05/05に公開

はじめに

マシンの管理などで、定期的に同じコマンド群を実行することがあります。
手順書のファイルからコマンドを一つずつコピペして結果を確認しているのですが、手間がかかりますし、順序を間違えたりするリスクもあります。

そのため、複数コマンドをループしながら、一つずつ実行確認していくスクリプトを作ってみました。

概要

以下の動きをします。

  • 複数コマンドを改行で区切ったファイルを、スクリプトファイル実行時に引き渡して使います。
  • 最初に対象のコマンドとインデックス番号を表示して、何番目から始めるかを指定します。
  • 各コマンド実行時は、コマンドの文字列を表示し、実行する/しない を指示します。
    • 実行しない を指示した時点でスクリプトを終了します。

ファイルと実行

まずはスクリプトファイルです。

execute_commands.sh
#!/bin/bash

# スクリプト実行時にファイルパスを引数として受け取る
if [ $# -ne 1 ]; then
    echo "Usage: $0 <commands_file>"
    exit 1
fi

# 引数で指定されたファイルの各行を配列に取り込む
mapfile -t commands < "$1"

# 配列をループしてインデックス付きで内容を表示
echo "Commands in $1:"
for index in "${!commands[@]}"; do
    echo "[$index] ${commands[$index]}"
done

# 有効なインデックス番号の入力を促して開始インデックス番号を取得するループ
while true; do
    read -p "Enter a valid index number to start from (0-$((${#commands[@]} - 1))): " start_index

    # 入力が数値かどうかをチェック
    if ! [[ "$start_index" =~ ^[0-9]+$ ]]; then
        echo "Error: Invalid input. Please enter a valid number."
        continue
    fi

    # 入力された開始インデックス番号が配列の範囲内かどうかをチェック
    if (( start_index < 0 || start_index >= ${#commands[@]} )); then
        echo "Error: Index out of range. Please enter a valid index between 0 and $(( ${#commands[@]} - 1 ))."
        continue
    fi

    break
done

# 開始インデックス番号から配列を開始してコマンドを実行
echo "Executing commands from index $start_index onwards:"
for (( i = start_index; i < ${#commands[@]}; i++ )); do
    command="${commands[$i]}"
    
    # コマンド実行前に確認メッセージを表示してユーザーに実行可否を再確認
    while true; do
        read -p "Execute command: $command ? (y/n): " execute_confirm

        case "$execute_confirm" in
            [Nn])
                echo "Execution cancelled. Exiting script."
                exit 0
                ;;
            [Yy])
                echo "Executing command: $command"
                eval "$command"  # コマンドを実行
                echo "-------------------------------------"
                break
                ;;
            *)
                echo "Invalid input. Please enter 'y' to execute or 'n' to cancel."
                ;;
        esac
    done
done

以下がテスト用のコマンド群のファイルです。

commands.txt
echo "This is a test message."
read -p "Enter your name: " name
echo "Hello, $name!"
date

実行する場合は以下のように指定します。

bash execute_commands.sh commands.txt

実行した結果は以下のようになります。

おまけ:生成に用いたプロンプト

このコードはChatGPT 3.5によって生成したスクリプトになります。その際に用いたプロンプトは以下になります。

以下の仕様のbashスクリプトを作ってください
・スクリプト実行時にファイルパスを指定して、そのファイルの各行にコマンドがありますので、各行を配列に取り込んでください
・最初に一度配列をループして、インデックス付きで内容を表示してください
・その後、配列にて有効なインデックス番号の入力を促して、開始インデックス番号として格納してください。入力チェックをして適切な入力になるまでループしてください
・開始インデックス番号から配列を開始して、配列の要素である文字列を、各々コマンドとして実行してください。
・配列のコマンドを実行する直前に、そのコマンドを実行してよいか確認するようにしてください。nが入力された場合はスクリプト全体を終了してください。yが入力された場合はコマンドを実行してください。それ以外の文字の場合は繰り返して確認してください。

またこのスクリプトをテストするための`commands.txt`の中身も記述してください。テストでは以下の事を確認したいです。
・標準出力が表示される
・プロンプトの入力待ちが可能できる
・プロンプトに入力された値が確認できる

結構緻密に指示すれば、ちゃんと作ってくれました。

おわりに

単純にコマンドを順々に実行する際に、楽になるようなスクリプトを記事にしました。単純な作業は手順を減らして、ミスするリスクを減らしていきたいですね。

またそれを生成AIに作ってもらいました。ある程度単純な内容であれば、かなり良いものができると感じました。

この記事がどなたかのお役に立てれば幸いです。

Discussion