Frage

Ich habe ein Problem mit einigen zombieähnlichen Prozessen auf einem bestimmten Server, die hin und wieder beendet werden müssen.Wie kann ich am besten diejenigen identifizieren, die länger als etwa eine Stunde gelaufen sind?

War es hilfreich?

Lösung

Wenn sie nur getötet werden müssen:

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

Wenn Sie sehen möchten, was dazu passt

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

Der -i Flag fordert Sie für jede Prozessübereinstimmung mit Ja/Nein auf.

Andere Tipps

Ich habe eine Antwort gefunden, die für mich funktioniert:

Warnung:das wird finden und töten lang laufende Prozesse

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

(Wo Benutzer-ID ist die ID eines bestimmten Benutzers mit lang laufenden Prozessen.)

Der zweite reguläre Ausdruck entspricht einer Zeit, die optional eine Tageszahl enthält, gefolgt von einer Stunde, einer Minute und einer zweiten Komponente und daher mindestens eine Stunde lang ist.

Für alles, was älter als einen Tag ist,

ps aux

wird Ihnen die Antwort geben, aber sie sinkt auf die Tagesgenauigkeit, was möglicherweise nicht so nützlich ist.

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]

Wenn Sie Linux oder ein anderes System mit dem /proc-Dateisystem verwenden, können Sie in diesem Beispiel nur sehen, dass Prozess 1 seit dem 22. Juni ausgeführt wird, aber keine Angabe zum Zeitpunkt des Starts.

stat /proc/<pid>

werde Dir eine genauere Antwort geben.Hier ist zum Beispiel ein genauer Zeitstempel für Prozess 1, der ps nur als Jun22 anzeigt:

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

Auf diese Weise erhalten Sie die Liste der zehn ältesten Prozesse:

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

Jodie C und andere haben darauf hingewiesen killall -i kann verwendet werden, was in Ordnung ist, wenn Sie den Prozessnamen zum Beenden verwenden möchten.Aber wenn Sie mit den gleichen Parametern töten möchten wie pgrep -f, müssen Sie etwas wie das Folgende verwenden, indem Sie pure bash und das verwenden /proc Dateisystem.

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

Auf diese Weise können Sie Prozesse finden und beenden, die älter sind als max_age Sekunden mit der Vollständiger Prozessname;d. h. der genannte Prozess /usr/bin/python2 offlineimap kann durch Verweis auf „offlineimap“ getötet werden, wohingegen die killall Die hier vorgestellten Lösungen funktionieren nur mit der Zeichenfolge „python2“.

Perls Proc::ProcessTable erledigt den Zweck:http://search.cpan.org/dist/Proc-ProcessTable/

Sie können es in Debian oder Ubuntu mit installieren sudo apt-get install libproc-processtable-perl

Hier ist ein Einzeiler:

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

Oder formatierter: Fügen Sie dies in eine Datei namens „process.pl“ ein:

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

dann renne perl process.pl

Dies bietet Ihnen mehr Vielseitigkeit und eine Auflösung von 1 Sekunde bei der Startzeit.

Sie können verwenden bc um die beiden Befehle in Mobs Antwort zu verbinden und zu ermitteln, wie viele Sekunden seit Beginn des Prozesses vergangen sind:

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

bearbeiten:

Aus Langeweile beim Warten auf lange Prozesse ist nach ein paar Minuten Fummelei Folgendes herausgekommen:

#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

Wenn Sie dies auf Ihren Weg bringen und es so nennen:seit jeher

Es werden die Befehlszeile und die Sekunden seit dem Start des Prozesses ausgegeben.Sie können dies auch in Ihren Pfad einfügen:

#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

Und wenn Sie laufen:

greptime <pattern>

Wenn „Muster“ eine Zeichenfolge oder ein erweiterter regulärer Ausdruck ist, werden alle Prozesse, die diesem Muster entsprechen, und die Sekunden seit ihrem Start ausgedruckt.:) :)

mach ein ps -aef.Dadurch wird Ihnen der Zeitpunkt angezeigt, zu dem der Vorgang gestartet wurde.Dann verwenden Sie die date Befehl findet die aktuelle Uhrzeit.Berechnen Sie die Differenz zwischen beiden, um das Alter des Prozesses zu ermitteln.

Ich habe etwas Ähnliches wie die akzeptierte Antwort gemacht, aber etwas anders, da ich eine Übereinstimmung basierend auf dem Prozessnamen und basierend auf dem fehlerhaften Prozess, der länger als 100 Sekunden läuft, abgleichen möchte

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

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

um die Startzeit des Prozesses in Sekunden seit der Epoche zu erhalten.Vergleichen Sie mit der aktuellen Zeit (date +%s), um das aktuelle Alter des Prozesses zu ermitteln.

Die Verwendung von ps ist der richtige Weg.Ich habe schon einmal etwas Ähnliches gemacht, habe aber die Quelle nicht zur Hand.Im Allgemeinen verfügt ps über die Option, anzugeben, welche Felder angezeigt und nach welchen sortiert werden sollen.Sie können die Ausgabe nach Laufzeit sortieren, den gewünschten Prozess durchsuchen und ihn dann beenden.

HTH

Falls jemand dies in C benötigt, können Sie readproc.h und libproc verwenden:

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

Irgendwo entdeckt. Ich dachte, es ist einfach und nützlich

Sie können den Befehl direkt in crontab verwenden.

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

oder wir können es als Shell-Skript schreiben,

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

Und nenne es Crontab so,

* * * * * longprockill.sh

Meine Version von sincetime oben von @Rafael S.Calsaverini:

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

Dadurch werden die Ausgabefelder umgekehrt:Zuerst die verstrichene Zeit, dann der vollständige Befehl einschließlich der Argumente.Dies wird bevorzugt, da der vollständige Befehl Leerzeichen enthalten kann.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top