代码之家  ›  专栏  ›  技术社区  ›  yukondude

如何杀死所有超过某个年龄的Linux进程?

  •  65
  • yukondude  · 技术社区  · 16 年前

    14 回复  |  直到 9 年前
        1
  •  36
  •   Kelvin    12 年前

    警告:这将找到 杀死

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

    (在哪里

    第二个正则表达式匹配具有可选天数的时间,后跟小时、分钟和第二个分量,因此长度至少为一小时。

        2
  •  34
  •   Jodie C    13 年前

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

    如果你想看看它匹配什么

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

    这个 -i

        3
  •  22
  •   Mark Harrison    16 年前

    对于任何超过一天的事情,

    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
    
        4
  •  9
  •   ggasp    16 年前

    通过这种方式,您可以获得十个最旧进程的列表:

    ps -elf | sort -r -k12 | head -n 10
        5
  •  8
  •   user67416 user67416    12 年前

    Jodie C和其他人指出 killall -i 可以使用,如果要使用进程名称终止,则可以使用。但是如果你想用和你一样的参数杀人 pgrep -f /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 完整进程名称 ; i、 例如,名为 /usr/bin/python2 offlineimap 可以通过引用“offlineimap”终止,而 killall 此处提供的解决方案仅适用于字符串“python2”。

        6
  •  7
  •   Peter V. Mørch    14 年前

    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秒的启动时间分辨率。

        7
  •  3
  •   Rafael S. Calsaverini    12 年前

    你可以用 bc

    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
    

    如果你把它放在你的路径上,并这样称呼它:

    它将打印流程cmdline和启动后的秒数。您还可以将其放在您的路径中:

    #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>
    

    当模式是字符串或扩展正则表达式时,它将打印出与此模式匹配的所有进程以及它们启动后的秒数。:)

        8
  •  2
  •   Jason Plank Maksim Kondratyuk    13 年前

    ps -aef . 这将显示进程开始的时间。然后使用 date

        9
  •  1
  •   Rodney Amato    13 年前

    我做了一些与公认答案类似的事情,但略有不同,因为我希望根据进程名称和运行超过100秒的坏进程进行匹配

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

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

    获取自历元以来进程的开始时间(以秒为单位)。与当前时间比较( date +%s )以获取进程的当前年龄。

        11
  •  0
  •   abyx    16 年前

    通常-ps有一个选项告诉它显示哪些字段以及按哪些字段排序。您可以通过运行时间对输出进行排序,grep您想要的进程,然后终止它。

        12
  •  0
  •   David Jeske    13 年前

    如果有人在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;
    }
    
        13
  •  0
  •   user3743785    10 年前

    我在某个地方遇到过……我觉得它简单又有用

    您可以直接使用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);'
    

    * * * * * longprockill.sh
    
        14
  •  0
  •   Phil Hudson    6 年前

    sincetime 以上作者@Rafael S.Calsaverini:

    #!/bin/bash
    ps --no-headers -o etimes,args "$1"
    

    这将反转输出字段:首先是经过的时间,然后是包含参数的完整命令。这是首选的,因为full命令可能包含空格。