简体   繁体   English

使用top命令捕获由COMMAND过滤的进程的%CPU和PID

[英]Capture %CPU and PID of processes filtered by COMMAND using top command

I need to write a Bash script that does the following: 我需要编写一个执行以下操作的Bash脚本:

  1. In the "top" command, I would like to filter the processes by a given COMMAND. 在“top”命令中,我想通过给定的COMMAND过滤进程。 In the following I use Google Chrome as an example, which appears as "chrome" in the COMMAND column. 在下文中,我使用Google Chrome作为示例,在COMMAND列中显示为“chrome”。
  2. After filtering, there can be zero, one or more processes with COMMAND "chrome" left (this is just to highlight that there is not exactly one process with COMMAND "chrome" in general). 过滤后,可以有零个,一个或多个进程,其中包含COMMAND“chrome”(这只是为了突出显示通常没有一个具有COMMAND“chrome”的进程)。
  3. Now I would like to write the current time (hh:mm:ss), the PID of the process and the %CPU value displayed for this process to a file "logfile" 现在我想将当前时间(hh:mm:ss),进程的PID和为此进程显示的%CPU值写入文件“logfile”
  4. Repeat steps 1 to 3 once every second. 每秒重复步骤1到3。

Example: Assuming that there are three "chrome" processes, the output in "logfile" should look something like below (for the first three seconds): 示例:假设有三个“chrome”进程,“logfile”中的输出应如下所示(前三秒):

    17:49:12 7954 14.0
    17:49:12 7969  9.3
    17:49:12 2626  1.3
    17:49:13 7954 12.0
    17:49:13 7969  6.3
    17:49:13 2626  1.2
    17:49:14 7954 14.7
    17:49:14 7969  8.5
    17:49:14 2626  2.1

My ideas so far: Using the command 到目前为止我的想法:使用命令

    top -b -n 1 -p 7954 | tail -n 2 | head -n 2 | awk '{print $1, $9}' >> logfile

I filter top by PID (in this case PID == 7954) and the output looks like 我通过PID过滤顶部(在这种情况下PID == 7954),输出看起来像

    PID %CPU
    7954 6.6

however (since I actually want to filer by COMMAND) I do not know how to filter by COMMAND. 然而(因为我实际上想要通过COMMAND文件管理器)我不知道如何通过COMMAND过滤。 In the line above, the "-p 7954" does the filtering for PID==7954, however what do I need to write here to filter by COMMAND==chrome? 在上面的行中,“-p 7954”对PID == 7954进行过滤,但是我需要在此处写什么来过滤COMMAND == chrome? Also, How can I remove/avoid the header? 另外,如何删除/避免标题?

According to the time step: I found that the command 根据时间步骤:我发现了命令

    date +"%T" 

gives me the time in the correct format (hh:mm:ss). 给我时间格式正确(hh:mm:ss)。

So I just struggle with putting these pieces together and fix the filtering problem mentioned above. 所以我只是努力将这些部分放在一起并修复上面提到的过滤问题。 Thank you for any help! 感谢您的任何帮助!

Awk can do this; Awk可以做到这一点; awk '/regex/ { print }' performs the print action only on lines matching regex . awk '/regex/ { print }'仅在匹配regex行上执行print操作。

However, you can (and perhaps also should) subsume head and tail as well: 但是,你也可以(也许也应该)包含headtail

top -b -n 1 | awk 'NR>1 && $10 == "chrome" {print strftime("%T"), $1, $9}' 

... assuming the tenth field of top output contains the command name. ...假设top输出的第十个字段包含命令名称。

however what do I need to write here to filter by COMMAND==chrome 但是我需要在这里写什么来过滤COMMAND == chrome

Write a small script to accomplish this, say calc_proc_mem which looks like below : 写一个calc_proc_mem完成这个,比如calc_proc_mem ,如下所示:

