ฉันจะฆ่ากระบวนการที่เก่ากว่า“ t” ได้อย่างไร


14

ครั้งแรกใช่ฉันได้เห็นคำถามนี้:

ค้นหา (และฆ่า) กระบวนการเก่า

คำตอบมีไม่ถูกต้องและไม่ทำงาน ฉันได้ลงคะแนนและแสดงความคิดเห็นตาม

กระบวนการที่ฉันต้องการฆ่ามีลักษณะเช่นนี้เมื่อจดทะเบียนกับps aux | grep page.py:

apache 424 0.0 0.1 6996 4564? S 07:02 0:00 / usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 2686 0.0 0.1 7000 3460? วันที่ Sep10 0:00 / usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 2926 0.0 0.0 6996 1404? วันที่ Sep02 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 7398 0.0 0.0 6996 1400? วันที่ Sep01 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 9423 0.0 0.1 6996 3824? วันที่ Sep10 0:00 / usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 11022 0.0 0.0 7004 1400? วันที่ Sep01 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 15343 0.0 0.1 7004 3788? วันที่ Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 15364 0.0 0.1 7004 3792 วันที่ Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 15397 0.0 0.1 6996 3788? วันที่ Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 16817 0.0 0.1 7000 3788? วันที่ Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 17590 0.0 0.0 7000 1432 วันที่ Sep07 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 24448 0.0 0.0 7000 1432 วันที่ Sep07 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
apache 30361 0.0 0.1 6996 3776? วันที่ Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py

ฉันกำลังมองหาการติดตั้ง cron รายวันง่ายๆที่จะค้นหาและฆ่าpage.pyกระบวนการใด ๆ ที่เก่ากว่าหนึ่งชั่วโมง

คำตอบที่ได้รับการยอมรับสำหรับคำถามดังกล่าวไม่ทำงานเนื่องจากไม่ตรงกับช่วงเวลาเพียงจับคู่กระบวนการที่ทำงานจาก 7 วันถึง 7 วัน 23 ชั่วโมง 59 นาทีและ 59 วินาที ฉันไม่ต้องการฆ่ากระบวนการที่ใช้งานจาก 1-2 ชั่วโมง แต่มีอะไรมากกว่า 1 ชั่วโมง

คำตอบอื่น ๆ ของคำถามที่กล่าวถึงการใช้งานfindไม่ได้อย่างน้อยไม่ได้อยู่ใน Gentoo หรือ CentOS 5.4 มันจะพ่นคำเตือนออกไปหรือไม่ส่งคืนสิ่งใดหากปฏิบัติตามคำแนะนำของคำเตือนดังกล่าว

คำตอบ:


22

GNU Killall สามารถฆ่ากระบวนการที่เก่ากว่าอายุที่กำหนดโดยใช้ชื่อกระบวนการ

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

1
ตัวเลือกนั้นไม่สามารถใช้งานได้บน CentOS 6.6 รุ่น: killall (PSmisc) 22.6
ระบุชื่อ

9

ขอบคุณคำตอบของคริสโตเฟอร์ฉันสามารถปรับให้เข้ากับสิ่งต่อไปนี้:

find /proc -maxdepth 1 -user apache -type d -mmin +60 -exec basename {} \; \
| xargs ps | grep page.py | awk '{ print $1 }' | sudo xargs kill

-mmin คือคำสั่ง find ที่ฉันหายไป


3
ไม่แน่ใจว่า - นาทีเหมาะสำหรับการตรวจจับอายุของกระบวนการหรือไม่
LatinSuD

ไม่ปรากฏว่าไดเรกทอรี / proc / ได้รับการแก้ไขอย่างมากดังนั้นนี่จึงใช้งานได้ ที่ถูกกล่าวว่าฉันไม่ต้องการที่จะเรียกร้องมันเป็นไปไม่ได้
Christopher Karel

ฉันไม่คิดว่านี่จะตอบคำถามของคุณได้เนื่องจากคำตอบนี้แคบเกินไปและคำถามนั้นกว้างกว่า
poige

