web-dev-qa-db-ja.com

「t」より古いプロセスを強制終了するにはどうすればよいですか?

まず、はい、この質問を見ました。

古いプロセスを検索(および強制終了)

そこの答えは正しくなく、機能しません。私は投票し、それに応じてコメントしました。

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? S Sep10 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 2926 0.0 0.0 6996 1404? S Sep02 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 7398 0.0 0.0 6996 1400? S Sep01 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 9423 0.0 0.1 6996 3824? S Sep10 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 11022 0.0 0.0 7004 1400? S Sep01 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 15343 0.0 0.1 7004 3788? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 15364 0.0 0.1 7004 3792? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 15397 0.0 0.1 6996 3788? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 16817 0.0 0.1 7000 3788? S Sep09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 17590 0.0 0.0 7000 1432? S Sep07 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 24448 0.0 0.0 7000 1432? S Sep07 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 30361 0.0 0.1 6996 3776? 9月9日0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py

私は、1時間以上前のpage.pyプロセスを見つけて強制終了する単純な毎日のcronをセットアップすることを考えています。

上記の質問に対する受け入れられた回答は、時間の範囲と一致しないため機能しません。単に7日間から7日間23時間59分59秒で実行されているプロセスと一致します。 1〜2時間実行していたプロセスを強制終了したくありません。むしろ、1時間よりも長いものはすべて強制終了します。

findを使用した前述の質問に対する他の回答は機能しません。少なくともGentooやCentOS 5.4では機能しません。警告が表示されるか、警告のアドバイスに従っても何も返されません。

14
hobodave

クリストファーの答えのおかげで、私はそれを以下に適応させることができました:

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コマンドでした。

9
hobodave

GNU Killallは、プロセス名を使用して、特定の年齢より古いプロセスを強制終了できます。

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

findは常に機能するとは限りません。すべてのシステムでetimeが利用できるわけではありません。また、それは私の正規表現の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を使用して、4番目の列($ 4、USER)にテキスト「ビルダー」が含まれ、5番目の列($ 5、TT)にテキスト「pts」が含まれ、ELAPSED列に600秒より大きい値があるPIDを印刷します(@amtdに感謝)

その後、それをパイプで殺すか、必要に応じて何でもできます。

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

たとえば、psにPIDのリストを入力して、検索することができます。 g .:

ps h -O etimes 1 2 3
5
poige

問題

etimeコマンドのps(経過時間)列を秒に変換します。時間の指定は、この形式_[[dd-]hh:]mm:ss_です。 psの新しいバージョンには、etimes値を秒単位で出力するetime列があります。

解決策:シンプルなカスタムawk関数

このカスタムawk関数は、etime列のすべての形式をサポートします(例:_03-12:30:59_、_00:07_など)。 awkスクリプトに貼り付けるだけで、1行にやさしいソリューションになります。

_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を秒に変換します
  • _[[dd-]hh:]mm:ss_形式のT時間指定(例:etime
  • CTのフィールド数(awkのNF変数に相当)
  • AT内のフィールドの配列(awkの$変数に相当)
  • _A[C>3?C-3:99]_これは、4番目の値(つまり、日数)を逆の順序で参照する安全な方法です。日と時間はオプションであるため、このアプローチは便利です。配列が十分に長くない場合は、_A[99]_を逆参照し、_0_値を生成します。私は、_99_がほとんどのユースケースに十分対応できると想定しています。
  • 秒を整数として返します

実例

このbashワンライナーは、プロセスが180秒より古い場合、現在のユーザーで実行されている_soffice.bin_プロセスを強制終了します。

_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}')
_
apt-get install psmisc

killall -o 1h $proc_name
4
Alex

私はあなたがあなたのニーズに合うようにそれらの以前の答えのいくつかを修正できると思います。つまり:

 for FILE in(find。-maxdepth 1 -user processuser -type d -mmin +60)
 do kill -9 $(basename $ FILE)#ベース名がfindで機能しない幹部。方法がわかれば教えてください!
完了

または

ps -eo pid、etime、comm | awk '$ 2!〜/^..:..$/ && $ 3〜/ page\.py/{print $ 1}' |キル-9

2番目はあなたのニーズに最もよく合うと思います。検索バージョンは、そのユーザーによる他のプロセスの邪魔をします。


-クリストファーカレル

4

lstartpsフィールドは、エポック以降の秒数に変換するために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

これはおそらくやり過ぎですが、私はそれを完成させて機能することをテストするのに十分興味を持っていました(もちろん、システムの別のプロセス名で)。 $user$pidのキャプチャを強制終了して、私がデバッグ用に追加しただけの正規表現を簡略化できます。 Perl 5.10からの名前付きキャプチャは数行を削りますが、これは古いperlで動作するはずです。

もちろん、プリントをkillに置き換える必要がありますが、私は実際に自分のシステムで何かを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
Zed

これはうまくいくはずです

killall --older-than 1h $proc_name

0
Jabir Ahmed

私は他の解決策に満足していませんでした、それらのほとんどはあまりにも不可解です(私の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
0
Francesco

私はこの単純なスクリプトを使用して、プロセスの2つの引数名と経過時間を秒単位で取得します。

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

/ 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
Vincent

/procのプロセスエントリのctimeを使用するPythonバージョン:

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

以前の投稿で彼らがあなたに与えた答えを変更しました

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つのタイプの2番目の引数を検索します。

  • 数字とマイナス記号の形式の日。
  • Hours:minutes:seconds式。

これは、minutes:secondsという形式の若いプロセスを除くすべてに一致します。

0
LatinSuD