Làm cách nào để giết các tiến trình cũ hơn so với trên mạng


14

Đầu tiên, vâng tôi đã thấy câu hỏi này:

Tìm (và giết) các quy trình cũ

Các câu trả lời không chính xác và không hoạt động. Tôi đã bỏ phiếu và bình luận phù hợp.

Các quy trình tôi muốn giết trông như thế này khi được liệt kê với 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/civerse/bin/page.py
apache 2686 0,0 0,1 7000 3460? S Sep10 0:00 /usr/bin/python2.6 /u/apps/pysnpp/civerse/bin/page.py
apache 2926 0,0 0,0 6996 1404? S Sep02 0:00 /usr/bin/python2.6 /u/apps/pysnpp/civerse/bin/page.py
apache 7398 0,0 0,0 6996 1400? S Sep01 0:00 /usr/bin/python2.6 /u/apps/pysnpp/civerse/bin/page.py
apache 9423 0,0 0,1 6996 3824? S Sep10 0:00 /usr/bin/python2.6 /u/apps/pysnpp/civerse/bin/page.py
apache 11022 0,0 0,0 7004 1400? S Sep01 0:00 /usr/bin/python2.6 /u/apps/pysnpp/civerse/bin/page.py
apache 15343 0,0 0,1 7004 3788? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/civerse/bin/page.py
apache 15364 0,0 0,1 7004 3792? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/civerse/bin/page.py
apache 15394 0,0 0,1 6996 3788? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/civerse/bin/page.py
apache 16817 0,0 0,1 7000 3788? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/civerse/bin/page.py
apache 17590 0,0 0,0 7000 1432? S Sep07 0:00 /usr/bin/python2.6 /u/apps/pysnpp/civerse/bin/page.py
apache 24448 0,0 0,0 7000 1432? S Sep07 0:00 /usr/bin/python2.6 /u/apps/pysnpp/civerse/bin/page.py
apache 30361 0,0 0,1 6996 3776? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/civerse/bin/page.py

Tôi đang tìm cách thiết lập một cron hàng ngày đơn giản sẽ tìm và giết mọi page.pytiến trình cũ hơn một giờ.

Câu trả lời được chấp nhận cho câu hỏi đã nói ở trên không hoạt động, vì nó không khớp với nhiều lần, nó chỉ đơn giản khớp với các quá trình đã chạy từ 7 ngày đến 7 ngày 23 giờ 59 phút và 59 giây. Tôi không muốn giết các tiến trình đã chạy từ 1-2 giờ, mà là bất cứ điều gì lớn hơn 1 giờ.

Câu trả lời khác cho câu hỏi đã nói ở trên sử dụng findkhông hoạt động, ít nhất là không phải trên Gentoo hoặc CentOS 5.4, nó sẽ đưa ra cảnh báo hoặc không trả lời gì nếu lời khuyên cảnh báo được nói theo.

Câu trả lời:


21

GNU Killall có thể tiêu diệt các tiến trình cũ hơn một độ tuổi nhất định, sử dụng tên tiến trình của chúng.

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

1
Tùy chọn đó không khả dụng trên CentOS 6.6. Phiên bản: killall (PSmisc) 22.6.
Onnonymous

9

Nhờ câu trả lời của Christopher, tôi đã có thể điều chỉnh nó như sau:

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

-mmin là lệnh find tôi bị thiếu.


3
Không chắc chắn nếu -mmin phù hợp để phát hiện tuổi của một quy trình.
LatinSuD

Nó không xuất hiện / Proc / thư mục được sửa đổi rất nhiều, vì vậy điều này dường như hoạt động. Điều đó đã được nói, tôi sẽ không muốn tuyên bố điều đó là không thể.
Christopher Karel

Tôi không nghĩ câu trả lời này cho câu hỏi của bạn vì câu trả lời này quá hẹp và câu hỏi rộng hơn.
poige

Và tôi còn nói nhiều hơn nữa - nó hoàn toàn không hoạt động: find /proc -maxdepth 1 -type d -name 1 -mmin +60 -ls- / sbin / init không được liệt kê mặc dù thời gian hoạt động trong nhiều ngày chứ không phải hàng giờ. Có vẻ như bạn không thể dựa vào thời gian sửa đổi thư mục của / Proc /.
poige

3
Thật không may, dấu thời gian trong / Proc không thể phụ thuộc vào điều này. Ít nhất là không còn nữa.
dpk

8

find không phải lúc nào cũng hoạt động, không phải mọi hệ thống đều có sẵn etimes và nó có thể là trạng thái regex newb của tôi, nhưng tôi không nghĩ bạn cần gì hơn thế này:

