Domanda

Ho un problema con alcuni processi simili a zombie su un determinato server che devono essere terminati di tanto in tanto.Come posso identificare al meglio quelli che hanno funzionato per più di un'ora circa?

È stato utile?

Soluzione

Se hanno solo bisogno di essere uccisi:

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

Se vuoi vedere cosa corrisponde

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

IL -i flag ti chiederà sì/no per ogni corrispondenza di processo.

Altri suggerimenti

Ho trovato una risposta che funziona per me:

avvertimento:questo troverà e uccidere processi a lungo termine

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

(Dove ID utente è l'ID di un utente specifico con processi a lunga esecuzione.)

La seconda espressione regolare corrisponde all'ora che ha un numero facoltativo di giorni, seguito da un'ora, un minuto e un secondo componente, quindi dura almeno un'ora.

Per qualsiasi cosa più vecchia di un giorno,

ps aux

ti darà la risposta, ma si riduce alla precisione del giorno che potrebbe non essere altrettanto utile.

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]

Se utilizzi Linux o un altro sistema con il filesystem /proc, in questo esempio puoi solo vedere che il processo 1 è in esecuzione dal 22 giugno, ma nessuna indicazione dell'ora in cui è stato avviato.

stat /proc/<pid>

ti darà una risposta più precisa.Ad esempio, ecco un timestamp esatto per il processo 1, che ps mostra solo come 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

In questo modo è possibile ottenere l'elenco dei dieci processi più vecchi:

ps -elf | sort -r -k12 | head -n 10

Jodie C e altri lo hanno sottolineato killall -i può essere utilizzato, il che va bene se si desidera utilizzare il nome del processo per terminare.Ma se vuoi uccidere con gli stessi parametri di pgrep -f, devi usare qualcosa di simile al seguente, usando pure bash e the /proc filesystem.

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

Ciò ti consente di trovare e terminare processi più vecchi di max_age secondi utilizzando il nome completo del processo;cioè, il processo denominato /usr/bin/python2 offlineimap può essere ucciso facendo riferimento a "offlineimap", mentre il killall le soluzioni qui presentate funzioneranno solo sulla stringa "python2".

Proc::ProcessTable di Perl farà il trucco:http://search.cpan.org/dist/Proc-ProcessTable/

Puoi installarlo in Debian o Ubuntu con sudo apt-get install libproc-processtable-perl

Ecco una riga:

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" } }'

Oppure, più formattato, inseriscilo in un file chiamato 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";
    }
}

poi corri perl process.pl

Ciò ti offre maggiore versatilità e una risoluzione di 1 secondo sull'ora di inizio.

Puoi usare bc per unire i due comandi nella risposta di mob e ottenere quanti secondi sono trascorsi dall'inizio del processo:

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

modificare:

Per noia mentre aspettavamo l'esecuzione di processi lunghi, questo è ciò che è venuto fuori dopo alcuni minuti di tentativi:

#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

Se lo metti sul tuo percorso e lo chiami così:da allora

stamperà la riga cmd del processo e i secondi dall'avvio.Puoi anche inserire questo nel tuo percorso:

#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

E se corri:

greptime <pattern>

dove pattern è una stringa o un'espressione regolare estesa, stamperà tutti i processi che corrispondono a questo modello e i secondi da quando sono stati avviati.:)

fai un ps -aef.questo ti mostrerà l'ora in cui è iniziato il processo.Quindi utilizzando il date il comando trova l'ora corrente.Calcola la differenza tra i due per trovare l'età del processo.

Ho fatto qualcosa di simile alla risposta accettata ma leggermente diversa poiché voglio abbinare in base al nome del processo e in base al processo errato in esecuzione per più di 100 secondi

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

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

per ottenere l'ora di inizio del processo in secondi dall'epoca.Confronta con l'ora corrente (date +%s) per ottenere l'età attuale del processo.

Usare ps è la strada giusta.Ho già fatto qualcosa di simile prima ma non ho la fonte a portata di mano.Generalmente, ps ha un'opzione per indicargli quali campi mostrare e in base a quali ordinare.Puoi ordinare l'output in base al tempo di esecuzione, eseguire il grep sul processo desiderato e quindi terminarlo.

HTH

Nel caso qualcuno ne abbia bisogno in C, puoi usare readproc.h e 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;
}

Mi sono imbattuto da qualche parte...ho pensato che fosse semplice e utile

Puoi usare il comando direttamente in crontab,

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

oppure possiamo scriverlo come script di shell,

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

E chiamalo crontab in questo modo,

* * * * * longprockill.sh

La mia versione di sincetime sopra di @Rafael S.Calsaverini:

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

Questo inverte i campi di output:prima il tempo trascorso, poi il comando completo inclusi gli argomenti.Questo è preferibile perché il comando completo può contenere spazi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top