web-dev-qa-db-ja.com

KornShell-「-x」(デバッグ)フラグをグローバルに設定しますか?

KornShell(ksh)スクリプトでデバッグモード( set -x )をグローバルに設定する方法はありますか?現在、私は次のようなことをしているようです。

a(){
   set -x
   #commands
}

b(){
   set -x
   #more commands
}

set-x 
a
#commands
b

Set-xコマンドを1か所で呼び出すだけでよいのです。

注:これはすべてAIX上のKSH88にあります。

例:

#!/bin/ksh
set -x

a(){
   echo "This is A!"
}

b(){
   echo "This is B!"
}

a
echo "Outside"
b
 dev2:/ home/me->./testSetX
+a 
これはA!
 + echo Outside 
 Outside 
 + b 
これはBです!
 dev2:/ home/me-> 
8
C. Ross

これは、HP-UXマシンのksh88です。

_me@Host ..dev/
$ cat ./test/verbose
#!/bin/ksh
set -x

hello() {
  print $1
}

hello kapow!
exit

[email protected]/
$ ./test/verbose    
+ hello kapow!
+ print kapow!
kapow!
+ exit
_

それは確かに見えるそれはうまくいくようです。最初の関数呼び出しの前に、「set-x」でも機能することを検証しました。

私はAIXシステムに移行し、あなたが説明した問題を経験しました。関数がAIXksh88で_function a {_またはa() {として定義されている場合、_set -x_は関数ローカルスコープに持ち越されていないように見えます。同じAIXボックスでksh93に切り替えると、新しい_function a {_構文を使用して宣言された関数も、外側の_set -x_を内側のスコープに持ち込みません。ただし、ksh93は、以前のPOSIX sh(および他のプラットフォームではksh88)のように動作し、関数が古いa(){メソッドで定義されている場合は、_set -x_を関数に渡します。これはおそらく、関数が古い方法で定義されているときに古い動作をエミュレートしようとするksh93の後方互換性によるものです。

したがって、デバッグの目的でインタプリタを一時的にksh93に切り替えてから、より長い配列、連想配列、浮動小数点演算、名前空間のサポート、および10倍の大幅な改善が必要ない場合はksh88に戻すことができる場合があります。 ksh93がもたらす実行速度。 ;)答えは「いいえ、それはできません」のように見えるので、AIX上のksh88では。 :(

8
dannysauer

グローバル_set -x_をksh88(Solaris 10上)とksh93(Fedora 17)でテストし、スクリプトの先頭にあるグローバル_set -x_コマンドの両方に関数ローカルスコープがありません(つまり、ローカル効果はありません)。

回避策として、スコープ内のすべての関数(定義後)およびtypesetを介して呼び出される前にローカルコマンドトレースを有効にできます。

_$ cat test.ksh
PS4='$LINENO: '

set -x

function foo {
  print Hello
}

bar() {
  print World
}

typeset -ft `typeset +f` 

foo
bar
_

Ksh88(Solaris 10)での出力:

_$ ksh test.ksh 
13: typeset +f
13: typeset -ft bar foo
15: foo
1: print Hello
Hello
16: bar
1: print World
World
_

タイプセットがコメントアウト

_$ ksh test.ksh 
15: foo
Hello
16: bar
World
_

Ksh93(Fedora 17)での出力:

_$ ksh test.ksh
13: typeset +f
13: typeset -ft 'bar()' foo
15: foo
6: print Hello
Hello
16: bar
10: print World
World
_

タイプセットがコメントアウト

_$ ksh test.ksh
15: foo
Hello
16: bar
10: print World
World
_

Bashでの出力

typesetがコメントアウトされ、printがechoに置き換えられました:

_$ bash test.ksh
15: foo
6: echo Hello
Hello
16: bar
10: echo World
World
_

(Fedora 17のbash 4.2.39(1))

Fedora17のzsh5.0.2で同じ出力。

結論

Kshを使用する場合、ksh93とfnname()関数定義構文でのみ、グローバル_set -x_にもローカルスコープがあります。 _typeset -ft_ベースの回避策は、すべての関数のコマンドトレースを有効にする比較的簡単な方法です。

Bash(およびzsh)では、グローバル_set -x_は期待どおりに機能します。つまり、すべての関数のローカルスコープもあります。

したがって、kshの代わりにbashを使用して新しいスクリプトを作成する場合は、このため、より適切な代替手段になる可能性があります。

補足として:bashはおそらくksh88よりもさらに移植性が高く、特にksh93よりも移植性があります。

5
maxschlepzig

あなたのシバンラインにそれを追加してください:

#!/bin/ksh -x

または、スクリプトの先頭に設定します。

#!/bin/ksh
set -x

または、コマンドラインからスクリプトを開始します。

ksh -x script_name

「set-x」の動作は、AIXシェルの「特異性」です(頭脳は言うまでもありません...)。

「デバッグモードをグローバルに設定する方法」を求めました。これを達成するために私が行うことは次のとおりです。

set_x="${set_x-:}"; # Defaults to ":" (NOOP) unless already non-empty
# Using ":" instead of "" makes termination via semicolon work,
# which in turn allows inlining, especially when using SSH.
# Alternatively, if tracing should be on by default:
#set_x="${set_x-set -x}"; # Defaults to "set -x" unless already non-empty

$set_x; # Apply to file scope

f() {
    $set_x; # Apply to local scope
    echo working...;
}
main() {
    $set_x; # Apply to local scope
    f;
    ssh localhost $set_x\; hostname; # Apply to remote Shell scope
    ssh localhost "set_x=\"$set_x\" foo"; # Apply to foo called in remote Shell
}
main;

トレースを有効にするには、スクリプトの環境で$set_xを「set -x」に設定します。これを通話ごとに制御するには、通話の前に「set_x='set -x'」を付けます。環境変数が使用されるため、このメソッドはネストされた呼び出しで自然に機能します。

$set_x;」のこれらすべての使用法は少し醜いですが、それはすべてのシェルで機能し、通常、利点はコストを上回ります。

AIXシェルの「特異性」の別の例:

set -e;
trap "echo trapped at file scope" EXIT;
f() { return 1; }
main() { f; }
main;

上記は「ファイルスコープでトラップされた」と出力するはずですが、何も出力しません。

1
Rainer

2つのタイプの関数宣言の間でスコープが影響を受けることに注意してください

a(){}

vs.

関数a {}

特に、kshの下のtypsetは、前者の場合に期待するようには機能しません。再帰関数を使用してスクリプトをデバッグしようとしたときに見つかりました。詳細はこちら:

http://www.dartmouth.edu/~rc/classes/ksh/functions.html

1
JBS