ps -eo pid,etimes,comm,user,tty | awk '{if ($4 ~ /builder/ && $5 ~ /pts/ && $2>600) print $1}'
  • liệt kê tất cả các quy trình và cung cấp các cột PID, ELAPSED (etimes = giây), LỰA CHỌN, NGƯỜI DÙNG, TT (cảm ơn @ahoffman)
  • với awk in PID trong đó cột thứ 4 ($ 4, USER) chứa văn bản 'trình xây dựng' và cột thứ 5 ($ 5, TT) chứa văn bản 'pts' và cột ELAPSED có giá trị lớn hơn 600 giây (cảm ơn @amtd)

sau đó bạn có thể tiêu diệt nó hoặc bất cứ điều gì bạn cần.


Tôi nghĩ rằng đây là một trong những giải pháp mạnh mẽ hơn, đặc biệt là về việc bạn sử dụng ps, nhưng tôi sẽ gấp nhiều greps thành một awkvà để an toàn hạn chế mẫu khớp với các cột cụ thể (để loại trừ ví dụ khớp tên lệnh người xây dựng, v.v.)
jmtd

Điều này tốt khi phạm vi thời gian của bạn tính bằng ngày, nhưng sẽ không hoạt động nếu bạn muốn kiểm tra thời gian đã trôi qua tính bằng giờ, phút hoặc giây.
Vlastimil Ovčáčík

sử dụng "etimes" thay vì "etime", điều này sẽ trả về thời gian đã trôi qua tính bằng giây, dễ phân tích hơn nhiều.
ahofmann

@jmtd & ahofmann: Tôi đã cập nhật theo nhận xét của bạn. Tôi hy vọng điều này đúng như bạn dự định
eugenevd

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

Nếu bạn muốn, bạn có thể cung cấp psdanh sách các PID để tra cứu bên trong, ví dụ:

ps h -O etimes 1 2 3

2
etimeschỉ hoạt động cho mới hơnps
Tino

4

Tôi nghĩ bạn có thể sửa đổi một số câu trả lời trước đó để phù hợp với nhu cầu của bạn. Cụ thể là:

cho FILE trong (tìm. -maxdepth 1 -user processuser -type d -mmin +60)
  do kill -9 $ (tên cơ sở $ FILE) # Tôi không bao giờ có thể lấy tên cơ sở để làm việc với hàm exec của find. Hãy cho tôi biết nếu bạn biết làm thế nào!
làm xong

Hoặc là

ps -eo pid, etime, comm | awk '$ 2! ~ / ^ ..: .. $ / && $ 3 ~ / page \ .py / {in $ 1}' | giết -9

Tôi nghĩ rằng thứ hai có thể phù hợp nhất với nhu cầu của bạn. Phiên bản tìm kiếm sẽ kết thúc các quá trình khác bởi người dùng đó


--Christopher Karel


7
Đừng sử dụng kill -9ngoại trừ như là phương sách cuối cùng. Sử dụng -SIGINThoặc -SIGTERM.
Tạm dừng cho đến khi có thông báo mới.

Đây là sử dụng định dạng của thời gian trôi qua làm tiêu chí kiểm tra, không phải giá trị của nó. pssẽ xuất thời gian ở ^..:..$định dạng khi ít hơn một giờ.
Vlastimil Ovčáčík

4
apt-get install psmisc

killall -o 1h $proc_name

Bạn có thể giúp giải thích thêm về các psmisctiện ích? OP đã đề cập đến CentOS; nó có sẵn dưới dạng RPM không?
Castaglia

4

Vấn đề

Chuyển đổi etimecột (thời gian trôi qua) của pslệnh thành giây. Đặc điểm kỹ thuật thời gian là ở định dạng này [[dd-]hh:]mm:ss. Các phiên bản mới hơn của psmột etimescột có etimegiá trị đầu ra tính bằng giây.

Giải pháp: chức năng awk tùy chỉnh đơn giản

Chức năng tùy chỉnh awk này hỗ trợ tất cả các định dạng của etimecột (ví dụ 03-12:30:59, 00:07vv). Chỉ cần dán nó vào tập lệnh awk của bạn, đó là giải pháp thân thiện một lớp.

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) chuyển đổi T thành giây
  • Tđặc tả thời gian ở [[dd-]hh:]mm:ssđịnh dạng (ví dụ etime)
  • Csố lượng các trường trong T(tương đương với biến NF của awk)
  • Amảng các trường trong T(tương đương với biến $ của awk)
  • A[C>3?C-3:99]đây là cách an toàn để tham chiếu giá trị thứ tư (tức là số ngày) theo thứ tự ngược lại. Cách tiếp cận này hữu ích vì ngày và giờ là tùy chọn. Nếu mảng không đủ dài, nó A[99]sẽ mang lại 0giá trị. Tôi giả sử 99là đủ cao cho hầu hết các trường hợp sử dụng.
  • trả về giây dưới dạng số nguyên

