5

Bash プログラムの場合:

 1  #!/bin/bash
 2  
 3  trapinfo()
 4  {
 5     echo "=== Trap Info: Status=$? LINENO=$@ A=$A"
 6  }
 7  
 8  main()
 9  {
10     trap 'trapinfo $LINENO -- ${BASH_LINENO[*]}' ERR
11  
12     set -e
13     set -E
14     set -o errtrace
15     shopt -s extdebug
16  
17     local -g A=1
18  
19     # false        # If uncommented, LINENO would be 19
20     (exit 73)      # LINENO is 9. How can I get 20 instead?
21  
22     A=2
23  }
24  
25  main

出力で:

=== Trap Info: Status=73 LINENO=9 -- 25 0 A=1

trapゼロ以外のステータスで終了するサブシェルがキャッチされ、失敗したサブシェルの行番号が表示されるようにする方法を探しています。上記の例では、結果として行 20を探しています。エラーがサブシェルにない場合は、必要な行番号を取得することに注意してください (false上記を参照)。

9行番号が実際にトラップ呼び出しに接続されているかどうかを確認するために、サブシェルの直前にトラップを移動しようとしましたが、同じ結果が得られます。サブシェルにもsetandエントリを配置しようとしましたが、これも動作に変更はありません。shopt

環境:

  • bash-4.2.46-21.el7_3.x86_64 : これは要件ですが、POSIX 準拠は必須ではありません。また、Bash の今後のリリース (4.2 以降) にも関心があります。
  • CentOS 7+:主に CentOS に関心がありますが、最終的には Ubuntu 16.04+ および CentOS 6 に展開される Bash スクリプトにもこれが必要になります。

ゼロ以外のステータスを返すサブプロセスの行番号を取得することは可能ですか? それが不可能な場合、その趣旨の文書はありますか? 解決策が存在する場合は、コードに不要な装飾を加えることなく適切にスケーリングする必要があります。

4

2 に答える 2

1

これについては、Bash の電子メール グループhelp-bashに助けを求めました。Eduardo Bustamante は、ここでの問題の根底にある Bash の潜在的なバグを指摘するために、次の 2 つのコード ブロックを提供しました。

まず、問題のさらに簡単なデモンストレーション:

     1  #!/bin/bash
     2  shopt -s extdebug
     3  main() {
     4  trap 'echo $LINENO' ERR
     5  (exit 17)
     6  }
     7  main

上記の出力は3.

次に、次のように変更$(...)することを検討して`...`ください。

     1  #!/bin/bash
     2  shopt -s extdebug
     3  main() {
     4  trap 'echo $LINENO' ERR
     5  `exit 17`
     6  }
     7  main

上記の出力は5.

今、私は自分のテストをしました:

     1  #!/bin/bash
     2  shopt -s extdebug
     3  main() {
     4  trap 'echo $LINENO' ERR
     5  $(exit 17)
     6  }
     7  main

これには、 の目的の出力もあり5ます。

したがって、この質問の解決策は、これが Bash のバグであり、サブシェルの代わりにコマンド置換()を使用することで回避できるようです。

繰り返しになりますが、Eduardo Bustamante の洞察力に感謝します。彼がここに解決策を投稿して彼の答えを受け入れるかどうかを確認するために、数日待ちます。それ以外の場合は、これを受け入れられた回答としてマークし、彼に感謝します。

于 2016-12-30T12:27:12.077 に答える
1
#!/bin/bash

trapinfo()
{
   echo "=== Trap Info: Status=$? LINENO=$@ A=$A"
}

main()
{
   trap 'trapinfo $LINENO $SAVE_IT -- ${BASH_LINENO[*]}' ERR

   set -e
   set -E
   set -o errtrace
   shopt -s extdebug

   local -g A=1

   # false        # If uncommented, LINENO would be 19
   SAVE_IT=$LINENO && (exit 73)     # LINENO is magic, but a custom variable isn’t

   A=2
}

main

多分私は何かが欠けているかもしれませんが、おそらくこれはあなたのために働くでしょう...

于 2016-12-27T14:59:32.057 に答える