杀死所有早于 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。
当不需要检查命令参数,只考虑进程名称时,这将是完美的工具。
-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 -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='>~<')
如果您想要 最好的 控制 app
和 args
值:
kill $(ps -eo "%p>~<%t>~<%c>~<%a"|\
gawk -v app="sidekiq" -v args="au.*stopping" '~/-/ && ~ app && ~ args{printf "%d ",}' FS='>~<')
我试图通过早于 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。
当不需要检查命令参数,只考虑进程名称时,这将是完美的工具。
-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 -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='>~<')
如果您想要 最好的 控制 app
和 args
值:
kill $(ps -eo "%p>~<%t>~<%c>~<%a"|\
gawk -v app="sidekiq" -v args="au.*stopping" '~/-/ && ~ app && ~ args{printf "%d ",}' FS='>~<')