Ví dụ thế giới thực

Bash oneliner này sẽ giết soffice.bintiến trình đang chạy dưới người dùng hiện tại nếu quá trình này cũ hơn 180 giây.

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
RẤT NHIỀU câu trả lời khác. nó cũng xử lý nhiều procs.
Denny Weinberg

Sẽ tốt hơn nếu đặt 'lệnh' hoặc 'args' ở cuối danh sách định dạng 'ps' để có thể grep trên chuỗi lệnh / args đầy đủ. Đặt nó ở đầu sẽ dẫn đến ps cắt ngắn các lệnh dài hơn.
Maksym

1

Các lstartlĩnh vực trong psđưa ra một định dạng thời gian phù hợp mà chúng tôi có thể ăn để datechuyển đổi sang giây kể từ khi kỷ nguyên. Sau đó, chúng tôi chỉ so sánh với thời điểm hiện tại.

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

Tôi đã sửa đổi câu trả lời họ đã cho bạn trong bài viết trước

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

Biểu thức chính quy tìm kiếm 2 loại đối số thứ hai:

  • Ngày ở dạng chữ số và dấu trừ.
  • Hours:minutes:seconds biểu hiện.

Điều đó sẽ phù hợp với tất cả mọi thứ trừ các quy trình trẻ, những người sẽ có hình thức minutes:seconds.


Ngoài ra, chúng tôi có thể thử làm theo cách PS làm điều đó. Trừ đối số đầu tiên của / Proc / thời gian hoạt động từ đối số thứ 22 của / Proc / * / stat.
LatinSuD

0

Điều này có thể là quá mức cần thiết, nhưng tôi đã đủ tò mò để hoàn thành nó và kiểm tra xem nó có hoạt động không (tất nhiên là trên một tên quy trình khác trên hệ thống của tôi). Bạn có thể giết chết việc bắt giữ $user$pidđể đơn giản hóa biểu thức chính quy mà tôi chỉ thêm vào để gỡ lỗi và không cảm thấy như bị xé toạc. Các ảnh chụp được đặt tên từ perl 5.10 sẽ loại bỏ một vài dòng nữa, nhưng điều này sẽ hoạt động trên các perls cũ hơn.

Dĩ nhiên, bạn sẽ cần phải thay thế bản in bằng một kill, nhưng tôi không thực sự giết bất cứ thứ gì trên hệ thống của mình.

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

Tôi có một máy chủ có ngày sai trong / Proc và thấy không hoạt động nên tôi đã viết kịch bản này:

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

Phiên bản Python sử dụng thời gian của các mục quá trình trong /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

Tôi sử dụng tập lệnh đơn giản này, nó cần hai tên đối số của quá trình và tuổi trong vài giây.

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

cái này nên hoạt động

killall --older-than 1h $proc_name


1
Làm thế nào để điều này thêm hoặc cải thiện [các câu trả lời đã có]?
Hồi phục

2
@Reaces: Trong tất cả các công bằng, tôi đã phải tìm kiếm một câu trả lời được đề cập --older-than và thật dễ dàng để bỏ qua nó. So với các câu trả lời khác, việc này dễ hơn nhiều và hiện đã có trên EL7.
Sven

@Reaces điều này chỉ làm cho nó dễ dàng hơn so với việc viết các tập lệnh bằng cách sử dụng awk / sed, v.v. để giết một tiến trình, điều này tôi cho là đơn giản và gọn gàng hơn nhiều
Jabir Ahmed

0

Tôi không hài lòng với giải pháp khác, hầu hết chúng đều quá khó hiểu (kiến thức bash của tôi bị hạn chế) và vì vậy tôi không thể tùy chỉnh chúng ...
Tôi đã tạo ra giải pháp của riêng mình, Nó có thể không phải là tốt nhất nhưng nó hoạt động và nó có thể đọc được

Bạn có thể lưu tập lệnh này trong một tệp và làm cho nó có thể thực thi được (cuối cùng gọi nó bằng cách sử dụng 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 ngày 48 = 2 ngày 24 = 1 ngày

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

nó hoạt động :)


1
Điều đó cũng có thể, nhưng thật khó để đọc và học hỏi. Xem xét định dạng lại với một số dòng mới và công cụ ... tập lệnh tốt hơn so với một lớp để được hướng dẫn.
Falcon Momot
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.