"t"보다 오래된 프로세스를 어떻게 종료합니까?


14

먼저, 나는이 질문을 보았습니다.

오래된 프로세스를 찾아서 죽입니다.

답변이 잘못되어 작동하지 않습니다. 이에 따라 투표하고 의견을 제시했습니다.

내가 죽이고 싶은 프로세스는 다음과 같이 나열되면 다음과 ps aux | grep page.py같습니다.

아파치 424 0.0 0.1 6996 4564? S 07:02 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
아파치 2686 0.0 0.1 7000 3460? 9 월 10 일 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
아파치 2926 0.0 0.0 6996 1404? S Sep02 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
아파치 7398 0.0 0.0 6996 1400? S Sep01 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
아파치 9423 0.0 0.1 6996 3824? 9 월 10 일 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
아파치 11022 0.0 0.0 7004 1400? S Sep01 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
아파치 15343 0.0 0.1 7004 3788? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
아파치 15364 0.0 0.1 7004 3792? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
아파치 15397 0.0 0.1 6996 3788? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
아파치 16817 0.0 0.1 7000 3788? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
아파치 17590 0.0 0.0 7000 1432? S Sep07 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
아파치 24448 0.0 0.0 7000 1432? S Sep07 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
아파치 30361 0.0 0.1 6996 3776? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py

page.py한 시간보다 오래된 프로세스를 찾아 죽일 간단한 일일 cron을 설정하려고합니다 .

위에서 언급 한 질문에 대한 대답은 작동하지 않습니다. 범위와 일치하지 않기 때문에 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.
Onnonymous

9

Christopher의 답변 덕분에 나는 그것을 다음에 적응시킬 수있었습니다.

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

-mmin 내가 빠진 찾기 명령이었습니다.


3
-mmin이 프로세스 수명을 감지하는 데 적합한 지 확실하지 않습니다.
LatinSuD

/ proc / 디렉토리가 많이 수정 된 것처럼 보이지 않으므로 작동하는 것 같습니다. 그것은 불가능하다고 주장하고 싶지 않습니다.
크리스토퍼 카렐

이 답변이 너무 좁고 질문이 더 넓기 때문에 이것이 귀하의 질문에 대한 답변이라고 생각하지 않습니다.
poige

그리고 더 많은 것을 말하고 싶습니다. 전혀 작동하지 않습니다. find /proc -maxdepth 1 -type d -name 1 -mmin +60 -ls— / sbin / init는 몇 시간이 아닌 며칠 동안 가동 시간에도 불구하고 나열되지 않습니다. / proc /의 dirs 수정 시간에 의존 할 수없는 것 같습니다.
poige

3
불행히도 / proc의 타임 스탬프는 이것에 의존 할 수 없습니다. 적어도 더 이상은 아닙니다.
dpk

8

찾기가 항상 작동하지는 않습니다. 모든 시스템에 etimes가 제공되는 것은 아니며 정규식 newb 상태 일 수는 있지만 이것보다 더 필요한 것은 없다고 생각합니다.

ps -eo pid,etimes,comm,user,tty | awk '{if ($4 ~ /builder/ && $5 ~ /pts/ && $2>600) print $1}'
  • 모든 프로세스를 나열하고 열 PID, ELAPSED (etimes = seconds), COMMAND, USER, TT (@ahoffman 덕분에)를 제공하십시오.
  • awk print를 사용하면 4 번째 열 ($ 4, USER)에 텍스트 'builder'가 포함되고 5 번째 열 ($ 5, TT)에 텍스트 'pts'가 포함되고 ELAPSED 열의 값이 600 초보다 큰 값 (@amtd)

그런 다음 파이프를 사용하여 필요에 따라 죽일 수도 있습니다.


나는 이것이 당신의 사용 측면에서보다 강력한 솔루션 중 하나라고 생각 ps하지만, 여러 개 grep를 single로 접고 awk안전을 위해 패턴 일치를 특정 열로 제한합니다 (예 : 명령 이름 일치 제외) 빌더 등)
jmtd

시간 범위가 며칠이면 괜찮지 만 시간, 분 또는 초 단위로 경과 시간을 테스트하려는 경우 작동하지 않습니다.
Vlastimil Ovčáčík

