특정 기간보다 오래된 모든 Linux 프로세스를 어떻게 종료합니까?

StackOverflow https://stackoverflow.com/questions/6134

  •  08-06-2019
  •  | 
  •  

문제

특정 서버에서 가끔씩 종료되어야 하는 좀비 같은 프로세스에 문제가 있습니다.한 시간 이상 실행된 항목을 가장 잘 식별할 수 있는 방법은 무엇입니까?

도움이 되었습니까?

해결책

그냥 죽여야만 한다면:

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

어떤게 어울리는지 보고 싶으시다면

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

그만큼 -i 플래그는 각 프로세스 일치에 대해 예/아니요를 묻는 메시지를 표시합니다.

다른 팁

나에게 맞는 답변을 찾았습니다.

경고:이것은 찾을 것이다 그리고 죽여라 장기 실행 프로세스

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

(어디 사용자 ID 장기 실행 프로세스가 있는 특정 사용자의 ID입니다.)

두 번째 정규식은 선택적 일 숫자와 그 뒤에 시간, 분, 두 번째 구성 요소가 있는 시간과 일치하므로 길이는 최소 1시간입니다.

하루 이상 지난 항목의 경우

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]

Linux 또는 /proc 파일 시스템이 있는 다른 시스템을 사용하는 경우 이 예에서는 프로세스 1이 6월 22일 이후 실행 중이라는 것만 볼 수 있지만 시작된 시간은 표시되지 않습니다.

stat /proc/<pid>

좀 더 정확한 답변을 드리겠습니다.예를 들어 프로세스 1의 정확한 타임스탬프는 다음과 같습니다. ps에서는 Jun22로만 표시됩니다.

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

이 방법으로 가장 오래된 10개의 프로세스 목록을 얻을 수 있습니다.

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

Jodie C와 다른 사람들은 다음과 같이 지적했습니다. killall -i 사용할 수 있습니다. 프로세스 이름을 사용하여 종료하려는 경우에는 괜찮습니다.하지만 다음과 같은 매개변수로 죽이고 싶다면 pgrep -f, 순수한 bash와 다음을 사용하여 다음과 같은 것을 사용해야 합니다. /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 "offlineimap"을 참조하면 종료될 수 있습니다. killall 여기에 제시된 솔루션은 "python2" 문자열에서만 작동합니다.

Perl의 Proc::ProcessTable은 다음과 같은 작업을 수행합니다.http://search.cpan.org/dist/Proc-ProcessTable/

데비안이나 우분투에 설치할 수 있습니다 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";
    }
}

그런 다음 실행 perl process.pl

이를 통해 시작 시간에 더 많은 다양성과 1초 해상도를 제공합니다.

당신이 사용할 수있는 bc mob의 답변에 두 명령을 결합하고 프로세스가 시작된 후 경과된 시간(초)을 얻으려면 다음을 수행하십시오.

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

이것을 경로에 놓고 다음과 같이 호출하면:그 이후로

프로세스 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>

여기서 패턴은 문자열 또는 확장 정규식인 경우 이 패턴과 일치하는 모든 프로세스와 시작된 이후의 시간(초)을 인쇄합니다.:)

~을 하다 ps -aef.그러면 프로세스가 시작된 시간이 표시됩니다.그런 다음 date 현재 시간을 찾는 명령입니다.프로세스의 나이를 찾기 위해 둘 사이의 차이를 계산합니다.

나는 허용된 답변과 비슷한 작업을 수행했지만 프로세스 이름을 기준으로 일치시키고 100초 이상 실행되는 잘못된 프로세스를 기반으로 일치시키고 싶기 때문에 약간 다릅니다.

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

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

에포크 이후 프로세스의 시작 시간을 초 단위로 가져옵니다.현재 시간과 비교(date +%s) 프로세스의 현재 수명을 가져옵니다.

ps를 사용하는 것이 올바른 방법입니다.이전에 비슷한 작업을 이미 수행했지만 소스가 없습니다.일반적으로 ps에는 표시할 필드와 정렬 기준을 알려주는 옵션이 있습니다.실행 시간별로 출력을 정렬하고 원하는 프로세스를 grep한 다음 종료할 수 있습니다.

HTH

C에서 이것이 필요한 경우 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;
}

어디선가 우연히 발견했는데..간단하고 유용하다고 생각했어요

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);'

그리고 그것을 crontab이라고 부르세요.

* * * * * longprockill.sh

내 버전 sincetime 위의 @Rafael S.칼사베리니:

#!/bin/bash
ps --no-headers -o etimes,args "$1"

그러면 출력 필드가 반전됩니다.경과 시간이 먼저, 인수를 포함한 전체 명령이 두 번째입니다.전체 명령에 공백이 포함될 수 있으므로 이는 선호됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top