Reputation: 8835
I'm trying to kill all processes by a regular expression older than x - but no processes are found!
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
But it's not working somehow?
UPDATE
Removing -o 24h
does not help:
dep@srv-05:~$ killall -r sidekiq.*au.*stopping
sidekiq.*au.*stopping: no process found
Upvotes: 3
Views: 1832
Reputation: 14955
I wrote a thing about this.
Will be the perfect tool when there's no need to inspect the command args, only process name is taken in consideration.
-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.
Example:
pkill -f "sidekiq.*au.*stopping"
Solves the problem of hiding parameters:
-f
Match the pattern anywhere in the full argument string of the process instead of just the executable name.
But does not provide a way to sort processes by elapsed time.
Let's go back to an old friend ps
.
From the man page:
-e Select all processes.
-o format user-defined format.
AIX FORMAT DESCRIPTORS
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
First things first, To Kill a process, we need its PID
, then get how long has it been running and finally the command name and it's args.
This be accomplished by this format string using the codes mentioned in the table above:
ps -eo "%p>~<%t>~<%a"
NOTE : It’s important to choose a complicated string as separator between our fields >~<
, we don't want to find the same one inside the command name or the args garbling our data.
To process this output let's compose an awk
oneliner, step by step.
In ps
man page:
etime
ELAPSED elapsed time since the process was started, in the form[[dd-]hh:]mm:ss
So, a dash char in the second field means that the program has been running for at least 24 hours.
Example:
$ ps -eo "%p>~<%t>~<%a" | awk -v '$2 ~ /-/' 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
NOTE: FS
is set to the string used in ps
format: >~<
Last step, check if the command
+ args
(%a
) contains our regexp
, for this example the rotatelogs string.
$ ps -eo "%p>~<%t>~<%a" | awk -v r="rotate.*access.*" '$2 ~ /-/ && $3 ~ 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
Lets print only the pids.
$ ps -eo "%p>~<%t>~<%a" |\
awk -v r="rotate.*access.*" '$2 ~ /-/ && $3 ~ r{printf "%d ",$1}' FS='>~<'
746 747 748 749
Bash command substituion
will make the final trick.
$ kill $(ps -eo "%p>~<%t>~<%a" |\
awk -v r="rotate.*access.*" '$2 ~ /-/ && $3 ~ r{printf "%d ",$1}' FS='>~<')
kill $(ps -eo "%p>~<%t>~<%c %a"|\
gawk -v r="sidekiq.*au.*stopping" '$2~/-/ && $3 ~ r{print $1}' FS='>~<')
If you want a finest control over app
and args
values:
kill $(ps -eo "%p>~<%t>~<%c>~<%a"|\
gawk -v app="sidekiq" -v args="au.*stopping" '$2~/-/ && $3 ~ app && $4 ~ args{printf "%d ",$1}' FS='>~<')
Upvotes: 3