2008-08-08 33 views
65

मुझे कुछ ज़ोंबी जैसी प्रक्रियाओं के साथ एक निश्चित सर्वर पर समस्या है जिसे हर समय और फिर मारने की आवश्यकता है। मैं उन लोगों की सबसे अच्छी पहचान कैसे कर सकता हूं जो एक घंटे से अधिक समय तक चल रहे हैं?आप एक निश्चित आयु से अधिक की सभी लिनक्स प्रक्रियाओं को कैसे मारते हैं?

+5

लिनक्स में 'killall -i --older-1h someprocessname' – sanmai

+0

का उपयोग करें या मेरा उत्तर देखें जो 'pgrep' का उपयोग करता है और इस प्रकार 'killall' से अधिक लचीला है। – g33kz0r

उत्तर

28

वे सिर्फ मारे जाने के लिए की जरूरत है:

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

आप को देखने के लिए यह क्या चाहते हैं मिलान

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

-i झंडा प्रत्येक प्रक्रिया मैच के लिए हाँ के साथ संकेत देगा/कोई।

+0

अच्छी टिप। मैं बाद में स्विच की तुलना में --ल्डर पर ठोकर खाई, लेकिन -i यह जानने के लिए उपयोगी बनाता है कि कौन जानता है। – yukondude

+3

'if [[" $ (uname) "=" Linux "]] का बिंदु क्या है? प्रासंगिक भाग सिर्फ 'killall' कमांड नहीं है? (ऐसा लगता है कि आसपास के 'अगर' खंड को इस उत्तर को थोड़ा और प्रत्यक्ष बनाने के लिए हटाया जा सकता है) – rinogo

+0

@ringo कुछ प्रणालियों (जैसे सोलारिस) पर, killall एक पूरी तरह से अलग आदेश है।सोलारिस पर, यह सभी आदेशों को समाप्त करता है। – ctc

0

पीएस का उपयोग करना सही तरीका है। मैंने पहले ही कुछ ऐसा ही किया है लेकिन स्रोत को आसान नहीं है। आम तौर पर - पीएस के पास यह बताने का विकल्प होता है कि कौन से फ़ील्ड दिखाना है और किस प्रकार से सॉर्ट करना है। आप समय चलकर आउटपुट को सॉर्ट कर सकते हैं, जिस प्रक्रिया को आप चाहते हैं उसे grep करें और फिर इसे मार दें।

HTH

22

एक दिन से अधिक उम्र कुछ भी के लिए,

ps aux 

आप इस सवाल का जवाब दे देंगे, लेकिन यह दिन परिशुद्धता जो के रूप में उपयोगी नहीं हो सकता है के लिए नीचे चला जाता है।

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] 

आप लिनक्स या/proc फाइल सिस्टम के साथ एक और प्रणाली पर हैं, तो इस उदाहरण में, आप केवल उस प्रक्रिया 1 22 जून के बाद से चल रहा है देख सकते हैं, लेकिन समय का कोई संकेत नहीं है कि यह शुरू किया गया था।

stat /proc/<pid> 

आपको एक और सटीक उत्तर देगा।

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

ऐसा लगता है कि 'ps' और 'stat' मेरे लिए अलग-अलग परिणाम दिखा रहा है। 'पीएस' से पता चलता है कि प्रक्रिया 1 दिन पहले शुरू हुई थी और स्टेट शो जो आज शुरू हुआ था। क्यूं कर? – pl1nk

+0

ध्यान दें कि 'ps' आउटपुट में' TIME' कॉलम किसी प्रक्रिया के वास्तविक रन टाइम को नहीं दिखाता है। यह प्रक्रिया के संचित CPU समय को दिखाता है - जिस समय सीपीयू ने प्रक्रिया के साथ काम किया था। –

+0

धन्यवाद, स्टेट/proc/ ने मुझे प्रक्रिया जीवनकाल (स्टार्टअप समय) – baptx

36

एक जवाब है कि मेरे लिए काम करता मिला::

चेतावनी: इस खोजने के लिए और लंबे प्रक्रियाओं चल मार डालेगा उदाहरण के लिए, यहाँ प्रक्रिया 1 के लिए एक सटीक टाइमस्टैम्प, जो ps केवल Jun22 रूप से पता चलता है

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

(कहाँ उपयोगकर्ता के आईडी लंबे समय से चल प्रक्रियाओं के साथ एक विशिष्ट उपयोगकर्ता की आईडी है।)

दूसरी नियमित अभिव्यक्ति उस समय से मेल खाती है जिसमें एक वैकल्पिक दिन का आंकड़ा होता है, उसके बाद एक घंटे, मिनट और दूसरा घटक होता है, और कम से कम एक घंटे की लंबाई होती है।

+5

उम्म, क्या आप प्रक्रिया को मार रहे हैं? मुझे उम्मीद है कि लोगों को यह एहसास होगा कि यह कोड न सिर्फ खोजता है, बल्कि मारता है, या वे परेशान हो सकते हैं। –

+0

@ बटलबूटस अच्छा बिंदु। हां, सवाल का पूरा कारण पुरानी प्रक्रियाओं को ढूंढना और उन्हें मारना था, लेकिन स्पष्ट रूप से स्पष्ट रूप से इसका उल्लेख नहीं किया गया है। दूसरों के लिए ध्यान दें: जब तक आप उपयोगकर्ताओं से नाराज कॉल का आनंद न लें तब तक लाइन के आखिरी छोटे हिस्से को अनदेखा करें। – yukondude

+2

wtf! कृपया प्रश्न का शीर्षक बदलें। सौभाग्य से मैं प्रक्रिया का मालिक नहीं है! –

9

इस तरह आप दस सबसे पुराने प्रक्रियाओं की सूची प्राप्त कर सकते हैं:

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