และฉันจะบอกว่ามากกว่านี้ - มันใช้งานไม่ได้เลย: find /proc -maxdepth 1 -type d -name 1 -mmin +60 -ls- / sbin / init ไม่ได้อยู่ในรายการแม้จะมีเวลาทำงานหลายวันไม่ใช่ชั่วโมง ดูเหมือนว่าคุณไม่สามารถพึ่งพา / proc / 's เวลาแก้ไข dirs
poige

3
เวลาบันทึกใน / proc ไม่สามารถขึ้นอยู่กับสิ่งนี้โชคไม่ดี อย่างน้อยก็ไม่มีอีกแล้ว
dpk

8

find ไม่ทำงานเสมอไปทุกระบบมีเวลาให้บริการและอาจเป็นสถานะ newb ของฉัน regex แต่ฉันไม่คิดว่าคุณต้องการอะไรมากกว่านี้:

ps -eo pid,etimes,comm,user,tty | awk '{if ($4 ~ /builder/ && $5 ~ /pts/ && $2>600) print $1}'
  • แสดงรายการกระบวนการทั้งหมดและระบุคอลัมน์ PID, ELAPSED (etimes = วินาที), คำสั่ง, USER, TT (ขอบคุณ @ahoffman)
  • ด้วย awk พิมพ์ PID ที่คอลัมน์ที่ 4 ($ 4, USER) มีข้อความ 'builder' และคอลัมน์ที่ 5 ($ 5, TT) มีข้อความ 'pts' และคอลัมน์ ELAPSED มีค่ามากกว่า 600 วินาที (ขอบคุณ @amtd)

คุณสามารถไปป์นั้นเพื่อฆ่าหรืออะไรก็ตามที่คุณต้องการ


ฉันคิดว่านี่เป็นหนึ่งในโซลูชั่นที่มีประสิทธิภาพมากขึ้นโดยเฉพาะอย่างยิ่งในแง่ของการใช้งานของpsคุณ แต่ฉันจะพับหลายgreps ลงในซิงเกิ้ลawkและเพื่อความปลอดภัย จำกัด การจับคู่รูปแบบกับคอลัมน์เฉพาะ ผู้สร้าง ฯลฯ )
jmtd

นี่เป็นเรื่องปกติเมื่อขอบเขตเวลาของคุณเป็นวัน แต่จะไม่ทำงานถ้าคุณต้องการทดสอบเวลาที่ผ่านไปในชั่วโมงนาทีหรือวินาที
Vlastimil Ovčáčík

ใช้ "etimes" แทน "etime" สิ่งนี้จะคืนค่าเวลาที่ผ่านไปในไม่กี่วินาทีซึ่งง่ายต่อการแยกวิเคราะห์
ahofmann

@jmtd & ahofmann: ฉันได้อัปเดตตามความคิดเห็นของคุณแล้ว ฉันหวังว่าสิ่งนี้จะเป็นไปตามที่คุณตั้งใจไว้
eugenevd

5
# get elapsed time in seconds, filter our only those who >= 3600 sec
ps axh -O etimes  | awk '{if ($2 >= 3600) print $2}'

หากคุณต้องการคุณสามารถป้อนpsด้วยรายการ PID ที่จะค้นหาภายในเช่น:

ps h -O etimes 1 2 3

2
etimesใช้งานได้เฉพาะรุ่นใหม่ps
Tino

4

ฉันคิดว่าคุณสามารถแก้ไขคำตอบก่อนหน้านี้บางส่วนเพื่อให้เหมาะกับความต้องการของคุณ กล่าวคือ:

สำหรับ FILE in (ค้นหา. -maxdepth 1 -user processuser -type d -mmin +60)
  ทำ kill -9 $ (basename $ FILE) # ฉันไม่สามารถรับ basename เพื่อทำงานร่วมกับ exec's find แจ้งให้เราทราบหากคุณรู้วิธี!
เสร็จแล้ว

หรือ

ps -eo pid, etime, comm | awk '$ 2! ~ /^..:..$/ && $ 3 ~ / หน้า \ .py / {พิมพ์ $ 1}' | ฆ่า -9

ฉันคิดว่าครั้งที่สองอาจตอบสนองความต้องการของคุณได้ดีที่สุด รุ่นค้นหาจะไขลานกระบวนการอื่น ๆ โดยผู้ใช้ - ค


ริสโทเฟอร์คาเรล


