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

我需要编写一个Bash脚本来执行以下操作:

  1. 在“顶部”的命令,我想通过给定的命令过滤进程。 在下面我使用Google Chrome作为例子,它在COMMAND列中显示为“chrome”。
  2. 过滤之后,可以有零个,一个或多个COMMAND为“chrome”的进程(这只是强调一般不会有一个COMMAND为“chrome”的进程)。
  3. 现在我想将当前时间(hh:mm:ss),进程的PID和此进程显示的%CPU值写入文件“logfile”
  4. 每秒重复步骤1至3一次。

示例:假设有三个“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 

我的想法到目前为止:使用命令

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

我通过PID过滤顶部(在这种情况下PID = 7954),输出看起来像

  PID %CPU 7954 6.6 

然而(因为我实际上要通过命令filer)我不知道如何通过COMMAND筛选。 在上面的行中,“-p 7954”对PID == 7954进行过滤,但是我需要在这里写入来通过COMMAND == chrome进行过滤? 另外,如何删除/避免标题?

按照时间步骤:我发现了这个命令

  date +"%T" 

给我正确的格式(hh:mm:ss)的时间。

所以我只是拼凑在一起,并修复上述过滤问题。 感谢您的任何帮助!

Awk可以做到这一点; awk '/regex/ { print }'仅在匹配regex行上执行print操作。

但是,您可以(也可以也应该)包含headtail

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

假设top输出的第十个字段包含命令名称。

然而,我需要写在这里通过COMMAND == chrome过滤

写一个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 

运行脚本

 ./calc_proc_mem process_name 

示例输出

 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 

注意

由于您运行的是无限while-loop ,因此您需要使用Ctrl C手动终止程序。

你可以删除“-p PID”选项,接下来,通过命令grep。 你可以做下一个:

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

另一个命令示例可以帮助您:

 $ 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 

它打印日期调用给出的时间,从上到下找到PID,%CPU和COMMAND字段。 头文件和不匹配的数据行通过sed进行过滤(在开始时没有数字,可以按照下面的方式(这样也可以接受行开始处的空间)抑制小的pid,grep在命令上。开始行注入存储的时间戳和空白区分开。

这不是优雅的,但可能适合您的需要有一个开始。

pgrep解决方案或使用awk与正则表达式看起来更好…但至少我喜欢试图解决它与顶级。 管道中的尾部和头部阶段对我来说很可疑