RHEL で Bash スクリプトを作成し実行する

Red Hat Enterprise LinuxBeginner
オンラインで実践に進む

はじめに

この実験(Lab)では、RHEL システム管理のための Bash スクリプトの作成と実行について学びます。まず、シンプルなスクリプトを作成し、システムコマンドを追加して実行可能にします。次に、システム情報の収集などのタスクを自動化するためにforループを使用し、grepと正規表現を使用してコマンド出力をフィルタリングする方法を学びます。最終的には、包括的な RHEL システム情報スクリプトを構築し、管理タスクの自動化と強力なシェル機能の活用に関する実践的なスキルを習得します。

シンプルな Bash スクリプトの作成と実行

このステップでは、基本的な Bash スクリプトを作成し、実行する方法を学びます。Bash スクリプトは、Bash シェルが実行できる一連のコマンドを含むプレーンテキストファイルです。これらは、繰り返し行うタスクを自動化し、複数のコマンドを単一の実行可能なユニットにまとめるための強力なツールです。

まず、スクリプトを保存するための新しいディレクトリを作成します。ファイルを整理することは良い習慣であり、スクリプトを専用のディレクトリに配置すると、ホームディレクトリを整理整頓できます。

  1. スクリプト用のディレクトリを作成します。
    mkdirコマンドを使用して、~/projectディレクトリ内にscriptsという名前のディレクトリを作成します。ここに Bash スクリプトを保存します。

    mkdir ~/project/scripts

    このコマンドが成功した場合、直接的な出力はありません。

  2. 最初の Bash スクリプトファイルを作成します。
    新しく作成したscriptsディレクトリに移動し、nanoテキストエディタを使用してfirstscript.shという名前のファイルを作成します。.sh拡張子は、シェルスクリプトの一般的な慣例ですが、厳密には必須ではありません。

    cd ~/project/scripts
    nano firstscript.sh

    nanoエディタ内には、空白の画面が表示されます。

  3. スクリプトに内容を追加します。
    すべての Bash スクリプトは、"shebang"行、#!/usr/bin/bashで始める必要があります。この行は、オペレーティングシステムに、スクリプトを実行するためにどのインタープリターを使用するかを指示します(この場合は Bash)。shebang の後には、ターミナルにメッセージを出力するシンプルなechoコマンドを追加します。

    nanoエディタに次の行を入力します。

    #!/usr/bin/bash
    echo "Hello, LabEx! This is my first Bash script."

    内容を入力したら、Ctrl+O、次にファイル名を確認するためにEnter、そしてCtrl+Xを押してnanoを終了してファイルを保存します。

    ターミナルはコマンドプロンプトに戻ります。

  4. bashインタープリターを使用してスクリプトを実行します。
    bashインタープリターに明示的に実行するように指示することで、Bash スクリプトを実行できます。この方法では、スクリプトに実行権限は必要ありません。

    bash firstscript.sh

    スクリプトの出力が表示されます。

    Hello, LabEx! This is my first Bash script.

    これにより、スクリプトが正しく作成され、正常に実行されたことが確認できます。

システムコマンドを追加し、実行可能にする Bash スクリプトの強化