7
อย่าใช้kill -9ยกเว้นเป็นทางเลือกสุดท้าย ใช้หรือ-SIGINT -SIGTERM
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

นี่คือการใช้รูปแบบของเวลาที่ผ่านไปเป็นเกณฑ์การทดสอบไม่ใช่ค่าของมัน psจะส่งออกเวลาใน^..:..$รูปแบบเมื่อมันน้อยกว่าหนึ่งชั่วโมง
Vlastimil Ovčáčík

4
apt-get install psmisc

killall -o 1h $proc_name

คุณช่วยอธิบายเพิ่มเติมเกี่ยวกับpsmiscยูทิลิตี้ได้หรือไม่? CentOS กล่าวถึง OP; เป็น RPM หรือไม่
Castaglia

4

ปัญหา

etimeคอลัมน์การแปลง(เวลาที่ผ่านไป) ของpsคำสั่งเป็นวินาที ข้อมูลจำเพาะเวลาอยู่ในรูปแบบ[[dd-]hh:]mm:ssนี้ เวอร์ชันที่ใหม่กว่าpsจะมีetimesคอลัมน์ซึ่งให้ผลลัพธ์เป็นetimeวินาที

การแก้ปัญหา: ฟังก์ชั่น awk ที่กำหนดเองง่าย

ฟังก์ชั่น awk ที่กำหนดเองนี้รองรับทุกรูปแบบของetimeคอลัมน์ (เช่น03-12:30:59, 00:07ฯลฯ ) เพียงวางไว้ในสคริปต์ awk ของคุณมันเป็นทางออกที่เป็นมิตรหนึ่งสมุทร

function sec(T){C=split(T,A,"[:-]"); return A[C>3?C-3:99]*86400 + A[C>2?C-2:99]*3600 + A[C>1?C-1:99]*60 + A[C>0?C-0:99]*1}
  • sec(T) แปลง T เป็นวินาที
  • Tข้อมูลจำเพาะเวลาใน[[dd-]hh:]mm:ssรูปแบบ (เช่นetime)
  • Cจำนวนฟิลด์ในT(เทียบเท่ากับตัวแปร NF ของ awk)
  • Aอาร์เรย์ของฟิลด์ในT(เทียบเท่ากับ $ ตัวแปร awk)
  • A[C>3?C-3:99]นี่เป็นวิธีที่ปลอดภัยในการอ้างอิงค่าที่สี่ (เช่นจำนวนวัน) ในลำดับที่กลับกัน วิธีนี้มีประโยชน์เพราะวันและเวลาเป็นทางเลือก ถ้าอาเรย์นั้นไม่นานพอมันA[99]จะเกิด0ข้อผิดพลาดซึ่งจะทำให้เกิดค่า ฉันถือว่า99สูงพอสำหรับกรณีใช้งานส่วนใหญ่
  • ส่งคืนวินาทีเป็นจำนวนเต็ม

ตัวอย่างโลกแห่งความจริง

bash oneliner นี้จะฆ่าsoffice.binกระบวนการที่ทำงานภายใต้ผู้ใช้ปัจจุบันหากกระบวนการนั้นมีอายุมากกว่า 180 วินาที

kill -9 $(ps cx -o command,etime,pid | awk '/^soffice.bin/ {if (sec($2)>180) {print $3}} function sec(T){C=split(T,A,"[:-]"); return A[C>3?C-3:99]*86400 + A[C>2?C-2:99]*3600 + A[C>1?C-1:99]*60 + A[C>0?C-0:99]*1}')

1
ดีกว่ามากว่าคำตอบอื่น ๆ นอกจากนี้ยังจัดการหลาย procs
Denny Weinberg

จะเป็นการดีกว่าถ้าวาง 'command' หรือ 'args' ที่ส่วนท้ายของรายการรูปแบบ 'ps' เพื่อให้สามารถ grep บนสตริงคำสั่ง / args ทั้งหมด การวางไว้ที่จุดเริ่มต้นจะทำให้ ps ตัดคำสั่งที่ยาวออกไป
Maksym

1

lstartในสนามpsให้รูปแบบเวลาที่สอดคล้องกันซึ่งเราสามารถเลี้ยงเพื่อdateการแปลงวินาทีตั้งแต่ยุค จากนั้นเราก็เปรียบเทียบมันกับเวลาปัจจุบัน

