杀死所有早于 x 的进程,匹配正则表达式

Killing all processes older than x, matching regex

我试图通过早于 x 的正则表达式终止所有进程 - 但未找到任何进程!

dep@srv-05:~$ ps aux | grep sidekiq

dep  6154 65.5  4.8 4652148 3170540 ?     Ssl  10:00  32:35 sidekiq 4.2.6 au [1 of 8 busy] stopping
dep  6172 80.8  4.3 4462376 2897480 ?     Ssl  10:20  23:52 sidekiq 4.2.6 au [8 of 8 busy]
dep  9099 89.9  1.7 2216372 1167664 ?     Ssl  10:48   1:23 sidekiq 4.2.6 au [8 of 8 busy]
dep  9548 86.8  1.6 2624832 1097428 ?     Ssl  10:48   1:16 sidekiq 4.2.6 au [8 of 8 busy]
dep 14196  0.0  0.0  13224  2076 pts/17   S+   10:50   0:00 grep --color=auto sidekiq
dep 21933 84.8  4.2 4342940 2792592 ?     Ssl  10:41   7:34 sidekiq 4.2.6 au [8 of 8 busy]
dep 26466 29.5  5.8 5116960 3822876 ?     Ssl  09:07  30:18 sidekiq 4.2.6 au [1 of 8 busy] stopping
dep 27790 64.3  4.8 5074216 3210584 ?     Ssl  09:58  33:34 sidekiq 4.2.6 au [3 of 8 busy] stopping
dep 29695 87.4  3.1 3405204 2094332 ?     Ssl  10:44   4:53 sidekiq 4.2.6 au [7 of 8 busy]
dep 29850  0.2  5.0 4663268 3296372 ?     Ssl  mar02  12:42 sidekiq 4.2.6 au [1 of 8 busy] stopping
dep 29919 87.5  2.7 3207616 1805844 ?     Ssl  10:45   4:35 sidekiq 4.2.6 au [8 of 8 busy]

dep@srv-05:~$ killall -o 24h -r sidekiq.*au.*stopping
sidekiq.*au.*stopping: no process found

但不知何故不起作用?

更新

删除 -o 24h 没有帮助:

dep@srv-05:~$ killall -r sidekiq.*au.*stopping
sidekiq.*au.*stopping: no process found

我写了一个关于这个的 thing


killall

不需要检查命令参数,只考虑进程名称时,这将是完美的工具。

-o, --older-than Match only processes that are older (started before) the time specified. The time is specified as a float then a unit. The units are s,m,h,d,w,M,y for seconds, minutes, hours, days, weeks, Months and years respectively.

-r, --regexp Interpret process name pattern as an extended regular expression.

pkill

示例:

pkill -f "sidekiq.*au.*stopping"

解决了隐藏参数的问题:

-f Match the pattern anywhere in the full argument string of the process instead of just the executable name.

但是不提供按运行时间对进程排序的方法。


所以...让我们构建自定义解决方案。

让我们回到老朋友身边ps

来自 man 页面:

-e Select all processes.

-o format user-defined format.

AIX 格式描述符

This ps supports AIX format descriptors, which work somewhat like the formatting codes of printf(1) and printf(3). For example, the normal default output can be produced with this: ps -eo "%p %y %x %c"

   CODE   NORMAL   HEADER
   %C     pcpu     %CPU
   %G     group    GROUP
   %P     ppid     PPID
   %U     user     USER
   %a     args     COMMAND
   %c     comm     COMMAND
   %g     rgroup   RGROUP
   %n     nice     NI
   %p     pid      PID
   %r     pgid     PGID
   %t     etime    ELAPSED
   %u     ruser    RUSER
   %x     time     TIME
   %y     tty      TTY
   %z     vsz      VSZ

首先,要杀死一个进程,我们需要它的PID,然后得到它已经运行了多长时间运行 最后是命令名称及其参数。

这可以通过使用上面 table 中提到的代码的格式字符串来完成:

ps -eo "%p>~<%t>~<%a"

注意:选择一个复杂的字符串作为字段>~<之间的分隔符很重要,我们不希望在命令名称或 args 中找到相同的参数来混淆我们的数据。


为了处理这个输出,让我们一步一步地组成一个 awk oneliner。

如何获取进程 运行 + 24 小时?

ps 手册页中:

etime ELAPSED elapsed time since the process was started, in the form [[dd-]hh:]mm:ss

所以,a dash char in the second field 表示该程序已 运行 至少 24 小时.

示例:

$ ps -eo "%p>~<%t>~<%a" | awk -v ' ~ /-/' FS='>~<'
  528>~<49-04:37:37>~</sbin/udevd -d
  746>~<21-08:21:52>~</dummys/apache/bin/rotatelogs -f /logs/access_log800 86400
  747>~<21-08:21:52>~</dummys/apache/bin/rotatelogs -f /logs/access_log445 86400
  748>~<21-08:21:52>~</dummys/apache/bin/rotatelogs -f /logs/access_log1447 86400
  749>~<21-08:21:52>~</dummys/apache/bin/rotatelogs -f /logs/access_log450 86400
 2170>~<49-04:37:14>~</sbin/rsyslogd -i /var/run/syslogd.pid -c 5
 2204>~<49-04:37:14>~<irqbalance --pid=/var/run/irqbalance.pid
 2270>~<49-04:37:14>~</usr/sbin/mcelog --daemon
 6892>~<49-04:37:01>~</usr/sbin/snmpd -LS0-6d -Lf /dev/null -p /var/run/snmpd.pid
 6920>~<49-04:37:01>~<xinetd -stayalive -pidfile /var/run/xinetd.pid

注意FS设置为ps格式中使用的字符串:>~<

命令行是否匹配我们的regexp?

最后一步,检查 command + args (%a) 是否包含我们的 regexp,例如 rotatelogs 字符串.

$ ps -eo "%p>~<%t>~<%a" | awk -v r="rotate.*access.*" ' ~ /-/ &&  ~ r' FS='>~<'
  746>~<21-08:21:52>~</dummys/apache/bin/rotatelogs -f /logs/access_log800 86400
  747>~<21-08:21:52>~</dummys/apache/bin/rotatelogs -f /logs/access_log445 86400
  748>~<21-08:21:52>~</dummys/apache/bin/rotatelogs -f /logs/access_log1447 86400
  749>~<21-08:21:52>~</dummys/apache/bin/rotatelogs -f /logs/access_log450 86400

让我们只打印 pids。

$ ps -eo "%p>~<%t>~<%a" |\
   awk -v r="rotate.*access.*" ' ~ /-/ &&  ~ r{printf "%d ",}' FS='>~<'
  746 747 748 749

Bash command substituion 将完成最后一招。

$ kill $(ps -eo "%p>~<%t>~<%a" |\
  awk -v r="rotate.*access.*" ' ~ /-/ &&  ~ r{printf "%d ",}' FS='>~<')

针对您的情况

kill $(ps -eo "%p>~<%t>~<%c %a"|\
  gawk -v r="sidekiq.*au.*stopping" '~/-/ &&  ~ r{print }' FS='>~<')

如果您想要 最好的 控制 appargs 值:

kill $(ps -eo "%p>~<%t>~<%c>~<%a"|\
         gawk -v app="sidekiq" -v args="au.*stopping" '~/-/ &&   ~ app &&  ~ args{printf "%d ",}' FS='>~<')