如何取消早于“ t”的进程?


14

首先,是的,我已经看到了这个问题:

查找(并杀死)旧进程

那里的答案不正确,不起作用。我对此进行了投票并发表了评论。

当要列出时,我要杀死的进程如下所示ps aux | grep page.py

阿帕奇424 0.0 0.1 6996 4564 S 07:02 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
阿帕奇2686 0.0 0.1 7000 3460?S Sep10 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
阿帕奇2926 0.0 0.0 6996 1404吗?S Sep02 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
阿帕奇7398 0.0 0.0 0.0 6996 1400?S Sep01 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
阿帕奇9423 0.0 0.1 6996 3824?S Sep10 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
阿帕奇11022 0.0 0.0 0.0 7004 1400?S Sep01 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
阿帕奇15343 0.0 0.1 7004 3788?S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
阿帕奇15364 0.0 0.1 7004 3792 S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
阿帕奇15397 0.0 0.1 6996 3788 S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
阿帕奇16817 0.0 0.1 7000 3788?S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
阿帕奇17590 0.0 0.0 0.0 7000 1432?S Sep07 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 24448 0.0 0.0 0.0 7000 1432?S Sep07 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
阿帕奇30361 0.0 0.1 6996 3776 S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py

我希望设置一个简单的日常cron,它将发现并杀死page.py一个小时以上的所有进程。

前面提到的问题的公认答案不起作用,因为它与时间范围不匹配,它仅与从7天到7天(23小时59分59秒)运行的流程匹配。我不想杀死从1-2小时开始运行的进程,而是杀死大于 1小时的任何进程。

其他答案使用上述问题find是不行的,至少不会在Gentoo或CentOS的5.4,它要么吐出一个警告,或者不返回任何内容,如果说警告的意见之后。

Answers:


22

GNU Killall可以使用进程名称杀死比给定年龄更旧的进程。

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

1
该选项在CentOS 6.6上不可用。版本:killall(PSmisc)22.6。
匿名

9

多亏克里斯托弗(Christopher)的回答,我才能够将其调整为以下内容:

find /proc -maxdepth 1 -user apache -type d -mmin +60 -exec basename {} \; \
| xargs ps | grep page.py | awk '{ print $1 }' | sudo xargs kill

-mmin 是我缺少的查找命令。


3
不确定-mmin是否适合检测进程的年龄。
LatinSuD

似乎没有对/ proc /目录进行大量修改,因此这似乎可行。话虽如此,我不想声称这是不可能的。
Christopher Karel

我认为这不会回答您的问题,因为此答案太狭窄而问题又很广泛。
poige

我还要说更多-它根本不起作用:find /proc -maxdepth 1 -type d -name 1 -mmin +60 -ls-尽管正常运行时间是几天而不是几个小时,但/ sbin / init并未列出。看来您不能依赖/ proc /的dirs修改时间。
poige 2012年

3
不幸的是,不能依赖/ proc中的时间戳。至少没有了。
2013年

8

find并不总是有效,不是每个系统都有可用的etimes,这可能是我的regex newb状态,但是我认为您不需要的还不止于此:

ps -eo pid,etimes,comm,user,tty | awk '{if ($4 ~ /builder/ && $5 ~ /pts/ && $2>600) print $1}'
  • 列出所有进程并提供列PID,ELAPSED(etimes = seconds),COMMAND,USER,TT(感谢@ahoffman)
  • 用awk打印PID,其中第4列($ 4,USER)包含文本“ builder”,第5列($ 5,TT)包含文本“ pts”,而ELAPSED列的值大于600秒(感谢@amtd)

然后,您可以通过管道将其杀死,或者满足您的任何需求。


我认为这是更可靠的解决方案之一,尤其是在您使用时ps,但我会将倍数greps 折叠为单个awk,为了安全起见,将模式匹配限制为特定的列(以排除例如命令名称匹配建筑商等)
jmtd

当您的时间范围以天为单位时,这很好,但是如果您要以小时,分钟或秒为单位来测试经过的时间,则无法使用。
VlastimilOvčáčík16年

使用“ etimes”而不是“ etime”,这将返回经过的时间(以秒为单位),这很容易解析。
ahofmann

@jmtd&ahofmann:我已经根据您的评论进行了更新。我希望这是您所希望的
eugenevd

5
# get elapsed time in seconds, filter our only those who >= 3600 sec
ps axh -O etimes  | awk '{if ($2 >= 3600) print $2}'

如果需要,可以提供要ps在其中查找的PID列表,例如:

ps h -O etimes 1 2 3

2
etimes仅适用于较新版本ps
Tino

4

