Как вы убиваете все процессы Linux, которые старше определенного возраста?
У меня проблема с некоторыми зомби-подобными процессами на определенном сервере, которые нужно время от времени убивать. Как я могу лучше всего определить те, которые работают дольше часа или около того?
14 ответов:
если их просто нужно убить:
if [[ "$(uname)" = "Linux" ]];then killall --older-than 1h someprocessname;fi
Если вы хотите увидеть, что он соответствует
if [[ "$(uname)" = "Linux" ]];then killall -i --older-than 1h someprocessname;fi
The
-i
флаг предложит вам с Да / нет для каждого процесса матча.
нашел ответ, который работает для меня:
внимание: это будет найти убить длительные процессы
ps -eo uid,pid,etime | egrep '^ *user-id' | egrep ' ([0-9]+-)?([0-9]{2}:?){3}' | awk '{print }' | xargs -I{} kill {}
(где user-id - это идентификатор конкретного пользователя с длительными процессами.)
второе регулярное выражение соответствует времени, которое имеет необязательную цифру дней, за которой следуют час, минута и второй компонент, и поэтому имеет длину не менее одного часа.
для всего, что старше одного дня,
ps aux
даст вам ответ, но он падает до дневной точности, которая может быть не так полезна.
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 7200 308 ? Ss Jun22 0:02 init [5] root 2 0.0 0.0 0 0 ? S Jun22 0:02 [migration/0] root 3 0.0 0.0 0 0 ? SN Jun22 0:18 [ksoftirqd/0] root 4 0.0 0.0 0 0 ? S Jun22 0:00 [watchdog/0]
если вы работаете в linux или другой системе с файловой системой /proc, в этом примере вы можете видеть только, что процесс 1 запущен с 22 июня, но нет указания времени его запуска.
stat /proc/<pid>
даст вам более точный ответ. Например, вот точное время процесса 1, который ps показывает только как Jun22:
ohm ~$ stat /proc/1 File: `/proc/1' Size: 0 Blocks: 0 IO Block: 4096 directory Device: 3h/3d Inode: 65538 Links: 5 Access: (0555/dr-xr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2008-06-22 15:37:44.347627750 -0700 Modify: 2008-06-22 15:37:44.347627750 -0700 Change: 2008-06-22 15:37:44.347627750 -0700
таким образом, вы можете получить список из десяти старейших процессов:
ps -elf | sort -r -k12 | head -n 10
Perl Proc:: ProcessTable сделает трюк: http://search.cpan.org/dist/Proc-ProcessTable/
вы можете установить его в debian или ubuntu с
sudo apt-get install libproc-processtable-perl
вот один-лайнер:
perl -MProc::ProcessTable -Mstrict -w -e 'my $anHourAgo = time-60*60; my $t = new Proc::ProcessTable;foreach my $p ( @{$t->table} ) { if ($p->start() < $anHourAgo) { print $p->pid, "\n" } }'
или, более форматированный, поместите это в файл под названием process.pl:
выполнить#!/usr/bin/perl -w use strict; use Proc::ProcessTable; my $anHourAgo = time-60*60; my $t = new Proc::ProcessTable; foreach my $p ( @{$t->table} ) { if ($p->start() < $anHourAgo) { print $p->pid, "\n"; } }
perl process.pl
это дает вам больше многосторонности и 1 секунд-разрешения на времени начала.
Джоди С и другие указали, что
killall -i
может быть использован, что нормально, если вы хотите использовать имя процесса, чтобы убить. Но если вы хотите убить по тем же параметрам, что иpgrep -f
, вам нужно использовать что-то вроде следующего, используя pure bash и/proc
файловой системы.#!/bin/sh max_age=120 # (seconds) naughty="$(pgrep -f offlineimap)" if [[ -n "$naughty" ]]; then # naughty is running age_in_seconds=$(echo "$(date +%s) - $(stat -c %X /proc/$naughty)" | bc) if [[ "$age_in_seconds" -ge "$max_age" ]]; then # naughty is too old! kill -s 9 "$naughty" fi fi
это позволяет находить и убивать процессы старше
max_age
секунд с помощью полное имя процесса, т. е. процесс, называемый/usr/bin/python2 offlineimap
может быть убит ссылкой на "offlineimap", тогда какkillall
решения, представленные здесь, будут работать только на строке "python2".
можно использовать
bc
чтобы присоединиться к двум командам в ответе моба и получить, сколько секунд прошло с момента начала процесса:echo `date +%s` - `stat -t /proc/<pid> | awk '{print }'` | bc
edit:
от скуки в ожидании долгих процессов, чтобы запустить, это то, что вышло через несколько минут возиться:
#file: sincetime #!/bin/bash init=`stat -t /proc/ | awk '{print }'` curr=`date +%s` seconds=`echo $curr - $init| bc` name=`cat /proc//cmdline` echo $name $seconds
если вы поставите это на свой путь и назовете это так: с тех пор
он будет печатать процесс cmdline и секунд с момента запуска. Вы также можете поместить это в ваш путь:
#file: greptime #!/bin/bash pidlist=`ps ax | grep -i -E | grep -v grep | awk '{print }' | grep -v PID | xargs echo` for pid in $pidlist; do sincetime $pid done
а чем если запустить:
greptime <pattern>
где patterns-это строка или расширенное регулярное выражение, он будет печатать все процессы, соответствующие этому шаблону и секундам с момента их запуска. :)
сделать
ps -aef
. это покажет вам время, в которое начался процесс. Затем с помощью найти текущее время. Вычислите разницу между ними, чтобы найти возраст процесса.
Я сделал что-то похожее на принятый ответ, но немного по-другому, так как я хочу соответствовать на основе имени процесса и на основе плохого процесса, работающего более 100 секунд
kill $(ps -o pid,bsdtime -p $(pgrep bad_process) | awk '{ if ($RN > 1 && > 100) { print ; }}')
stat -t /proc/<pid> | awk '{print }'
получить время запуска процесса в секундах с начала эпохи. Сравните с текущим временем (
date +%s
), чтобы получить текущий возраст процесса.
использование ps-это правильный путь. Я уже делал что-то подобное раньше, но у меня нет источника под рукой. Вообще-ps имеет возможность сказать ему, какие поля показывать и по которым сортировать. Вы можете сортировать вывод по времени выполнения, grep процесс, который вы хотите, а затем убить его.
HTH
если кому-то это нужно в C, вы можете использовать readproc.h и libproc:
#include <proc/readproc.h> #include <proc/sysinfo.h> float pid_age(pid_t pid) { proc_t proc_info; int seconds_since_boot = uptime(0,0); if (!get_proc_stats(pid, &proc_info)) { return 0.0; } // readproc.h comment lies about what proc_t.start_time is. It's // actually expressed in Hertz ticks since boot int seconds_since_1970 = time(NULL); int time_of_boot = seconds_since_1970 - seconds_since_boot; long t = seconds_since_boot - (unsigned long)(proc_info.start_time / Hertz); int delta = t; float days = ((float) delta / (float)(60*60*24)); return days; }
наткнулся где-то..думал это просто и полезно
вы можете использовать команду в crontab напрямую ,
* * * * * ps -lf | grep "user" | perl -ane '($h,$m,$s) = split /:/,$F +[13]; kill 9, $F[3] if ($h > 1);'
или, мы можем написать его как скрипт
#!/bin/sh # longprockill.sh ps -lf | grep "user" | perl -ane '($h,$m,$s) = split /:/,$F[13]; kill + 9, $F[3] if ($h > 1);'
и назовем его кронтаб вот так,
* * * * * longprockill.sh