Como faço para matar processos mais antigos que “t”?

12

Primeiro, sim, já vi essa pergunta:

Encontre (e mate) processos antigos

As respostas estão incorretas e não funcionam. Eu votei e comentei de acordo.

Os processos que eu quero matar ficam assim quando listados com ps aux | grep page.py :

apache     424  0.0  0.1   6996  4564 ?        S    07:02   0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache    2686  0.0  0.1   7000  3460 ?        S    Sep10   0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache    2926  0.0  0.0   6996  1404 ?        S    Sep02   0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache    7398  0.0  0.0   6996  1400 ?        S    Sep01   0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache    9423  0.0  0.1   6996  3824 ?        S    Sep10   0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache   11022  0.0  0.0   7004  1400 ?        S    Sep01   0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache   15343  0.0  0.1   7004  3788 ?        S    Sep09   0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache   15364  0.0  0.1   7004  3792 ?        S    Sep09   0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache   15397  0.0  0.1   6996  3788 ?        S    Sep09   0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache   16817  0.0  0.1   7000  3788 ?        S    Sep09   0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache   17590  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   7000  1432 ?        S    Sep07   0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache   30361  0.0  0.1   6996  3776 ?        S    Sep09   0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py

Estou tentando configurar um cron diário simples que encontre e mate qualquer page.py de processos com mais de uma hora.

A resposta aceita na questão acima mencionada não funciona, pois não corresponde a um intervalo de vezes, ela simplesmente corresponde a processos que foram executados de 7 dias a 7 dias, 23 horas, 59 minutos e 59 segundos. Não quero matar processos que foram executados de 1 a 2 horas, mas sim qualquer coisa maior que 1 hora.

A outra resposta à questão acima mencionada usando find não funciona, pelo menos não no Gentoo ou no CentOS 5.4, ou ele avisa ou não retorna nada se o aviso do aviso for seguido.

    
por hobodave 15.09.2010 / 19:05

16 respostas

8

Graças à resposta de Christopher, consegui adaptá-lo ao seguinte:

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

-mmin foi o comando de localização que estava faltando.

    
por 15.09.2010 / 20:10
19

O GNU Killall pode matar processos mais antigos que uma determinada idade, usando seu nome de processo.

if [[ "$(uname)" = "Linux" ]];then killall --older-than 1h page.py;fi
    
por 29.05.2012 / 05:11
6

o find nem sempre funciona, nem todo sistema tem etimes disponíveis, e pode ser o meu status de regex newb, mas eu não acho que você precise de algo mais do que isso:

ps -eo pid,etime,comm,user,tty | grep builder | grep pts | grep -v bash |awk '$2~/-/ {if ($2>7) print $1}'
  • encontre o processo em execução como criador de usuário, executado a partir de pts de login interativos, exclua processos bash
  • a segunda coluna será o tempo decorrido (etime)
  • use o awk na segunda coluna ($ 2) e obtenha com um regex (~) a string antes do - (ps etime imprime no formato dd-hh: mm: ss)
  • Se esse valor for maior que 7 (ou seja, executado em mais de sete dias), imprima o que está na primeira coluna $ 1, ou seja, pid

você pode canalizar isso para matar ou qualquer que seja sua necessidade.

    
por 17.08.2012 / 12:32
3

Acho que você pode modificar algumas dessas respostas anteriores para atender às suas necessidades. A saber:

for FILE in (find . -maxdepth 1 -user processuser -type d -mmin +60)
  do kill -9 $(basename $FILE) # I can never get basename to work with find's exec.  Let me know if you know how!
done

Ou

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

Acho que o segundo pode se adequar melhor às suas necessidades. A versão find acabaria com a nuking outros processos por esse usuário


- Christopher Karel

    
por 15.09.2010 / 19:48
3
apt-get install psmisc

killall -o 1h $proc_name
    