#!/bin/bash
current_time=$(date +%s)
ps axo lstart=,pid=,cmd= |
    grep page.py |
    while read line
    do
        # 60 * 60 is one hour, multiply additional or different factors for other thresholds 
        if (( $(date -d "${line:0:25}" +%s) < current_time - 60 * 60 ))
        then
            echo $line | cut -d ' ' -f 6    # change echo to kill
        fi
    done

0

ฉันแก้ไขคำตอบที่พวกเขาให้คุณในโพสต์ก่อนหน้า

ps -eo pid,etime,comm | 
egrep '^ *[0-9]+ +([0-9]+-[^ ]*|[0-9]{2}:[0-9]{2}:[0-9]{2}) +/usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py' | 
awk '{print $1}' | 
xargs kill

นิพจน์ทั่วไปค้นหาอาร์กิวเมนต์ที่สอง 2 ประเภท:

  • จำนวนวันในรูปของตัวเลขและเครื่องหมายลบ
  • Hours:minutes:seconds การแสดงออก

minutes:secondsที่ควรจะตรงกับทุกอย่างยกเว้นกระบวนการหนุ่มสาวที่จะมีแบบฟอร์ม


หรือเราจะลองทำตามวิธีที่ PS ทำ ระงับอาร์กิวเมนต์แรกของ / proc / uptime จากอาร์กิวเมนต์ที่ 22 ของ / proc / * / stat
LatinSuD

0

อาจเป็น overkill แต่ฉันอยากรู้อยากเห็นพอที่จะทำให้เสร็จและทดสอบว่ามันใช้งานได้ (ในชื่อกระบวนการที่แตกต่างกันในระบบของฉัน) คุณสามารถฆ่าการจับ$userและ$pidเพื่อให้ regexp ง่ายขึ้นซึ่งฉันเพิ่งเพิ่มสำหรับการดีบั๊กและไม่รู้สึกว่าฉีกออกมา การจับชื่อที่มีชื่อจาก perl 5.10 จะกำจัดเส้นให้มากขึ้นอีกสองเส้น แต่สิ่งนี้น่าจะใช้ได้กับผู้ที่อายุมากกว่า

คุณจะต้องแทนที่การพิมพ์ด้วยการฆ่าแน่นอน แต่ฉันไม่ได้กำลังจะฆ่าอะไรในระบบของฉันเอง

#!/usr/bin/perl -T
use strict; use warnings;

$ENV{"PATH"} = "/usr/bin:/bin";                                                       

my (undef,undef,$hour) = localtime(time);                                             
my $target = $hour - 2; # Flag process before this hour                               
my $grep = 'page.py';                                                   

my @proclist = `ps -ef | grep $grep`;                                                 
foreach my $proc (@proclist)                                                          
{                                                                                     
    $proc =~ /(\w+)\s+(\d+)\s+\d+\s+\d+\s+(.*?).*/;                   
    my $user = $1;                                                                    
    my $pid = $2;                                                                     
    my $stime = $3;                                                                   

    $stime =~ s/(\d+):(\d+)/$1/;                                                      

    # We're going to do a numeric compare against strings that                        
    # potentially compare things like 'Aug01' when the STIME is old                   
    # enough.  We don't care, and we want to catch those old pids, so                 
    # we just turn the warnings off inside this foreach.                              
    no warnings 'numeric';                                                            

    unless ($stime > $target)                                                         
    {                                                                                 
        print "$pid\n";                                                               
    }                                                                                 
}


0

ฉันมีเซิร์ฟเวอร์ที่มีวันที่ไม่ถูกต้องใน / proc และ find ไม่ทำงานดังนั้นฉันจึงเขียนสคริปต์นี้:

#!/bin/bash

MAX_DAYS=7  #set the max days you want here
MAX_TIME=$(( $(date +'%s') - $((60*60*24*$MAX_DAYS)) ))

function search_and_destroy()
{
        PATTERN=$1
        for p in $(ps ux|grep "$PATTERN"|grep -v grep| awk '{ print $2 }')
        do
            test $(( $MAX_TIME - $(date -d "`ps -p $p -o lstart=`" +'%s') )) -ge 0 && kill -9 $p
        done
}