#!/bin/bash
if [ -z "$1" ] #checking if first param exist
then
  echo "Usage : cal_proc_mem process_name"
  exit 1 # Exiting with a non-zero value
else
  proc_ids=( $(pgrep "$1") )
  if [ ${#proc_ids[@]} -eq 0 ] #checking if if pgrep returned nothing
  then
    echo "$1 : Process Not Running/No such process"
    exit 1 # Exiting with a non-zero value
  else
    echo "$1's %CPU-%MEM usage as on $(date +%F)" >> logfile
    while true
    do
      for proc_id in "${proc_ids[@]}"
      do
      usage="$(ps -p "$proc_id" -o %cpu,%mem | awk -v pid=$proc_id 'NR==2{printf "PID : %-10d \%CPU : %f \%MEM : %f\n",pid,$1,$2}' 2>/dev/null)"
      echo -e "$(date +%H:%M:%S)\t$usage" >> logfile
      done
      sleep 3
    done 
  fi
fi

Run the script as 运行脚本为

./calc_proc_mem process_name

Sample Output 样本输出

chrome's %CPU-%MEM usage as on 2016-06-27
23:40:33    PID : 3983       %CPU : 1.300000 %MEM : 2.200000
23:40:33    PID : 8448       %CPU : 0.100000 %MEM : 4.300000
23:40:33    PID : 8464       %CPU : 0.000000 %MEM : 0.400000
23:40:33    PID : 8470       %CPU : 0.000000 %MEM : 0.200000
23:40:33    PID : 8526       %CPU : 0.000000 %MEM : 3.000000
23:40:33    PID : 8529       %CPU : 0.000000 %MEM : 0.200000
23:40:33    PID : 8563       %CPU : 0.000000 %MEM : 1.500000
23:40:33    PID : 8655       %CPU : 0.300000 %MEM : 4.900000
23:40:33    PID : 32450      %CPU : 0.300000 %MEM : 2.100000

Note 注意

Since you've an infinite while-loop running, you need to manually terminate the program using Ctrl C. 由于您无限while-loop运行,因此需要使用Ctrl C手动终止程序。

You can drop '-p PID' option and next, grep by COMMAND. 您可以删除'-p PID'选项,然后按命令删除grep。 You can do the next: 你可以做下一个:

top -b -n 1 | grep 'chrome' | tail -n 2 | head -n 2 | awk '{print $1, $9}'

Another command sample to get you going could be: 另一个让你前往的命令示例可能是:

$ cmd="sleep"; for j in {1..3}; do (${cmd} 123 &); done; 
$ ts=$(date +"%T"); top -b -n 1| sed s/^[^\ 0123456789].*$//g |grep "${cmd}"|tr -s '\n'| awk '{print $1, $9, $12}'|sed s/^/"${ts} "/g
19:36:51 35122 0.0 sleep
19:36:51 35124 0.0 sleep
19:36:51 35126 0.0 sleep

It prints the time as given by the date call, and from top: PID, %CPU, and COMMAND field found. 它打印日期调用给出的时间,从顶部开始:找到PID,%CPU和COMMAND字段。 The headers and non matching data lines are filtered via sed (no number at start, which could suppress small pids by the way =( thus also a space at line start is accepted) and grep on the command. The time is prepended py sed on start of line injecting the stored timestamp and a blank space to separate. 标题和非匹配数据行通过sed进行过滤(开始时没有数字,这可以通过方式抑制小pid =(因此也可以接受行开始处的空格)和命令上的grep。时间预先设置为pyd行开始注入存储的时间戳和空格分隔。

It is not elegant but might fit your needs to have a start. 它不优雅,但可能符合您的需求,有一个开始。

The pgrep solutions or using awk with a regex look better ... but at least I enjoyed trying to solve it with top. pgrep解决方案或使用带正则表达式的awk看起来更好......但至少我很乐意尝试用top解决它。 The tail and head stages in the pipe look suspicious to me ... 管道中的尾部和头部阶段对我来说很可疑......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM