Shellデバッグ技術総括(二)


(3)デバッグフックは、デバッグブロックとも呼ばれ、他の高度なプログラム言語に由来するデバッグ方法であり、デバッグフックは実際にはif/then構造のコードブロックであり、DEBUG変数はこのコードが実行されるかどうかを制御し、プログラムの開発デバッグ段階でDEBUG変数をTRUEに設定し、デバッグ情報を出力させ、プログラムの交付段階でDEBUGをFALSEに設定し、デバッグフックコードを削除することなく、デバッグフックを閉じます.一般的なデバッグフックは、次のコードブロックです.
1 if [ "$DEBUG" ="true" ]
  2then
 3   echo "Debugginginformation: "
 4   、、、、
 5   fi

デバッグフックのDEBUGはグローバル変数であり、デバッグ開始時にexport DEBUG=trueを使用してDEBUGをtrueに設定できます.もちろん、上記のコードブロックはデバッグが必要な場合に非常に面倒ですが、DEBUG関数を定義してデバッグフックを植え込むのが便利です.
1 #!/bin/sh
  2DEBUG()
  3 {
 4   if [ "$DEBUG" ="true" ]
 5   then
 6     $@
 7   fi
  8 }
 9  a=0
 10  b=2
 11 c=100
 12  DEBUG echo "a=$a b=$b c =$c" # 1     
 13 while :
 14  do
 15 DEBUG echo "a=$a b=$b c =$c" #      
 16     if (( $a >= 10 ))
 17    then
18      break
 19    fi
 20   let "a=$a+2"
 21   let "b=$b*2"
 22   let "c=$c-10"
 23  done
[root@localhost shell]# export DEBUG=true
[root@localhost shell]# sh debugblock
a=0 b=2 c =100
a=0 b=2 c =100
a=2 b=4 c =90
a=4 b=8 c =80
a=6 b=16 c =70
a=8 b=32 c =60
a=10 b=64 c =50

デバッグフックはif/else構造です.DEBUG変数がtrueの場合、すべての位置関数が実行されます.上記のスクリプトについては、まずexportコマンドでDEBUGをtrueに割り当て、デバッグフックがスクリプトの実行を開始するとa,b,cの3つの変数の値が出力され、最終的に変数値の変化を追跡する目的を達成します.この方法はtrap命令捕捉DEBUG信号追跡変数値法と等価である.
(四)Shellオプションを使用する.
Shelllオプションを使用したデバッグ方法は、ソースコードを変更しない方法です.多くのShellオプションでは、スクリプトのデバッグに使用できる3つのオプションが-n、-x、-cです.
Shellのデバッグオプション、簡略化、意味
オプション名
簡潔に書く
意味
noexec
n
スクリプト内のコマンドを読み込み、構文チェックを行いますが、コマンドは実行されません.
xtrace
x
各コマンドを実行する前に、各コマンドを標準出力(stdout)に印刷します.
なし
c..
からの読み取りコマンド
例を挙げる
1 #!/bin/bash
  2 set -x
  3 export PATH
  4 read -p "Please input (Y/N)"
  5 if [ "$yn" == "$Y" ] ||[ "$yn" == "$y"]; then
  6        echo "ok ,continue";
  7 elif [ "$yn" == "$N" ]|| [ "$yn" == "$n"]; then
  8        echo "oh ,interrupt!";
  9 else echo "I don't know what is yourchoise"
 10 fi
[root@localhostshell]# sh else
+ export PATH
+ read -p 'Pleaseinput (Y/N)'
Please input(Y/N)y
+ '[' '' == '' ']'
+ echo 'ok,continue'
ok ,continue

