web-dev-qa-db-ja.com

複数のawkコマンドへのパイピング

1つのコマンドの出力を2つの異なるawkコマンドにパイプしようとしています。次の この投稿 私はteeとプロセス置換を使用しています。ただし、置換されたプロセスの出力が表示されません。

_nvidia-smi | tee >(awk '/ C / {print $6}') | awk '/ C / {print $3}' | xargs -r ps -o user
_

これは、すべてのGPUプロセスのユーザーとメモリ使用量を示すことになっています。メモリ使用量とPIDは、それぞれ_nvidia-smi_から_awk '/ C / {print $6}'_と_awk '/ C / {print $3}'_によって抽出され、後者は_ps -o user_にパイプされます。ただし、出力にはユーザーのみが含まれます。

私が欲しいのは

_<memory-of-process1> <name-of-user-running-process1>
<memory-of-process2> <name-of-user-running-process2>
<memory-of-process3> <name-of-user-running-process3> 
etc
_

そして私が得ているのは

_<name-of-user-running-process1>
<name-of-user-running-process2>
<name-of-user-running-process3>
etc
_

提案されているように、最初のawkコマンドにfflush()または_stdbuf -o0_を追加してみました ここ

1
ludog

シェルスクリプトを使用したよりコンパクトなソリューション:

nvidia-smi | grep ' C ' | while read _ _ pid _ _ mem; do
    user="$( ps -o user "${pid}" | tail -n +2 )"
    printf '%8s  %6d  %s\n' "${mem}" "${pid}" "${user}"
done

これは、pidごとに3つの追加プロセスを実行することに注意してください。

awkを使用した元のソリューション:

#! /bin/bash

function nvidia-smi { cat <<'[][]'
A C 937 D E 1.7MB
A C 1232 D E 0.25MB
A E 6112 D E 13MB
A C 2008 D E 437KB
A C 2024 D E 314157
[][]
}

AWK='
/ C / { Pid[NR] = $3; xPid[$3] = NR; Mem[NR] = $6; }
END {
    for (j in Pid) pp = pp "," Pid[j];
    cmd = "ps 2>&1 -o pid,user -p " substr (pp, 2);
    while (cmd | getline) 
        if ($1 in xPid) User[xPid[$1]] = $2;
    close (cmd);
    fmt = "%8s  %6d  %s\n";
    for (j = 1; j <= NR; ++j) 
        if (j in Mem)
            printf (fmt, Mem[j], Pid[j], User[j]);
}
'
    nvidia-smi | awk "${AWK}"

関数nvidia-smiは、いくつかのテストデータを表示するだけです-それを破棄します。 AWK変数(一重引用符の間の複数行定数の12行)とその下の短いパイプラインが必要です。

テスト。メモリを使用していたpidを含めました:

paul $ ./nVid
   1.7MB     937  syslog
  0.25MB    1232  root
   437KB    2008  postfix
  314157    2024  paul
0
Paul_Pedant