我认为您可以修改一些以前的答案以适合您的需求。即:

用于FILE in(查找。-maxdepth 1-用户进程user -type d -mmin +60)
  杀掉-9 $(basename $ FILE)#我永远也无法使用basename与find的exec一起工作。让我知道是否知道!
做完了

要么

ps -eo pid,etime,comm | awk'$ 2!〜/^..:..$/ && $ 3〜/ page \ .py / {print $ 1}'| 杀-9

我认为第二个可能最适合您的需求。查找版本将结束该用户的其他进程


--Christopher Karel


7
kill -9除非不得已,否则请勿使用。使用-SIGINT-SIGTERM
暂停,直到另行通知。

这是将经过时间的格式用作测试标准,而不是其值。小于一个小时的ps时间将以^..:..$格式输出。
VlastimilOvčáčík16年

4
apt-get install psmisc

killall -o 1h $proc_name

您能帮忙解释一下有关该psmisc实用程序的更多信息吗?OP提到了CentOS;它可以作为RPM使用吗?
Castaglia '16

4

问题

将命令etime(经过的时间)列转换ps为秒。时间规格采用这种格式[[dd-]hh:]mm:ss。较新的版本ps具有一etimes列,etime以秒为单位输出值。

解决方案:简单的自定义awk功能

这种定制的awk支持所有格式的etime列(如03-12:30:5900:07等)。只要将其粘贴到您的awk脚本中,它就是一线友好的解决方案。