"etime"대신 "etimes"를 사용하면 구문 분석이 훨씬 쉬운 경과 시간을 초 단위로 반환합니다.
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

귀하의 필요에 맞게 이전 답변 중 일부를 수정할 수 있다고 생각합니다. 즉:

파일의 위치 (. -maxdepth 1 -user processuser -type d -mmin +60 찾기)
  kill -9 $ (basename $ FILE) # find의 exec로 작업 할 basename을 절대 얻을 수 없습니다. 당신이 방법을 알고 있으면 알려주세요!
끝난

또는

ps -eo pid, etime, comm | awk '$ 2! ~ /^..:..$/ && $ 3 ~ / page \ .py / {print $ 1}'| 죽이기 -9

두 번째는 귀하의 요구에 가장 잘 맞는 것 같습니다. 찾기 버전은 해당 사용자에 의해 다른 프로세스를


막을 수 있습니다 -Christopher Karel


7
kill -9최후의 수단으로 사용하지 마십시오 . -SIGINT또는을 사용하십시오 -SIGTERM.
추후 공지가있을 때까지 일시 중지되었습니다.

이것은 경과 시간 형식을 값이 아닌 테스트 기준으로 사용합니다. ps시간 ^..:..$이 1 시간 미만이면 형식으로 시간을 출력합니다 .
Vlastimil Ovčáčík

4
apt-get install psmisc

killall -o 1h $proc_name

psmisc유틸리티에 대해 더 자세히 설명해 주 시겠습니까? OP는 CentOS를 언급했습니다. 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(awk의 NF 변수와 동일)
  • 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
다른 답변보다 훨씬 좋습니다. 또한 멀티 프로세서도 처리합니다.
데니 와인버그

전체 명령 / args 문자열을 잡을 수 있도록 'ps'형식 목록의 끝에 'command'또는 '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

정규식은 두 가지 유형의 두 번째 인수를 검색합니다.

  • 숫자와 빼기 기호 형태의 요일.
  • Hours:minutes:seconds 표현.

그것은 형식을 가진 젊은 프로세스를 제외한 모든 것과 일치해야합니다 minutes:seconds.


또는 PS가하는 방식대로 시도해 볼 수도 있습니다. / proc / * / stat의 22 번째 인수에서 / proc / uptime의 첫 번째 인수를 뺍니다.
LatinSuD

0

이것은 아마도 과잉 일 것입니다. 그러나 그것을 끝내고 그것이 작동하는지 테스트 할만 큼 호기심이 생겼습니다 (물론 내 시스템의 다른 프로세스 이름에서). 당신의 캡처를 죽일 수 $user$pid난 단지 디버깅을 위해 추가 된 정규 표현식을 단순화하고, 다시 리핑 같은 느낌하지 않았다. perl 5.10에서 이름을 붙인 캡처는 몇 줄을 더 줄 였지만 이전 perls에서는 작동합니다.

물론 프린트를 킬 (kill)로 교체해야하지만 실제로 내 시스템에서 아무것도 죽이려고하지 않았습니다.

#!/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에 날짜가 잘못된 서버가 있고 찾기가 작동하지 않으므로이 스크립트를 작성했습니다.

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

프로세스 항목의 ctime을 사용하는 Python 버전 /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
@Reaces : 모든 공정성에서 언급 한 답변 하나를 검색해야했으며 --older-than 간과하기 쉽습니다. 다른 답변과 비교할 때 훨씬 쉬우 며 EL7에서도 사용할 수 있습니다.
Sven

이 그냥 쉽게 사용하여 스크립트를 작성하는 것보다 만드는 @Reaces AWK / SED 등의 프로세스를 죽이고, 내가 가정이 훨씬 간단하고 청소기
의 Jabir 아메드

0

나는 다른 해결책에 만족하지 않았고, 대부분 그것들은 너무 비밀 스럽습니다 (내 bash 지식은 제한적입니다). 그리고 그것들을 사용자 정의 할 수는 없습니다 ...
나는 내 자신의 해결책을 만들었습니다. 아마도 최고는 아니지만 작동합니다. 읽을 수있다

이 스크립트를 파일에 저장하고 실행 가능하게 만들 수 있습니다 (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.