BASHプログラミング
 Computer >> コンピューター >  >> プログラミング >> BASHプログラミング

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

シェルスクリプトデバッグシリーズのこの記事では、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
シェルトレースを使用してシェルスクリプトでコマンドの実行をトレースする方法

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

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

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

$ sudo bash -n sys_info.sh 
シェルトレースを使用してシェルスクリプトでコマンドの実行をトレースする方法

シェルスクリプトを批判的に見ると、if statementであることがわかります。 終了する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行目のエラーが表示されます。 閉じている二重引用符が欠落しているためです(”) 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
シェルトレースを使用してシェルスクリプトでコマンドの実行をトレースする方法 シェルトレースを使用してシェルスクリプトでコマンドの実行をトレースする方法

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

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

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

ここでの魔法は、if statementによって制御されます。 式[ "$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部構成のシリーズ全体に関する質問やフィードバックに対応できます。


  1. Powershell スクリプトに一時停止を追加する方法 (例あり)

    この記事では、powershell スクリプトに一時停止を追加する方法を紹介します。 一時停止または待機コマンドを追加するには、さまざまな方法があります。以下に、例を挙げてこれらの方法を示します。 Powershell スクリプトに一時停止を追加する方法 Powershell スクリプトに一時停止を追加するには、次の手順に従います PowerShell ISE を開く スタートメニューから 次に、一時停止コマンドを追加する PowerShell スクリプトを開きます start-sleep -Seconds 5 という行を追加します (数字の 5 を、スクリプトを一時停止する秒数に置

  2. 5 つの実用的な例を含む Bash スクリプト入門チュートリアル

    進行中の Unix Sed および Unix Awk シリーズと同様に、Bash スクリプトに関するいくつかの記事を投稿します。実用的な例ですべての bash スクリプト テクニックをカバーします。 シェルは、ユーザー コマンドを解釈するプログラムです。コマンドは、ユーザーが直接入力するか、シェル スクリプトと呼ばれるファイルから読み取るかのいずれかです。ユーザーからの入力を直接読み取る場合、シェルは対話型シェルとして呼び出されます。 シェルは、ファイルからコマンドを読み取って実行するときに、非対話型シェルとして呼び出されます。この場合、シェルはスクリプト ファイルの各行を上から下に読み取