如何杀死超过特定年龄的Linux进程?

我在某些服务器上有一些类似僵尸的进程出现问题,需要立刻杀掉。 我怎样才能最好地确定已经跑了一个多小时左右?

如果他们只是需要被杀害:

 if [[ "$(uname)" = "Linux" ]];then killall --older-than 1h someprocessname;fi 

如果你想看看它是什么匹配

 if [[ "$(uname)" = "Linux" ]];then killall -i --older-than 1h someprocessname;fi 

-i标志将提示您是否为每个进程匹配。

find了一个适合我的答案:

警告:这将find并杀死长时间运行的进程

 ps -eo uid,pid,etime | egrep '^ *user-id' | egrep ' ([0-9]+-)?([0-9]{2}:?){3}' | awk '{print $2}' | xargs -I{} kill {} 

(其中user-id是具有长时间运行的进程的特定用户ID。)

第二个正则expression式与具有可选天数的时间相匹配,后跟小时,分钟和秒组件,因此至less有一个小时的长度。

对于一天以前的任何事情,

 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自6月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 | 头-n 10 

Perl的Proc :: ProcessTable将做到这一点: http : //search.cpan.org/dist/Proc-ProcessTable/

你可以使用sudo apt-get install libproc-processtable-perl来安装debian或ubuntu

这是一个单行的:

 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

这为您提供更多的多function性和开始时间1秒的分辨率。

Jodie C和其他人指出, killall -i可以使用,如果你想使用进程名称来杀死,这是很好的。 但是如果你想通过与pgrep -f相同的参数来杀死,你需要使用类似下面的东西,使用纯粹的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_agemax_age秒更早的进程 ; 即,名为/usr/bin/python2 offlineimap可以通过引用“offlineimap”来终止,而这里介绍的killall解决scheme只适用于string“python2”。

你可以使用bc来join怪物的回答中的两个命令,并获得自从进程开始以来经过了多less秒钟:

 echo `date +%s` - `stat -t /proc/<pid> | awk '{print $14}'` | bc 

编辑:

在等待长时间运行的时候,无聊的时候,几分钟之后就出现了:

 #file: sincetime #!/bin/bash init=`stat -t /proc/$1 | awk '{print $14}'` curr=`date +%s` seconds=`echo $curr - $init| bc` name=`cat /proc/$1/cmdline` echo $name $seconds 

如果你把这个放在你的道路上,像这样调用它:sincetime

它将打印自启动以来的进程cmdline和秒数。 你也可以把它放在你的path中:

 #file: greptime #!/bin/bash pidlist=`ps ax | grep -i -E $1 | grep -v grep | awk '{print $1}' | grep -v PID | xargs echo` for pid in $pidlist; do sincetime $pid done 

而且如果你运行:

 greptime <pattern> 

其中模式是一个string或扩展的正则expression式,它将打印出与这个模式匹配的所有进程以及自启动以来的秒数。 🙂

做一个ps -aef 。 这将显示进程开始的时间。 然后使用date命令查找当前时间。 计算两者之间的差异以查找过程的年龄。

我做了一些类似于接受的答案,但稍微有点不同,因为我想根据进程名称匹配,并基于运行超过100秒的错误进程

 kill $(ps -o pid,bsdtime -p $(pgrep bad_process) | awk '{ if ($RN > 1 && $2 > 100) { print $1; }}') 

stat -t /proc/<pid> | awk '{print $14}'

以秒为单位获得该过程的开始时间。 与当前时间( date +%s )进行比较以获取当前进程的年龄。

使用ps是正确的方法。 我之前已经做过类似的事情,但是没有源代码。 一般来说 – ps有一个选项可以告诉它显示哪个字段以及哪个字段进行sorting。 你可以通过运行时间sorting输出,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);' 

或者,我们可以把它写成shell脚本,

 #!/bin/sh # longprockill.sh ps -lf | grep "user" | perl -ane '($h,$m,$s) = split /:/,$F[13]; kill + 9, $F[3] if ($h > 1);' 

并像这样调用它的crontab,

 * * * * * longprockill.sh