अच्छी चीजें, इसके लिए धन्यवाद। –

+0

असल में जो आपको 10 नवीनतम प्रक्रियाएं देता है क्योंकि डिफ़ॉल्ट रूप से यह STIME दिखाता है जो प्रोग्राम शुरू हुआ था। यदि यह ईटीआईएमई दिखा रहा था जो कार्यक्रम शुरू होने के बाद से समाप्त हो गया है तो यह सही होगा। –

2

एक ps -aef है। यह आपको वह समय दिखाएगा जिस पर प्रक्रिया शुरू हुई थी। फिर date कमांड का उपयोग वर्तमान समय ढूंढें। प्रक्रिया की उम्र खोजने के लिए दोनों के बीच के अंतर की गणना करें।

+0

दुर्भाग्य से यहां समय आउटपुट पार्स करना मुश्किल है। यह शॉर्ट-रनिंग प्रक्रियाओं के लिए "एचएच: एमएम" हो सकता है, या "एमएनडीडी" (संभवतः स्थानीयकृत!) या यहां तक ​​कि केवल बहुत लंबी चल रही प्रक्रियाओं के लिए वर्ष हो सकता है। –

7

पर्ल के प्रोक :: ProcessTable चाल करना होगा: sudo apt-get install libproc-processtable-perl

यहाँ के साथ http://search.cpan.org/dist/Proc-ProcessTable/

आप डेबियन में स्थापित कर सकते हैं या ubuntu एक एक लाइनर है:

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

या, अधिक स्वरूपित, इसे प्रक्रिया नामक फ़ाइल में डालें।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"; 
    } 
} 

तो चलाने perl process.pl

यह आपको अधिक बहुमुखी प्रतिभा और प्रारंभ समय पर 1-दूसरे संकल्प देता है।

1

मैं स्वीकार किए जाते हैं जवाब देने के लिए समान है, लेकिन कुछ अलग ढंग से के बाद से मैं इस प्रक्रिया नाम के आधार पर और 100 से अधिक सेकंड

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

पाने के लिए चल रहा है बुरा प्रक्रिया के आधार पर मिलान करना चाहते हैं कुछ किया युग के बाद से सेकंड में प्रक्रिया का प्रारंभ समय। प्रक्रिया की वर्तमान उम्र प्राप्त करने के लिए वर्तमान समय (date +%s) के साथ तुलना करें।

+0

प्रक्रिया शुरू होने के बाद से हम सेकंड्स प्राप्त करने के लिए दो आदेशों में शामिल हो सकते हैं: "echo' stat -t/proc/ | awk '{print $ 14}' '-' date +% s' | bc " –

+1

यह हमेशा नहीं होगा सही हो - कम से कम लिनक्स 2.6 सिस्टम के लिए नहीं। मेरे पास एक प्रक्रिया है जो 9:49 बजे शुरू हुई लेकिन स्टेट-टी (और स्टेट) दिखाती है कि यह 13:14 बजे शुरू हुआ। –

+0

@ डीपीके: कभी-कभी आपके पास मुख्य प्रक्रिया होती है और कुछ कांटे चलते हैं। मुख्य प्रक्रिया 9:49 होनी चाहिए, लेकिन बाल प्रक्रिया में कोई और हालिया समय हो सकता है। यह एक प्रक्रिया के धागे पर लागू होता है। – higuita

0

मामले में किसी को भी सी में इस की जरूरत है, तो आप readproc.h और 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

आप bc उपयोग कर सकते हैं भीड़ के जवाब में दो आदेशों में शामिल होने और कितने सेकंड ellapsed के बाद से प्रक्रिया आरंभ करने के लिए:

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

संपादित करें:

बोरियत से बाहर लंबा प्रक्रियाओं को चलाने के लिए इंतजार कर रहे हैं, जबकि , यह क्या नगण्य कुछ मिनट के बाद बाहर आ गया है:

#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 

आप अपने रास्ते पर इस डाल दिया और इसे इस तरह कॉल करते हैं: sincetime

यह प्रक्रिया के बाद से cmdline और सेकंड को प्रिंट करेगा। आप भी अपने रास्ते में इस डाल सकते हैं:

#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 

और अगर आप से चलाएँ:

greptime <pattern> 

जहां पैटर्न एक स्ट्रिंग या विस्तारित नियमित अभिव्यक्ति है, यह सभी प्रक्रियाओं बाहर प्रिंट होगा इस पैटर्न से मेल खाते और सेकंड शुरू होने के बाद से सेकंड। :)

7

जोडी सी और अन्य ने इंगित किया है कि killall -i का उपयोग किया जा सकता है, यदि आप प्रक्रिया के नाम को मारने के लिए उपयोग करना चाहते हैं तो ठीक है। लेकिन अगर आप pgrep -f के समान पैरामीटर से मारना चाहते हैं, तो आपको शुद्ध बैश और /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  

इससे आपको यह जानने और पूरी प्रक्रिया को नाम का उपयोग कर max_age सेकंड से अधिक उम्र के प्रक्रियाएं समाप्त करने देता है; अर्थात।, /usr/bin/python2 offlineimap नाम की प्रक्रिया को "ऑफ़लाइनमैप" के संदर्भ में मार दिया जा सकता है, जबकि यहां प्रस्तुत killall समाधान केवल स्ट्रिंग "पायथन 2" पर काम करेंगे।

0

भर में आया somewhere..thought यह सरल और उपयोगी

आप crontab सीधे में आदेश का उपयोग कर सकते हैं,

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

या, हम खोल स्क्रिप्ट के रूप में यह लिख सकते हैं,

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

और इसे क्रॉन्टाब को कॉल करें,

* * * * * longprockill.sh