2008-08-08 36 views

Répondre

28

Si elles ont besoin d'être tué:

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

Si vous voulez voir ce qu'il est correspondant à

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

Le drapeau -i vous demande avec oui/non pour chaque match de processus.

+0

Bon conseil. Je suis tombé sur l'interrupteur --older-than plus tard, mais le -i le rend utile pour vérifier avant de tuer qui sait quoi. – yukondude

+3

Quel est le point de 'if [[" $ (uname) "=" Linux "]];'? La partie pertinente n'est-elle pas juste la commande 'killall'? (Il semble que la clause 'if' qui entoure puisse être supprimée pour rendre cette réponse un peu plus directe) – rinogo

+0

@ringo Parce que sur certains systèmes (par exemple Solaris), killall est une commande entièrement différente.Sur Solaris, il termine toutes les commandes. – ctc

0

L'utilisation de ps est la bonne façon. J'ai déjà fait quelque chose de similaire auparavant mais je n'ai pas la source à portée de main. Généralement - ps a une option pour indiquer quels champs afficher et par quel tri. Vous pouvez trier la sortie en temps réel, grep le processus que vous voulez et ensuite le tuer.

HTH

22

Pour tout plus d'un jour,

ps aux 

vous donnera la réponse, mais il descend à la précision de jour qui pourrait ne pas être aussi 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] 

Si vous êtes sous Linux ou un autre système avec le système de fichiers/proc, Dans cet exemple, on ne peut voir que le processus 1 a été en cours d'exécution depuis le 22 Juin, mais aucune indication du moment où il a commencé.

stat /proc/<pid> 

vous donnera une réponse plus précise. Par exemple, voici un horodatage précis pour le processus 1, qui ps montre seulement comme 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 
+0

Il semble que 'ps' et' stat' montrent des résultats différents pour moi. 'ps' montre que le processus a commencé il y a 1 jour et les statistiques montrent que ça a commencé aujourd'hui. Pourquoi? – pl1nk

+0

Notez que la colonne 'TIME' dans la sortie' ps' n'affiche pas la durée d'exécution réelle d'un processus. Il montre le temps CPU accumulé du processus - le temps que les processeurs ont travaillé avec le processus. –

+0

merci, stat/proc/ m'a donné le résultat exact pour la durée de vie du processus (temps de démarrage) – baptx

36

trouvé une réponse qui fonctionne pour moi:

Avertissement: ce trouvera et tuer longs processus en cours

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

(Où utilisateur-id est l'identifiant d'un utilisateur spécifique aux processus de longue durée.)

La deuxième expression régulière correspond à l'heure qui comporte un nombre de jours optionnel, suivi d'une heure, d'une minute et d'un deuxième composant, et qui est donc d'au moins une heure.

+5

Umm, tu tues le processus? J'espère que les gens se rendent compte que ce code ne se contente pas de trouver, mais qu'il tue aussi, ou qu'ils risquent de se fâcher. –

+0

@ButtleButkus Bon point. Oui, toute la raison de la question était de trouver les anciens processus et de les tuer, mais cela n'est pas explicitement mentionné clairement. Note aux autres: ignorez le dernier petit bout de la ligne à moins de profiter des appels fâchés des utilisateurs. – yukondude

+2

wtf! s'il vous plaît changer le titre de la question. Heureusement, je ne possède pas le processus! –

9

De cette façon, vous pouvez obtenir la liste des dix plus anciens processus:

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

bonnes choses, merci pour cela. –

+0

En fait, cela vous donne les 10 derniers processus parce que par défaut, il montre STIME qui est l'heure à laquelle le programme a démarré. Si ETIME affichait le temps écoulé depuis le début du programme, cela serait correct. –

2

faire un ps -aef. Cela vous montrera l'heure à laquelle le processus a commencé. Ensuite, à l'aide de la commande date, recherchez l'heure actuelle. Calculez la différence entre les deux pour trouver l'âge du processus.

+0

Malheureusement, la sortie de temps ici est difficile à analyser. Il peut s'agir de "HH: MM" pour les processus de courte durée, ou de "MonDD" (éventuellement localisé!) Ou même simplement de l'année pour les processus de très longue durée. –

7

de Proc Perl :: ProcessTable fera l'affaire: http://search.cpan.org/dist/Proc-ProcessTable/

Vous pouvez l'installer dans debian ou ubuntu avec sudo apt-get install libproc-processtable-perl

Voici un one-liner:

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

Ou, plus formaté, mettez cela dans un fichier appelé processus.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"; 
    } 
} 

puis exécutez perl process.pl

Cela vous donne plus de polyvalence et 1 seconde résolution sur le temps de démarrage.

1

j'ai fait quelque chose de similaire à la réponse acceptée, mais un peu différemment puisque je veux correspondre basé sur le nom du processus et en fonction du mauvais processus en cours d'exécution pendant plus de 100 secondes

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

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

pour obtenir l'heure de début du processus en secondes depuis l'époque. Comparez avec l'heure actuelle (date +%s) pour obtenir l'âge actuel du processus.

+0

Nous pouvons joindre les deux commandes pour obtenir des secondes depuis le début du processus: "echo' stat -t/proc/ | awk '{print $ 14}' '-' date +% s' | bc " –

+1

Ce ne sera pas toujours avoir raison - du moins pas pour les systèmes Linux 2.6. J'ai un processus qui a commencé à 9h49 mais stat -t (et stat) montre qu'il a commencé à 13h14. –

+0

@dpk: parfois vous avez un processus principal et quelques fourchettes en cours d'exécution. Le processus principal doit être 9h49, mais le processus enfant peut avoir une date plus récente. La même chose s'applique aux threads d'un processus. – higuita

0

Au cas où quelqu'un a besoin de ce en C, vous pouvez utiliser readproc.h et 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; 
} 
3

Vous pouvez utiliser bc pour joindre les deux commandes dans la réponse de foule et d'obtenir le nombre de secondes ellapsed depuis que le processus a commencé:

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

modifier:

Par ennui en attendant de longs processus pour exécuter , voici ce qui est sorti au bout de quelques minutes de violoneux:

#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 

Si vous mettez cela sur votre chemin et appelez comme ceci: sincetime

il imprimera le processus cmdline et secondes depuis le début. Vous pouvez aussi mettre dans votre chemin:

#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 

Et que si vous exécutez:

greptime <pattern> 

où des motifs est une chaîne ou expression régulière étendue, il affichera tous les processus correspondant à ce modèle et la secondes depuis qu'ils ont commencé. :)

7

Jodie C et d'autres ont souligné que killall -i peut être utilisé, ce qui est bien si vous voulez utiliser le nom du processus à tuer. Mais si vous voulez tuer par les mêmes paramètres que pgrep -f, vous devez utiliser quelque chose comme ce qui suit, en utilisant pur bash et le système de fichiers /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  

Cela vous permet de trouver et de tuer des processus de plus de max_age secondes en utilisant le nom du processus complet ; c'est à dire., le processus nommé /usr/bin/python2 offlineimap peut être tué par référence à "offlineimap", alors que les solutions killall présentées ici ne fonctionneront que sur la chaîne "python2".

0

Entré dans somewhere..thought il est simple et utile

Vous pouvez utiliser la commande dans crontab directement,

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

ou, nous pouvons l'écrire comme script shell,

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

Et l'appeler crontab comme si,

* * * * * longprockill.sh