Bash

管道到多個 awk 命令

  • May 10, 2020

我正在嘗試將一個命令的輸出通過管道傳輸到兩個不同的awk命令。在這篇文章之後,我正在使用tee和處理替換。但是,我看不到替代過程的輸出。

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

這應該顯示所有 gpu 程序的使用者和記憶體使用情況。nvidia-smi記憶體使用情況和 PID分別由提取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

我已嘗試按照此處fflush()的建議將或添加stdbuf -o0到第一個 awk 命令。

使用 shell 腳本的更緊湊的解決方案:

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 執行三個額外的程序。

原始解決方案使用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

引用自:https://unix.stackexchange.com/questions/583755