シェルスクリプトのpargsでプロセスコマンドライン引数を解析します。

シェルスクリプトのpargsでプロセスコマンドライン引数を解析します。

Bashスクリプト(Javaプロセス)からPIDのリストを取得し、対応するコマンドライン引数を解析して、各PIDが対応するサーバーインスタンスを確認する必要があります。

現在、私はsed / cutを使用してこれを行います。

  PARGS=$(pargs -l $PID)
  PARGS_ARR=($PARGS)
  NODE='UNKNOWN'
  for ARG in ${PARGS_ARR[@]}
  do
    # trim single quotes 
    ARG=$(echo $ARG | sed "s/'//g")

    # split by equals sign
    ARGL=$(echo $ARG | cut -f1 -d=)
    ARGR=$(echo $ARG | cut -f2 -d=)

    if [ "$ARGL" == "-DnodeId" ]; then
      NODE=$ARGR
    fi
  done

ただし、多数のコマンドラインパラメータ(PIDあたり約20〜30個)のため、非常に遅く実行されます。

どういうわけか、コマンドライン引数を解析し、単一のコマンドを使用して解析されたキー=>値を取得する方法はありますか?

答え1

出力はどのようpargs -l $PIDに見えますか?コードでは、次の形式のすべてのコマンドライン引数を含む1行として表示されます。

arg1=val1 arg2=val2

-DnodeIdその場合は、次のコマンドを使用してパラメータ値を収集できますsed

$ ARGS="-DfirstArg=foo -DanotherArg=bar -DnodeId=1234 -DlastArg=baz"
$ echo "$ARGS" | sed -r 's/.*-DnodeId=([^ ]+).*/\1/g'
1234

したがって、スクリプトは次のようになります。

PARGS=$(pargs -l $PID)
NODE='UNKNOWN'
if [ -n "$(grep "DnodeId" <(echo "$PARGS"))" ]; then
    NODE=$(echo "$PARGS" | sed -r 's/.*-DnodeId=([^ ]+).*/\1/g')
fi

答え2

右側にあるものが何か興味がある場合(=左側にあるものがある場合)、-DnodeId次のようにできます。

NODE=$(pargs -l $PID| awk -F '-DnodeId=' '{sub(" .*","",$2);print $2}')

-DnodeId=これにより、最初のスペースを除いてパターンの右側にあるすべての項目が印刷されます。コマンドラインに複数がある場合は、-DnodeId最初のエントリにのみ適用されます。

1行に複数を処理する-DnodeIdことも可能です。

NODES=($(pargs -l $PID| awk -F '-DnodeId=' '{
          for(i=2;i<=NF;i++){
              sub(" .*","",$i);
              print $i
          }
        }'
))

答え3

あなたがやっていることが間違いなく遅くなるようです。var=$(command substitute)次のステップに進む前に、停止して出力を待つ必要があります。ストリームで処理すると、待ち時間が短くなると大胆です。sed,これstream editor:

NODE="$(pargs -l $PID | sed -rn '/(-DnodeId)=(\S*)/{s//\2/pq}')"

一重引用符が何であるかよくわかりません。ちょうど携帯に入力しました。しかし、sed's yそれでも必要な場合、関数は確実に処理できます。

上記のJoshは失敗のケースを示しています。以下を追加する方がはるかに簡単です。

${NODE:?PID not found...quitting}

上記の実行後sed注文する。

私が見るには、これらは必ずしも行で区切られていないようです。 1行だけ追加すると簡単に処理できます。|pipe- まだ1つのデータストリームにすべて含まれていますが、複数の一致の可能性も考慮します。

. <<PIDSED /dev/stdin
    $(pargs -l $PID |\
        sed -rn 's/(-DnodeId)=(\S*)/\
            echo "NODE$((i=i+1))=\2" ;/gp' |\
        . /dev/stdin)
PIDSED

答え4

bashパラメータ処理に外部プロセスの代わりに使用

for ARG in "${PARGS_ARR[@]}"
do
  # trim single quotes 
  ARG=${ARG//\'}

  # split by equals sign
  IFS="=" read ARGL ARGR <<< "$ARG"

  if [[ "$ARGL" == "-DnodeId" ]]; then
    NODE=$ARGR
  fi
done

関連情報