por 31.03.2016 / 00:58
3
# get elapsed time in seconds, filter our only those who >= 3600 sec
ps axh -O etimes  | awk '{if ($2 >= 3600) print $2}'

Se você quiser, pode alimentar ps com a lista de PIDs para procurar dentro, por e. g .:

ps h -O etimes 1 2 3
    
por 29.05.2012 / 08:20
2

O problema

Convertendo a coluna etime (tempo decorrido) do comando ps para segundos. A especificação de hora está neste formato [[dd-]hh:]mm:ss . Versões mais recentes de ps têm uma coluna etimes que gera etime em segundos.

A solução: função awk personalizada simples

Esta função awk personalizada suporta todos os formatos da coluna etime (por exemplo, 03-12:30:59 , 00:07 etc.). Basta colá-lo em seu script awk, é uma solução amigável de uma linha.

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) converte T em segundos
  • T especificação de tempo em [[dd-]hh:]mm:ss format (por exemplo, etime )
  • C contagem de campos em T (equivalente a variável NF do awk)
  • A matriz de campos em T (equivalente à variável $ do awk)
  • A[C>3?C-3:99] esta é uma maneira segura de referenciar o quarto valor (ou seja, o número de dias) na ordem inversa. Essa abordagem é útil porque dias e horas são opcionais. Se a matriz não for longa o suficiente, será cancelada a referência A[99] , que renderá 0 valor. Eu assumo que 99 é alto o suficiente para a maioria dos casos de uso.
  • retorna segundos como inteiro

Exemplo do mundo real

Esse basel oneliner matará o processo soffice.bin em execução no usuário atual se o processo tiver mais de 180 segundos.

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}')
    
por 12.11.2016 / 11:19
1

O campo lstart em ps fornece um formato de hora consistente, que podemos fornecer a date para converter em segundos desde a época. Então, apenas comparamos isso com o tempo atual.

#!/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
    
por 16.09.2010 / 01:25
0

Eu modifiquei a resposta que eles lhe deram no post anterior

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

A expressão regular procura 2 tipos de segundo argumento:

  • Dias na forma de dígitos e um sinal de menos.
  • Hours:minutes:seconds expression.

Isso deve corresponder a tudo, exceto aos processos jovens, que teriam o formato minutes:seconds .

    
por 15.09.2010 / 20:01
0

Este é provavelmente um exagero, mas fiquei curioso o suficiente para terminar e testar se funciona (em um nome de processo diferente no meu sistema, é claro). Você pode matar a captura de $user e $pid para simplificar o regexp, que eu adicionei apenas para depuração, e não tive vontade de voltar atrás. Capturas nomeadas do perl 5.10 eliminariam mais algumas linhas, mas isso deve funcionar em perls mais antigos.

Você precisará substituir a impressão por um kill, é claro, mas eu não ia matar nada no meu próprio sistema.

#!/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";                                                               
    }                                                                                 
}

    
por 15.09.2010 / 20:33
0

Eu tenho um servidor com datas erradas em / proc e o find não funciona, então eu escrevi este script:

#!/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 "
    
por 10.08.2011 / 15:42
0

Versão do Python usando o ctime das entradas do processo em /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
    
por 10.08.2011 / 16:07
0

Eu uso este script simples que leva dois argumentos nome do processo e idade em segundos.

#!/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
    
por 12.09.2013 / 18:21
0

Eu não estava satisfeito com a outra solução, a maioria deles é muito enigmática (meu conhecimento bash é meio limitado) e por isso não posso personalizá-los ...
Eu criei minha própria solução, provavelmente não é o melhor, mas funciona e é legível

Você pode salvar este script em um arquivo e torná-lo executável (eventualmente chamá-lo usando o 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
    
por 25.02.2017 / 13:27
-1

isso deve funcionar

killall --older-than 1h $proc_name

    
por 12.10.2015 / 15:42
-2

72 = 3 dias 48 = 2 dias 24 = 1 dia

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

funciona:)

    
por 25.04.2015 / 08:28