आप एक निश्चित उम्र से पुराने सभी लिनक्स प्रक्रियाओं को कैसे मारते हैं?

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

0
ro fr bn
या मेरा उत्तर देखें जो pgrep का उपयोग करता है और इस प्रकार killall से अधिक लचीला है।
जोड़ा लेखक g33kz0r, स्रोत
लिनक्स में killall -i --older-1h someprocessname का उपयोग करें
जोड़ा लेखक sanmai, स्रोत

13 उत्तर

एक दिन से भी पुराने किसी भी चीज़ के लिए,

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/

आपको एक और सटीक उत्तर देगा। उदाहरण के लिए, प्रक्रिया 1 के लिए एक सटीक टाइमस्टैंप है, जो पीएस केवल 2222 के रूप में दिखाता है:

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
जोड़ा
मैं यह भी ध्यान में रखूंगा कि यदि पिछले वर्ष में प्रक्रिया शुरू की गई थी, तो स्टार्ट कॉलम केवल वर्ष सूचीबद्ध करता है। बहुत सटीक नहीं है। बिलकुल। इसके अलावा, जब मैंने पिछले साल से लंबे समय से चलने वाले टीएमयूक्स सत्र की proc / id को स्टेट किया था, तो इस साल से इसकी तारीख वापस आई। समाधान के साथ मैं गया: <कोड> ps -eo pid, etime | grep $ पीआईडी ​​
जोड़ा लेखक Steven Lu, स्रोत
ऐसा लगता है कि ps और stat मेरे लिए अलग-अलग परिणाम दिखा रहा है। ps दिखाता है कि प्रक्रिया 1 दिन पहले शुरू हुई थी और स्टेट शो जो आज शुरू हुआ था। क्यूं कर?
जोड़ा लेखक pl1nk, स्रोत
ध्यान दें कि ps आउटपुट में TIME कॉलम एक प्रक्रिया के वास्तविक रन टाइम को नहीं दिखाता है। यह प्रक्रिया के संचित CPU समय को दिखाता है - जिस समय सीपीयू ने प्रक्रिया के साथ काम किया था।
जोड़ा लेखक matthias krull, स्रोत
धन्यवाद, स्टेट / proc / ने मुझे प्रक्रिया जीवनकाल (स्टार्टअप समय) के लिए सटीक परिणाम दिया
जोड़ा लेखक baptx, स्रोत

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

ps -elf | sort -r -k12 | head -n 10
0
जोड़ा
दरअसल यह आपको 10 नवीनतम प्रक्रियाएं देता है क्योंकि डिफ़ॉल्ट रूप से यह STIME दिखाता है जो प्रोग्राम शुरू हुआ था। यदि यह ईटीआईएमई दिखा रहा था जो कार्यक्रम शुरू होने के बाद से समाप्त हो गया है तो यह सही होगा।
जोड़ा लेखक Sarel Botha, स्रोत
अच्छी चीजें, इसके लिए धन्यवाद।
जोड़ा लेखक donovan.lampa, स्रोत

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

HTH

0
जोड़ा

एक उत्तर मिला जो मेरे लिए काम करता है:

चेतावनी: यह और लंबी चल रही प्रक्रियाओं को मिलेगा

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

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

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

