web-dev-qa-db-ja.com

bash配列に問題がある$ PIPESTATUS

私は、基本的に認証回数/カウントについて/var/log/accountpolicy.log*ログを解析するだけのスクリプト(OSXで実行され、おそらく他には何も実行されない)に取り組んでいます。最初のコマンドは、zgrepを介して実行されるSudoであり、これはawkにパイプされ、awkスクリプトを実行します。コマンドを実行した後、${PIPESTATUS[@]}を使用して、何かが失敗したかどうか、失敗した場合はどの部分かを判断します。

現在の状態のawkスクリプトは次のとおりです。

#! /usr/local/bin/awk -f

BEGIN {
  return_code = 0
  if ( length( username ) == 0 ){
    return_code = 2
    exit return_code
  }

  rows = 0
}
{ 
  if ( $8 != sprintf("\"%s\",", username ) ) next

  rows = rows+1
  print $0
} 
END {
  if ( return_code > 0 ) exit return_code
  if ( rows == 0 ) exit 3
}

Awkスクリプトには、いくつかのカスタム値検証および終了コードがあります。戻りコード1、2、および3は、次のことを意味します。

  1. Awkが失敗しました(awkに関連する何らかの理由で)
  2. 解析するawkのユーザー名が指定されていません
  3. ユーザー名が指定されましたが、値が見つかりませんでした

テスト#1(正しく機能している)

実行例(この質問は特にリターンコードに関連しているため、awkスクリプトからの出力を非表示にします):

$ Sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log* 2>/dev/null | awk -v username="${USER}" -f ./parse-accountpoliocy.awk &>/dev/null
$ echo ${PIPESTATUS[@]}
0 0

${PIPESTATUS[@]}は、Sudoawkの両方が成功したことを示していることがわかります。これは、私がSudoアクセス権を持っていることを知っているので、予想されます。awk変数usernameが設定され、ログエントリがあります。

テスト#2(正しく機能している)

ここで、awk変数username存在しないのアカウントに変更すると、awkスクリプトは3の戻りコードで終了するはずです。

$ Sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log* 2>/dev/null | awk -v username="fakeuser" -f ./parse-accountpoliocy.awk &>/dev/null
$ echo ${PIPESTATUS[@]}
0 3

完璧!

テスト#3(問題..)

上記のコマンドを実行したが、username awk変数の定義を怠った場合、awkスクリプトshould終了コード2で終了します。

$ Sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log* 2>/dev/null | awk -f ./parse-accountpoliocy.awk &>/dev/null
$ echo ${PIPESTATUS[@]}
141 2

ご覧のとおり、awkスクリプトdoes return 2ですが、何らかの理由で、Sudo/zgrep141を返します。コマンドのその部分がまったく変更されていないという事実にもかかわらず...そしてこれは私が遭遇している問題です。

[〜#〜] stdout [〜#〜]または[〜#〜] stderr [〜#〜]のいずれかの出力を非表示にせずにコマンドを実行しようとしました。 =)、結果は同じですが、エラーは表示されませんでした:

$ Sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log*  | awk -f ./parse-accountpoliocy.awk
$ echo ${PIPESTATUS[@]}
141 2

質問

awkスクリプトの終了コードは、${PIPESTATUS[@]}内に格納されているSudo/zgrepコマンドの終了コードをどのように変更できますか?


環境情報

  • OSxバージョン:10.11.6(El Capitan)
  • Bashバージョン:4.4.12
  • AWKバージョン:GNU Awk 4.1.4
5
Justin
_$ echo $((141-128))
13
$ kill -l | grep 13
13   PIPE Broken pipe                   29   INFO Information request
$ 
_

したがって、141は、シェルがPIPE信号を含む16ビットの終了ステータスワード(wait(2)を参照)を単一の数値にまとめる方法です。 _exit 3_の場合、これは発生しませんafterパイプされるデータはawkによって処理されました(そしてzgrepにはこれ以上何もありませんパイプ経由でawkに書き込みます)。代わりに、_exit 2_は非常に早い段階で発生しますが、zgrepにはまだawkにパイプしたいデータがあるため、zgrepPIPEで攻撃されます。消えたawkに書き込もうとします。

6
thrig