このステップでは、Bash スクリプトにさらに多くのシステムコマンドを追加し、スクリプトを直接実行可能にする方法を学びます。スクリプトを実行可能にすると、bashインタープリターを明示的に呼び出すことなく、他のコマンドのように実行できます。

  1. スクリプトディレクトリに移動します。
    前のステップでfirstscript.shを作成した~/project/scriptsディレクトリにいることを確認してください。

    cd ~/project/scripts
  2. firstscript.shを編集して、より多くのシステムコマンドを含めます。
    ブロックデバイスやファイルシステムの空き容量など、システム情報を表示するコマンドをスクリプトに追加します。これにより、スクリプトがシステムデータの収集を自動化する方法が示されます。

    nanoを使用してfirstscript.shを開きます。

    nano firstscript.sh

    次の内容に合わせてファイルの内容を変更します。このスクリプトは次のことを行います。

    • ブロックデバイス情報のヘッダーを出力します。
    • lsblkを実行して、ブロックデバイスを一覧表示します。
    • ファイルシステムの空き容量のヘッダーを出力します。
    • df -hを実行して、ディスク容量の使用状況を人間が読める形式で表示します。
    #!/usr/bin/bash
    echo "Hello, LabEx! This is my first Bash script."
    echo "#####################################################"
    echo "LIST BLOCK DEVICES"
    echo "#####################################################"
    lsblk
    echo "#####################################################"
    echo "FILESYSTEM FREE SPACE STATUS"
    echo "#####################################################"
    df -h

    Ctrl+O、次にEnter、そしてCtrl+Xを押してnanoを終了してファイルを保存します。

  3. スクリプトを実行可能にします。
    スクリプトを直接実行する(例:./firstscript.sh)には、実行権限を付与する必要があります。chmodコマンドは、ファイル権限を変更するために使用されます。+xは、すべてのユーザーに実行権限を追加します。

    chmod +x firstscript.sh

    このコマンドが成功した場合、直接的な出力はありません。

  4. スクリプトを直接実行します。
    スクリプトが実行可能になったので、そのパスを指定して実行できます。現在のディレクトリにあるため、./の後にスクリプト名を続けます。

    ./firstscript.sh

    最初のメッセージとlsblkおよびdf -hの出力を組み合わせた、次のような出力が表示されます。

    Hello, LabEx! This is my first Bash script.
    #####################################################
    LIST BLOCK DEVICES
    #####################################################
    NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
    loop0         7:0    0 10.2G  1 loop /
    loop1         7:1    0  200M  1 loop /usr/local/bin
    loop2         7:2    0  200M  1 loop /usr/local/go
    loop3         7:3    0  200M  1 loop /usr/local/java
    loop4         7:4    0  200M  1 loop /usr/local/node
    loop5         7:5    0  200M  1 loop /usr/local/python
    #####################################################
    FILESYSTEM FREE SPACE STATUS
    #####################################################
    Filesystem      Size  Used Avail Use% Mounted on
    overlay          10G  4.0G  6.1G  40% /
    tmpfs            64M     0   64M   0% /dev
    tmpfs           7.8G     0  7.8G   0% /sys/fs/cgroup
    shm              64M     0   64M   0% /dev/shm
    /dev/loop0       10G  4.0G  6.1G  40% /
    tmpfs           7.8G     0  7.8G   0% /proc/asound
    tmpfs           7.8G     0  7.8G   0% /proc/acpi
    tmpfs           7.8G     0  7.8G   0% /proc/scsi
    tmpfs           7.8G     0  7.8G   0% /sys/firmware

    lsblkdf -hの正確な出力は、特定の環境によって若干異なる場合がありますが、コマンドの構造と出力の存在は同様であるはずです。

RHEL サーバーで For ループを使用してホスト名を取得する自動化

このステップでは、Bash のforループについて学び、複数のサーバーでタスクを自動化する方法を学びます。forループは、リスト内の各項目に対してコードブロックを繰り返し実行できる基本的な制御フロー文です。これは、複数のシステムを効率的に管理するのに特に役立ちます。

この演習では、複数のサーバーでの作業をシミュレートするために、さまざまなアプローチを使用して localhost でこの概念を説明します。

  1. ローカルコマンドを使用してホスト名を取得します。
    ループを使用する前に、ローカルシステムから通常どのようにホスト名を取得するかを見てみましょう。この概念を説明するために、さまざまな方法を使用します。

    hostname
    hostname -f

    次のような出力が表示されます。

    684791f71c0e35fea6cc1243
    684791f71c0e35fea6cc1243

    これは、さまざまなオプションを使用してホスト名情報を正常に取得できることを示しています。このコンテナ環境では、すべてのホスト名オプションが同じコンテナ ID を返すことに注意してください。

  2. さまざまなオプションを使用してホスト名取得を自動化するforループを作成します。
    次に、forループを使用して、さまざまなホスト名コマンドをより効率的に実行します。forループは、ホスト名オプションのリストを反復処理し、各オプションでhostnameコマンドを実行します。

    for OPTION in "" "-f" "-s"; do
      echo "hostname ${OPTION}:"
      hostname ${OPTION}
      echo ""
    done

    このコマンドを分解してみましょう。

    • for OPTION in "" "-f" "-s";: この部分はループを初期化します。OPTIONは、各反復処理中にリスト内の各項目(空の文字列、-f-s)の値を受け取る変数です。
    • do: ループで実行するコマンドの開始を示します。
    • echo "hostname ${OPTION}:";: これは、どのオプションが使用されているかを表示します。
    • hostname ${OPTION};: これは、各反復処理で実行されるコマンドです。${OPTION}は、OPTION変数の現在の値に展開されます。
    • echo "";: 可読性を高めるために空白行を追加します。
    • done: ループの終了を示します。

    次のような出力が表示されます。

    hostname :
    684791f71c0e35fea6cc1243
    
    hostname -f:
    684791f71c0e35fea6cc1243
    
    hostname -s:
    684791f71c0e35fea6cc1243

    これは、さまざまなパラメーターを使用して繰り返しタスクを自動化するforループの力を示しています。