スクリプトにset–xが追加されている場合、setコマンドの後に実行されるコマンドと、コマンドラインに追加された変数と変数の値を含む任意のパラメータが表示されます.行の前にプラス記号(+)が付けられ、出力を追跡するシンボルであることが示されます.サブシェルで実行されるshellトレースコマンドには、1行の前にプラス記号「+」が2つ追加されます.
set-パラメータ「オプションを有効にする」、「set+パラメータ」はオプションをオフにすることを示します.起動時に「-x」オプションを使用してすべてのコマンドラインを追跡する必要はありません.この場合、スクリプトでsetコマンドを使用できます.この場合、スクリプトでsetコマンドを使用できます.
set-x#開始「-x」オプション
トレースするセグメント
set+x#「-x」オプションを閉じる
setコマンドは、前節で説明したデバッグフックDEBUG関数を使用して呼び出すこともできます.これにより、次のスクリプトクリップに示すように、スクリプトの使用時にデバッグ文を削除する手間を回避できます.
DEBUG set-x#スタート「-x」オプション
トレースするセグメント
DEBUG set+x#「-x」オプションをオフにする
もちろん-xにも欠点がありますが、このときbash Shellが提供する3つの有用な内部変数を利用して、-xオプションプロンプトの制限を利用することができます.
Shellがデバッグに使用する内部変数とその意味
変数名
意味
LINENO
Shellスクリプトを表す行番号
FUNCNAME
呼び出しチェーン全体のすべての関数名を表す配列変数
PS4
-xオプションのプロンプトを設定します.デフォルトは「+」記号です.
例:
1 #!/bin/sh
  2isroot()
  3 {
 4   if [ "$UID" -ne 0 ]
 5   then
 6       return 1
 7   else
 8       return 0
 9   fi
 10 }
 11echroot()
 12 {
 13isroot
 14   if[ "$?" -ne 0  ]
 15  then
 16    echo "I'm not root"
 17  else
18   echo "I'm root"
 19  fi
 20 }  
 21 # PS4  ,  -x      
 22export PS4='+{$LINENO: ${FUNCNAME[0]}:${FUNCNAME[1]}}'
 23echroot
[root@localhost shell]# sh -x nestfun
+ export 'PS4=+{$LINENO:${FUNCNAME[0]}:${FUNCNAME[1]}}'
+ PS4='+{$LINENO:${FUNCNAME[0]}:${FUNCNAME[1]}}'
+{23: :}echroot
+{13: echroot:main}isroot
+{4: isroot:echroot}'[' 0 -ne 0 ']'
+{8: isroot:echroot}return 0
+{14: echroot:main}'[' 0 -ne 0 ']'
+{18: echroot:main}echo 'I'\''m root'
I'm root

上記のスクリプトでは、PS 4変数にPS 4='+{$LINENO:${FUNNAME[0]}:${FUNNAME[1]}}}'、-xオプションのプロンプトにスクリプトの行番号、現在の関数名、および呼び出し関数名を表示する2つの関数isrootとechrootが定義されています.FUNCANAME[0]は現在の関数名を表し、FUNCANAME[1]は呼び出し関数名を表す.
-cオプションを使用すると、スクリプトファイルではなく文字列からShellインタプリタがShellコマンドを読み込み、実行します.スクリプトの実行結果を一時的にテストする必要がある場合に使用できます.
例:
[root@localhost shell]# sh -c 'a=2;b=3;letc=$a+$b;echo "$c"'
5
注意:単一引用符は文字列で、文字列にはいくつかのコマンドが含まれており、コマンド間は分割されています.
まとめ:Shellスクリプトで遭遇したエラーを解析し,論理エラーを包括的に解析し,trapはechoの代わりにスクリプト出力情報,揺れ木の追跡などに便利である.teeはパイプを运用して、パイプの间のデータの流れをはっきり见ることができて、デバッグフックは高级なプログラムの言语を考虑して、とても良いプログラミングの风格で、Shellオプションはスクリプトの内容を変えないで、-nと-xオプションはよくあるスクリプトのデバッグの手段で、-nは主にスクリプトの文法の间违ったデバッグに用いて、-xは主にスクリプトのロジックの间违ったデバッグに用います.