ウェブサイト検索

シェル トレースを使用してシェル スクリプトのコマンドの実行をトレースする方法


シェル スクリプト デバッグ シリーズのこの記事では、3 番目のシェル スクリプト デバッグ モード、つまりシェル トレースについて説明し、いくつかの例を見てその仕組みと使用方法を示します。

このシリーズの前の部分では、他の 2 つのシェル スクリプト デバッグ モード、詳細モード構文チェックモードについて明確に説明し、シェルを有効にする方法のわかりやすい例を示します。これらのモードでのスクリプトのデバッグ。

  1. Linux でシェル スクリプト デバッグ モードを有効にする方法 – パート 1
  2. シェル スクリプトで構文チェック デバッグ モードを実行する方法 – パート 2

シェル トレースとは、単にシェル スクリプト内のコマンドの実行をトレースすることを意味します。シェル トレースをオンにするには、-x デバッグ オプションを使用します。

これにより、実行時にすべてのコマンドとその引数を端末上に表示するようにシェルに指示されます。

以下の sys_info.sh シェル スクリプトを使用します。これにより、システムの日付と時刻、ログインしているユーザーの数、およびシステムの稼働時間が簡単に出力されます。ただし、これには構文エラーが含まれており、見つけて修正する必要があります。

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;    
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME
}

check_root
print_sys_info

exit 0

ファイルを保存し、スクリプトを実行可能にします。このスクリプトは root によってのみ実行できるため、次のように sudo コマンドを使用して実行します。

chmod +x sys_info.sh
sudo bash -x sys_info.sh

上記の出力から、コマンドは、その出力が変数の値として置き換えられる前に、最初に実行されることがわかります。

たとえば、日付が最初に実行され、その出力が変数日付の値として置き換えられました。

次のように構文チェックを実行して、構文エラーのみを表示できます。

sudo bash -n sys_info.sh 

シェル スクリプトを批判的に見ると、if ステートメント に終わりの fi 単語が欠けていることがわかります。したがって、これを追加すると、新しいスクリプトは次のようになります。

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
   fi    
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME
}

check_root
print_sys_info

exit 0

ファイルを再度保存し、root として呼び出して、いくつかの構文チェックを実行します。

sudo bash -n sys_info.sh

上記の構文チェック操作の結果では、スクリプトの行 21 にもう 1 つのバグがあることがわかります。したがって、構文を修正する必要がまだあります。

もう一度スクリプトを分析的に確認すると、行 21 のエラーは、 内の最後の echo コマンドに閉じ二重引用符 ( ”) が欠落していることが原因です。 >print_sys_info 関数。

echo コマンドに閉じ二重引用符を追加し、ファイルを保存します。変更されたスクリプトは以下のとおりです。

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME"
}

check_root
print_sys_info

exit 0

ここで、スクリプトの構文をもう一度確認してください。

sudo bash -n sys_info.sh

スクリプトの構文が正しいため、上記のコマンドは出力を生成しません。もう一度スクリプトの実行をすべてトレースすることもできます。これはうまく機能するはずです。

sudo bash -x sys_info.sh

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

sudo ./sys_info.sh

シェルスクリプト実行トレースの重要性

シェル スクリプトのトレースは、構文エラー、さらに重要なことに論理エラーを特定するのに役立ちます。 sys_info.sh シェル スクリプトの check_root 関数を例に挙げます。この関数は、スクリプトの実行のみが許可されているため、ユーザーが root であるかどうかを判断することを目的としています。スーパーユーザーによって。

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

ここでの魔法は、適切な数値演算子 ( を使用しない場合) if ステートメント[ "$UID" -ne "$ROOT_ID" ] によって制御されます。この場合、 -ne (等しくないことを意味します)、論理エラーが発生する可能性があります。

-eq (等しいという意味) を使用したと仮定すると、root ユーザーだけでなくすべてのシステム ユーザーにもスクリプトの実行が許可されるため、論理エラーが発生します。

check_root(){
    if [ "$UID" -eq "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

: このシリーズの冒頭で説明したように、set Shell 組み込みコマンドを使用すると、シェル スクリプトの特定のセクションでデバッグをアクティブ化できます。

したがって、以下の行は、関数の実行をトレースすることで、関数内のこの論理エラーを見つけるのに役立ちます。

論理エラーのあるスクリプト:

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -eq "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME"
}

#turning on and off debugging of check_root function
set -x ; check_root;  set +x ;
print_sys_info

exit 0

ファイルを保存してスクリプトを呼び出すと、以下の出力のように、 通常のシステム ユーザーがsudo を使用せずにスクリプトを実行できることがわかります。これは、USER_ID の値が 100 であり、ルートの ROOT_ID である 0 と等しくないためです。

./sys_info.sh

さて、今のところはここまでです。シェル スクリプトのデバッグ シリーズは終わりに来ました。このガイドまたは 3 部構成のシリーズ全体に関する質問やフィードバックは、以下の応答フォームを使用して解決できます。