RHEL サーバー向け For ループを使用した Bash スクリプトの作成と実行

このステップでは、前のステップで学習したforループを Bash スクリプトにカプセル化します。これにより、自動化ロジックを保存し、簡単に再利用できます。また、PATH環境変数と、任意のディレクトリからスクリプトにアクセスできるようにする方法についても学びます。

  1. スクリプトディレクトリに移動します。
    ~/project/scriptsディレクトリにいることを確認してください。

    cd ~/project/scripts
  2. ホスト名取得用の新しいスクリプトを作成します。
    さまざまなオプションを使用してホスト名情報を取得するforループを含む、get_hostnames.shという名前のスクリプトを作成します。

    nanoを使用してget_hostnames.shを開きます。

    nano get_hostnames.sh

    次の内容をファイルに追加します。

    #!/usr/bin/bash
    ## This script retrieves hostname information using different options.
    
    for OPTION in "" "-f" "-s"; do
      echo "Getting hostname with option: ${OPTION}"
      hostname ${OPTION}
      echo "------------------------"
    done
    
    exit 0

    Ctrl+O、次にEnter、そしてCtrl+Xを押してnanoを終了してファイルを保存します。

    新しい要素を分解してみましょう。

    • ## This script...: #で始まる行はコメントです。これらはシェルによって無視されますが、スクリプトをドキュメント化するのに役立ちます。
    • echo "Getting hostname with option: ${OPTION}": この行は、スクリプトの実行中にフィードバックを提供し、現在使用されているオプションを示します。
    • exit 0: このコマンドは、慣例的に成功を示すステータスコード0でスクリプトを明示的に終了します。
  3. スクリプトを実行可能にします。
    前のステップと同様に、新しいスクリプトに実行権限を付与する必要があります。

    chmod +x get_hostnames.sh

    このコマンドが成功した場合、直接的な出力はありません。

  4. 現在のディレクトリからスクリプトを実行します。
    スクリプトを実行して、その機能を検証します。

    ./get_hostnames.sh

    次のような出力が表示されます。

    Getting hostname with option:
    684791f71c0e35fea6cc1243
    ------------------------
    Getting hostname with option: -f
    684791f71c0e35fea6cc1243
    ------------------------
    Getting hostname with option: -s
    684791f71c0e35fea6cc1243
    ------------------------
  5. PATH環境変数を理解します。
    PATH環境変数は、シェルが実行可能コマンドを検索するディレクトリのリストです。lsgrepのようなコマンドを入力すると、シェルはPATHにリストされているディレクトリを検索して、対応する実行可能ファイルを見つけます。

    現在のPATH変数を表示します。

    echo $PATH

    コロンで区切られたディレクトリのリストが表示されます。例:

    /home/labex/.local/bin:/home/labex/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin

    ~/project/scripts(または/home/labex/project/scripts)は、通常、デフォルトのPATHに含まれていないことに注意してください。これが、スクリプトを実行するために./get_hostnames.shを使用する必要があった理由です。

  6. スクリプトディレクトリをPATHに追加します(オプション、今後の参考のために)。
    このラボステップでは必須ではありませんが、カスタムスクリプトを任意の場所から実行できるように、個人のbinまたはscriptsディレクトリをPATHに追加するのが一般的な方法です。export PATH=$PATH:~/project/scriptsのような行を~/.bashrcまたは~/.zshrcファイルに追加することで、これを行うことができます。このラボでは、スクリプトのパスを指定してスクリプトを実行し続けます。

RHEL で Grep と正規表現を使用してコマンド出力をフィルタリング