function sec(T){C=split(T,A,"[:-]"); return A[C>3?C-3:99]*86400 + A[C>2?C-2:99]*3600 + A[C>1?C-1:99]*60 + A[C>0?C-0:99]*1}
  • sec(T) 将T转换为秒
  • T时间[[dd-]hh:]mm:ss格式说明(例如etime
  • C中的字段数T(相当于awk的NF变量)
  • A中的字段数组T(相当于awk的$变量)
  • A[C>3?C-3:99]这是一种以相反顺序引用第四个值(即天数)的安全方法。这种方法很有用,因为几天和几小时是可选的。如果数组不够长,它将取消引用A[99],这将产生0值。我认为99对于大多数用例来说已经足够高了。
  • 返回秒作为整数

现实世界的例子

soffice.bin如果该进程超过180秒,则该bash oneliner将终止当前用户下运行的进程。

kill -9 $(ps cx -o command,etime,pid | awk '/^soffice.bin/ {if (sec($2)>180) {print $3}} function sec(T){C=split(T,A,"[:-]"); return A[C>3?C-3:99]*86400 + A[C>2?C-2:99]*3600 + A[C>1?C-1:99]*60 + A[C>0?C-0:99]*1}')

1
比其他答案更好。它也处理多进程。
丹尼·温伯格

最好将'command'或'args'放在'ps'格式列表的末尾,以便能够在完整的command / args字符串上grep。将其放在开头将导致ps截断较长的命令。
Maksym

1

中的lstart字段ps提供了一致的时间格式,我们可以将date其转换为自纪元以来的秒数。然后,我们将其与当前时间进行比较。

#!/bin/bash
current_time=$(date +%s)
ps axo lstart=,pid=,cmd= |
    grep page.py |
    while read line
    do
        # 60 * 60 is one hour, multiply additional or different factors for other thresholds 
        if (( $(date -d "${line:0:25}" +%s) < current_time - 60 * 60 ))
        then
            echo $line | cut -d ' ' -f 6    # change echo to kill
        fi
    done

0

我修改了他们在上一篇文章中给您的答案

ps -eo pid,etime,comm | 
egrep '^ *[0-9]+ +([0-9]+-[^ ]*|[0-9]{2}:[0-9]{2}:[0-9]{2}) +/usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py' | 
awk '{print $1}' | 
xargs kill

正则表达式搜索两种类型的第二个参数:

  • 以数字和减号形式的天数。
  • Hours:minutes:seconds 表达。

那应该匹配所有的东西,除了年轻的进程,他们将拥有表单minutes:seconds


或者,我们可以尝试按照PS的方式进行操作。从/ proc / * / stat的第22个参数中减去/ proc / uptime的第一个参数。
LatinSuD

0

这可能是多余的,但是我很好奇地完成了它并测试它是否正常工作(当然,在我系统上的另一个进程名称上)。您可以取消捕获正则表达式$user$pid简化正则表达式,我只是为了调试而添加了它,并且不想退缩。来自perl 5.10的命名捕获将减少几行,但这应该适用于较旧的perl。

当然,您需要用kill代替打印件,但是我实际上并不想在自己的系统上杀死任何东西。

#!/usr/bin/perl -T
use strict; use warnings;

$ENV{"PATH"} = "/usr/bin:/bin";                                                       

my (undef,undef,$hour) = localtime(time);                                             
my $target = $hour - 2; # Flag process before this hour                               
my $grep = 'page.py';                                                   

my @proclist = `ps -ef | grep $grep`;                                                 
foreach my $proc (@proclist)                                                          
{                                                                                     
    $proc =~ /(\w+)\s+(\d+)\s+\d+\s+\d+\s+(.*?).*/;                   
    my $user = $1;                                                                    
    my $pid = $2;                                                                     
    my $stime = $3;                                                                   

    $stime =~ s/(\d+):(\d+)/$1/;                                                      

    # We're going to do a numeric compare against strings that                        
    # potentially compare things like 'Aug01' when the STIME is old                   
    # enough.  We don't care, and we want to catch those old pids, so                 
    # we just turn the warnings off inside this foreach.                              
    no warnings 'numeric';                                                            

    unless ($stime > $target)                                                         
    {                                                                                 
        print "$pid\n";                                                               
    }                                                                                 
}


0

我的服务器在/ proc中的日期有误,并且找不到,因此我编写了以下脚本:

#!/bin/bash

MAX_DAYS=7  #set the max days you want here
MAX_TIME=$(( $(date +'%s') - $((60*60*24*$MAX_DAYS)) ))

function search_and_destroy()
{
        PATTERN=$1
        for p in $(ps ux|grep "$PATTERN"|grep -v grep| awk '{ print $2 }')
        do
            test $(( $MAX_TIME - $(date -d "`ps -p $p -o lstart=`" +'%s') )) -ge 0 && kill -9 $p
        done
}

search_and_destroy " command1 "
search_and_destroy " command2 "

0

在以下版本中使用进程条目的ctime的Python版本/proc

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# kills processes older than HOURS_DELTA hours

import os, time

SIGNAL=15
HOURS_DELTA=1

pids = [int(pid) for pid in os.listdir('/proc') if pid.isdigit()]

for pid in pids:
    if os.stat(os.path.join('/proc', str(pid))).st_ctime < time.time() - HOURS_DELTA * 3600:
        try:
            os.kill(pid, SIGNAL)
        except:
            print "Couldn't kill process %d" % pid

0

我使用这个简单的脚本,它需要两个参数名称process和age,以秒为单位。

#!/bin/bash
# first argument name of the process to check
# second argument maximum age in seconds
# i.e kill lighttpd after 5 minutes
#   script.sh lighttpd 300 
process=$1
maximum_runtime=$2
pid=`pgrep $process`
if [ $? -ne 0 ]
then
        exit 0
fi
process_start_time=`stat /proc/$pid/cmdline --printf '%X'`
current_time=`date +%s`
let diff=$current_time-$process_start_time

if [ $diff -gt $maximum_runtime ]
then
        kill -3 $pid
fi

0

这应该工作

killall --older-than 1h $proc_name


1
如何增加或改善[已经存在的答案]?
收起

2
@Reaces:公平地说,我必须搜索提到的一个答案--older-than ,而忽略它很容易。与其他答案相比,这要容易得多,并且现在还可以在EL7上使用。
斯文

@Reaces这仅比使用awk / sed等编写脚本杀死进程更容易,我想这更简单,更干净
Jabir Ahmed 2015年

0

我对其他解决方案不满意,其中大多数解决方案过于神秘(我的bash知识有限),因此我无法自定义它们……
我创建了自己的解决方案,可能不是最好的解决方案,但它可以正常工作,并且这是可读的

您可以将此脚本保存在文件中并使其可执行(最终使用cron进行调用)

#!/bin/bash
## time in second that trigger the kill
LIMIT=10
## [] skip the grep from the process list
PROC_NAME="[m]y process name"
## etimes return the time in seconds
TIME_SEC=$(ps axo etimes,pid,command | grep "$PROC_NAME" | awk {'print$1'})
PID=$(ps axo etimes,pid,command | grep "$PROC_NAME" | awk {'print$2'})

if [ -n "$TIME_SEC" ] 
    then
    if (( $TIME_SEC > $LIMIT )); then
        kill $PID
    fi
fi

-2

72 = 3天48 = 2天24 = 1天

a1=$(TZ=72 date +%d) ps -ef| cat filex.txt | sed '/[JFMASOND][aepuco][nbrylgptvc] '$a1'/!d' | awk '{ print $2 " " $5 " " $6 }' > file2.txt

有用 :)


1
可能不错,但是很难阅读和学习。考虑重新格式化一些换行符和其他内容。脚本比单行代码更好。
Falcon Momot 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.