0
जोड़ा
@ बटलबूटस अच्छा बिंदु। हां, सवाल का पूरा कारण पुरानी प्रक्रियाओं को ढूंढना और उन्हें मारना था, लेकिन स्पष्ट रूप से स्पष्ट रूप से इसका उल्लेख नहीं किया गया है। दूसरों के लिए ध्यान दें: जब तक आप उपयोगकर्ताओं से नाराज कॉल का आनंद न लें तब तक लाइन के आखिरी छोटे हिस्से को अनदेखा करें।
जोड़ा लेखक yukondude, स्रोत
@ मार्की 555 जो सिर्फ टिकट की तरह लगता है। पीएस के एक और हालिया संस्करण में होना चाहिए जो मैं चल रहा हूं, क्योंकि यह एक विकल्प के रूप में सूचीबद्ध नहीं है।
जोड़ा लेखक yukondude, स्रोत
उम्म, क्या आप प्रक्रिया को मार रहे हैं? मुझे उम्मीद है कि लोगों को यह एहसास होगा कि यह कोड न सिर्फ खोजता है, बल्कि मारता है, या वे परेशान हो सकते हैं।
जोड़ा लेखक Buttle Butkus, स्रोत
आप etime के बजाय विकल्प etimes का उपयोग कर सकते हैं हमेशा सेकंड में बीत चुके समय को प्रदर्शित करने के लिए और दिन / घंटे नहीं ...
जोड़ा लेखक Marki555, स्रोत
@ युकोंडुड आप सही हैं। मैंने अभी इसे जांच लिया है और ps v3.2.8 डेबियन निचोड़ से etimes पैरामीटर का समर्थन नहीं करता है, हालांकि डेबियन wheezy से v3.3.3 करता है।
जोड़ा लेखक Marki555, स्रोत
WTF! कृपया प्रश्न का शीर्षक बदलें। सौभाग्य से मैं प्रक्रिया का मालिक नहीं है!
जोड़ा लेखक neal aise, स्रोत

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

echo `date +%s` - `stat -t /proc/ | 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 

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

0
जोड़ा

Perl's Proc::ProcessTable will do the trick: http://search.cpan.org/dist/Proc-ProcessTable/

You can install it in debian or ubuntu with sudo apt-get install libproc-processtable-perl

यहां एक लाइनर है:

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

या, अधिक स्वरूपित, इसे 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";
    }
}

then run perl process.pl

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

0
जोड़ा

जोडी सी और अन्य ने इंगित किया है कि 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 ऑफ़लाइनमैप नाम की प्रक्रिया को "ऑफ़लाइनमैप" के संदर्भ में मार दिया जा सकता है, जबकि यहां प्रस्तुत killall समाधान केवल स्ट्रिंग पर काम करेंगे "python2 "।

0
जोड़ा

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

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

0
जोड़ा
प्रक्रिया शुरू होने के बाद से हम सेकंड्स प्राप्त करने के लिए दो आदेशों में शामिल हो सकते हैं: "echo stat -t / proc / | awk '{print $ 14}' - date +% s | बीसी "
जोड़ा लेखक Rafael S. Calsaverini, स्रोत
@ डीपीके: कभी-कभी आपके पास मुख्य प्रक्रिया होती है और कुछ कांटे चलते हैं। मुख्य प्रक्रिया 9:49 होनी चाहिए, लेकिन बाल प्रक्रिया में कोई और हालिया समय हो सकता है। यह एक प्रक्रिया के धागे पर लागू होता है।
जोड़ा लेखक higuita, स्रोत

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

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

मैंने स्वीकार्य उत्तर के समान कुछ किया लेकिन थोड़ा अलग है क्योंकि मैं प्रक्रिया नाम के आधार पर मिलान करना चाहता हूं और 100 सेकंड से अधिक समय तक चल रही खराब प्रक्रिया के आधार पर

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

यदि किसी को सी में इसकी आवश्यकता है, तो आप readproc.h और libproc का उपयोग कर सकते हैं:

#include 
#include 

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;
}
0
जोड़ा

अगर उन्हें सिर्फ मारने की जरूरत है:

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, स्रोत
if [["$ (uname)" = "Linux"]] का बिंदु क्या है; ? प्रासंगिक भाग सिर्फ killall कमांड नहीं है? (ऐसा लगता है कि आसपास के if खंड को इस उत्तर को थोड़ा और प्रत्यक्ष बनाने के लिए हटाया जा सकता है)
जोड़ा लेखक rinogo, स्रोत
@ringo क्योंकि कुछ प्रणालियों (जैसे सोलारिस) पर, killall एक पूरी तरह से अलग आदेश है। सोलारिस पर, यह सभी आदेशों को समाप्त करता है।
जोड़ा लेखक ctc, स्रोत

कहीं कहीं आया .. सोचा कि यह सरल और उपयोगी है

आप सीधे 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
0
जोड़ा