このステップでは、grepコマンドと正規表現を使用して、コマンド出力とファイルから特定の情報を効率的にフィルタリングして抽出する方法を学びます。grepは、プレーンテキストデータセットから正規表現に一致する行を検索するための強力なユーティリティです。正規表現(regex)は、検索パターンを定義する文字のシーケンスです。

  1. システムファイルで特定のユーザーとグループ情報を検索します。
    /etc/passwdファイルと/etc/groupファイルからlabexユーザーとグループに関する情報を検索するために、grepを使用します。これらのファイルは、それぞれユーザーとグループのアカウント情報を格納します。

    まず、/etc/passwdlabexユーザーエントリを検索してみましょう。

    grep "labex" /etc/passwd

    期待される出力:

    labex:x:1000:1000::/home/labex:/bin/bash

    次に、/etc/grouplabexグループエントリを検索します。

    grep "labex" /etc/group

    期待される出力:

    labex:x:1000:

    これらのコマンドは、正確な文字列の一致を見つけるための基本的なgrepの使用法を示しています。

  2. grepと正規表現を使用してlscpu出力をフィルタリングします。
    lscpuコマンドは、CPU アーキテクチャ情報を表示します。多くの場合、その広範な出力から特定の行のみが必要になります。正規表現とともにgrepを使用して、「CPU」で始まる行をフィルタリングできます。

    lscpu | grep '^CPU'

    このコマンドを分解してみましょう。

    • lscpu: CPU 情報を生成します。
    • |: これはパイプであり、lscpuの標準出力を取得し、それをgrepコマンドへの標準入力としてフィードします。
    • grep '^CPU': リテラル文字列「CPU」で始まる行を検索します。^(キャレット)は、行の先頭に一致する正規表現アンカーです。

    期待される出力(環境によって若干異なる場合があります):

    CPU op-mode(s):                     32-bit, 64-bit
    CPU(s):                             4
    CPU family:                         6
  3. コメントと空行を無視して、設定ファイルをフィルタリングします。
    設定ファイルには、実際の構成とは関係のないコメント(#で始まる行)と空行が含まれていることがよくあります。複数のパターンを持つgrepを使用して、これらの行を除外できます。/etc/passwdファイルでこれを示してみましょう。

    grep -v '^#' /etc/passwd | head -5

    このコマンドを分解してみましょう。

    • grep -v '^#' /etc/passwd: -vオプションは一致を反転させます。つまり、パターンに一致しない行を選択します。^#は、#で始まる行に一致します。したがって、この部分はコメント行をフィルタリングします。
    • |: 最初のgrepコマンドの出力を次のコマンドにパイプします。
    • head -5: 出力の最初の 5 行のみを表示します。

    期待される出力(コメントなしのユーザーアカウントエントリを表示):

    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
  4. システムファイルで特定のパターンを検索します。
    grepを使用して、さまざまなシステムファイルで特定のパターンを検索できます。/etc/passwdファイルでシェル関連のエントリを検索してみましょう。

    grep "bash" /etc/passwd

    期待される出力(bash シェルを持つユーザーを表示):

    root:x:0:0:root:/root:/bin/bash
    labex:x:1000:1000::/home/labex:/bin/bash

    このコマンドは、bash をデフォルトシェルとして持つユーザーを識別するのに役立ちます。

RHEL システム情報スクリプトの包括的な構築

この最終ステップでは、これまでに学習したすべての概念(Bash スクリプティング、forループ、リモート実行のためのssh、フィルタリングのための正規表現を使用したgrep)を組み合わせて、複数の RHEL サーバーからシステム情報を収集する包括的なスクリプトを構築します。スクリプトは、収集したデータをサーバーごとに個別の出力ファイルに保存します。

  1. スクリプトディレクトリに移動します。
    ~/project/scriptsディレクトリにいることを確認してください。

    cd ~/project/scripts
  2. system_info.shという名前の新しいスクリプトを作成します。
    このスクリプトは、さまざまなアプローチを使用してシステム情報を収集し、その出力を~/projectディレクトリ内の個別のファイルにリダイレクトします。

    nanoを使用してsystem_info.shを開きます。

    nano system_info.sh

    次の内容をファイルに追加します。

    #!/usr/bin/bash
    
    ## Define variables for output directory
    OUT_DIR='/home/labex/project'
    
    ## Loop through different information gathering approaches
    for APPROACH in "basic" "detailed"; do
      OUTPUT_FILE="${OUT_DIR}/output-${APPROACH}.txt"
    
      echo "Gathering ${APPROACH} system information..."
      ## Clear previous output file or create a new one
      > "${OUTPUT_FILE}"
    
      ## Get hostname information
      echo "#### Hostname Information ###" >> "${OUTPUT_FILE}"
      if [ "${APPROACH}" = "basic" ]; then
        hostname >> "${OUTPUT_FILE}"
      else
        hostname -f >> "${OUTPUT_FILE}"
      fi
      echo "" >> "${OUTPUT_FILE}" ## Add a blank line for readability
    
      ## Get CPU information (only lines starting with CPU)
      echo "#### CPU Information ###" >> "${OUTPUT_FILE}"
      lscpu | grep '^CPU' >> "${OUTPUT_FILE}"
      echo "" >> "${OUTPUT_FILE}"
    
      ## Get system users with bash shell
      echo "#### Users with Bash Shell ###" >> "${OUTPUT_FILE}"
      grep "bash" /etc/passwd >> "${OUTPUT_FILE}"
      echo "" >> "${OUTPUT_FILE}"
    
      ## Get system information based on approach
      if [ "${APPROACH}" = "basic" ]; then
        echo "#### Basic System Info ###" >> "${OUTPUT_FILE}"
        uname -r >> "${OUTPUT_FILE}"
      else
        echo "#### Detailed System Info ###" >> "${OUTPUT_FILE}"
        uname -a >> "${OUTPUT_FILE}"
      fi
      echo "" >> "${OUTPUT_FILE}"
    
      echo "Information saved to ${OUTPUT_FILE}"
      echo "-----------------------------------------------------"
    done
    
    echo "Script execution complete."

    Ctrl+O、次にEnter、そしてCtrl+Xを押してnanoを終了してファイルを保存します。

    このスクリプトの主な要素:

    • OUT_DIR='/home/labex/project': スクリプトをより柔軟で読みやすくするために使用される変数です。
    • OUTPUT_FILE="${OUT_DIR}/output-${APPROACH}.txt": 各アプローチに対して出力ファイル名を動的に構築します。
    • > "${OUTPUT_FILE}": 空のコマンドの出力をファイルにリダイレクトし、存在する場合はその内容を効果的にクリアし、存在しない場合は作成します。これにより、各実行で新しいファイルが確保されます。
    • >> "${OUTPUT_FILE}": コマンドの出力を指定されたファイルに追加します。
    • if [ "${APPROACH}" = "basic" ]; then ... else ... fi: 使用されているアプローチに基づいて異なるコマンドを実行する条件文です。
    • echo "#### Section Header ###": より良い整理のために、出力ファイルに明確なヘッダーを追加します。
  3. スクリプトを実行可能にします。

    chmod +x system_info.sh

    このコマンドが成功した場合、直接的な出力はありません。

  4. system_info.shスクリプトを実行します。
    包括的なスクリプトを実行します。さまざまなアプローチを使用してシステム情報を収集し、結果を個別のファイルに保存します。

    ./system_info.sh

    スクリプトの進行状況を示す出力がターミナルに表示されます。

    Gathering basic system information...
    Information saved to /home/labex/project/output-basic.txt
    -----------------------------------------------------
    Gathering detailed system information...
    Information saved to /home/labex/project/output-detailed.txt
    -----------------------------------------------------
    Script execution complete.
  5. 生成された出力ファイルを確認します。
    ~/projectディレクトリにあるoutput-basic.txtおよびoutput-detailed.txtファイルの内容を確認して、スクリプトが期待どおりに情報を収集したことを確認します。

    cat ~/project/output-basic.txt
    cat ~/project/output-detailed.txt

    各ファイルの内容は、次のようになります(実際の値は異なります)。

    output-basic.txt:

    #### Hostname Information ###
    684791f71c0e35fea6cc1243
    
    #### CPU Information ###
    CPU op-mode(s):                     32-bit, 64-bit
    CPU(s):                             4
    CPU family:                         6
    
    #### Users with Bash Shell ###
    root:x:0:0:root:/root:/bin/bash
    labex:x:1000:1000::/home/labex:/bin/bash
    
    #### Basic System Info ###
    5.4.0-162-generic

    output-detailed.txt:

    #### Hostname Information ###
    684791f71c0e35fea6cc1243
    
    #### CPU Information ###
    CPU op-mode(s):                     32-bit, 64-bit
    CPU(s):                             4
    CPU family:                         6
    
    #### Users with Bash Shell ###
    root:x:0:0:root:/root:/bin/bash
    labex:x:1000:1000::/home/labex:/bin/bash
    
    #### Detailed System Info ###
    Linux 684791f71c0e35fea6cc1243 5.4.0-162-generic #179-Ubuntu SMP Mon Aug 14 08:51:31 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

    この最終的なスクリプトは、さまざまな Bash 機能と Linux コマンドを組み合わせて、システム管理タスク用の強力な自動化ツールを作成する方法を示しています。

まとめ

この実験では、RHEL システム管理のための Bash スクリプトの作成と実行に関する基本的な手順を学びました。まず、スクリプト専用のディレクトリを設定し、shebang 行の重要性とechoコマンドの使用を理解しながら、シンプルな Bash スクリプトを作成しました。bashインタープリターで直接実行する方法や、実行可能にすることなど、スクリプトを実行するさまざまな方法を検討しました。

さらに、さまざまなアプローチでシステム情報を収集するために、forループを使用してシステムコマンドを組み込み、タスクを自動化することにより、スクリプト作成スキルを向上させました。また、システム情報を解析するための重要なスキルである、grepと正規表現を使用してコマンド出力を効果的にフィルタリングする方法も学びました。最後に、これらの概念を適用して、包括的な RHEL システム情報スクリプトを構築し、さまざまなコマンドとスクリプト構造を組み合わせて、貴重なシステムデータを収集して提示する方法を示しました。