search_and_destroy " command1 "
search_and_destroy " command2 "

0

Python version ใช้ ctime ของรายการกระบวนการใน/proc:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# kills processes older than HOURS_DELTA hours

import os, time

SIGNAL=15
HOURS_DELTA=1

pids = [int(pid) for pid in os.listdir('/proc') if pid.isdigit()]

for pid in pids:
    if os.stat(os.path.join('/proc', str(pid))).st_ctime < time.time() - HOURS_DELTA * 3600:
        try:
            os.kill(pid, SIGNAL)
        except:
            print "Couldn't kill process %d" % pid

0

ฉันใช้สคริปต์ง่าย ๆ นี้ใช้ชื่ออาร์กิวเมนต์สองกระบวนการและอายุในไม่กี่วินาที

#!/bin/bash
# first argument name of the process to check
# second argument maximum age in seconds
# i.e kill lighttpd after 5 minutes
#   script.sh lighttpd 300 
process=$1
maximum_runtime=$2
pid=`pgrep $process`
if [ $? -ne 0 ]
then
        exit 0
fi
process_start_time=`stat /proc/$pid/cmdline --printf '%X'`
current_time=`date +%s`
let diff=$current_time-$process_start_time

if [ $diff -gt $maximum_runtime ]
then
        kill -3 $pid
fi

0

สิ่งนี้น่าจะใช้ได้

killall --older-than 1h $proc_name


1
สิ่งนี้จะเพิ่มหรือปรับปรุง [คำตอบที่มีอยู่แล้ว] ได้อย่างไร
Reaces

2
@ ระยะ: ในความเป็นธรรมทั้งหมดฉันต้องค้นหาคำตอบเดียวที่กล่าวถึง--older-than และมันง่ายที่จะมองข้าม เมื่อเปรียบเทียบกับคำตอบอื่น ๆ แล้วมันก็ง่ายกว่ามากและตอนนี้มีวางจำหน่ายแล้วบน EL7 เช่นกัน
สเวน

@ นำมาใช้ทำให้การเขียนสคริปต์ทำได้ง่ายขึ้นโดยใช้ awk / sed ฯลฯ เพื่อฆ่ากระบวนการฉันคิดว่ามันง่ายและสะอาดกว่ามาก
Jabir Ahmed

0

ฉันไม่พอใจกับวิธีแก้ปัญหาอื่น ๆ ส่วนใหญ่ของพวกเขาลึกลับเกินไป (ความรู้ทุบตีของฉันมี จำกัด ) และดังนั้นฉันไม่สามารถปรับแต่งได้ ...
ฉันได้สร้างโซลูชันของตัวเองมันอาจจะไม่ดีที่สุด แต่ก็ใช้งานได้และ มันสามารถอ่านได้

คุณสามารถบันทึกสคริปต์นี้ในไฟล์และทำให้มันปฏิบัติ (ในที่สุดเรียกมันด้วยการใช้ cron)

#!/bin/bash
## time in second that trigger the kill
LIMIT=10
## [] skip the grep from the process list
PROC_NAME="[m]y process name"
## etimes return the time in seconds
TIME_SEC=$(ps axo etimes,pid,command | grep "$PROC_NAME" | awk {'print$1'})
PID=$(ps axo etimes,pid,command | grep "$PROC_NAME" | awk {'print$2'})

if [ -n "$TIME_SEC" ] 
    then
    if (( $TIME_SEC > $LIMIT )); then
        kill $PID
    fi
fi

-2

72 = 3 วัน 48 = 2 วัน 24 = 1 วัน

a1=$(TZ=72 date +%d) ps -ef| cat filex.txt | sed '/[JFMASOND][aepuco][nbrylgptvc] '$a1'/!d' | awk '{ print $2 " " $5 " " $6 }' > file2.txt

มันได้ผล :)


1
อาจเป็นไปได้ แต่มันยากที่จะอ่านและเรียนรู้จาก พิจารณาการจัดรูปแบบใหม่ขึ้นบรรทัดใหม่และสิ่งต่าง ๆ ... สคริปต์ดีกว่าการตอร์ปิโดหนึ่งครั้งเพื่อการเรียนการสอน
Falcon Momot
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.