「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?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 Sep 09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 15364 0.0 0.1 7004 3792?S Sep 09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 15397 0.0 0.1 6996 3788?S Sep 09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py
Apache 16817 0.0 0.1 7000 3788?S Sep 09 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?S Sep 09 0:00 /usr/bin/python2.6 /u/apps/pysnpp/current/bin/page.py

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

前述の質問で受け入れられた答えは、時間の範囲と一致せず、7日から7日23時間59分59秒まで実行されていたプロセスと単に一致するため、機能しません。1〜2時間実行されているプロセスを強制終了するのではなく 1時間を超えるプロセスを強制終了する必要はありません。

上記の質問に対する他の回答は、find少なくともGentooまたはCentOS 5.4では機能しません。警告を吐き出すか、警告のアドバイスに従った場合は何も返しません。

回答:


21

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 私が行方不明だった検索コマンドでした。


3
-mminがプロセスの経過時間の検出に適しているかどうかはわかりません。
LatinSuD

/ proc /ディレクトリが大幅に変更されるようには見えないので、これはうまくいくようです。そうは言っても、私はそれが不可能だと主張したくありません。
クリストファーカレル

この答えはあまりにも狭く、質問はより広いので、これがあなたの質問に答えるとは思わない。
poige

さらに言うと、それはまったく機能しませんfind /proc -maxdepth 1 -type d -name 1 -mmin +60 -ls。— / sbin / initは、時間ではなく日数のアップタイムカウントにもかかわらずリストに表示されません。/ proc /の変更時間に頼ることはできないようです。
-poige

3
残念ながら、/ procのタイムスタンプはこれに依存できません。少なくとももう。
dpk

8

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でPIDを出力します。4番目の列($ 4、USER)にはテキスト「builder」が含まれ、5番目の列($ 5、TT)にはテキスト「pts」が含まれ、ELAPSED列には600秒より大きい値があります(ありがとう@amtd)

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


私は、これは特にの使用の観点から、より堅牢なソリューションの一つだと思いpsますが、私は、複数の倍思いgrep単一にSをawk、そして安全のための特定の列にパターンマッチを制限する(除外するために例えば、コマンド名のマッチングビルダーなど)
-jmtd

これは、タイムスコープが日単位の場合は問題ありませんが、時間、分、秒単位で経過時間をテストする場合は機能しません。
ヴラスティミルオヴチャチク

「etime」ではなく「etimes」を使用すると、経過時間を秒単位で返すため、解析がはるかに簡単になります。
アホフマン

@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
ティノ

4

これらの以前の回答のいくつかを、ニーズに合わせて変更できると思います。すなわち:

FILEの場合(。-maxdepth 1 -user processuser -type d -mmin +60を見つけます)
  do kill -9 $(basename $ FILE)#findのexecで動作するbasenameを取得することはできません。あなたが方法を知っていれば私に知らせてください!
やった

または

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

2番目の方法がニーズに最も適していると思います。検索バージョンは、そのユーザーによる他のプロセスを


無効にします--Christopher Karel


7
kill -9最後の手段として以外は使用しないでください。-SIGINTまたはを使用し-SIGTERMます。
追って通知があるまで一時停止します。

これは、値ではなく経過時間の形式をテスト基準として使用しています。1時間未満の場合ps^..:..$形式で時刻を出力します。
ヴラスティミルオヴチャチク

4
apt-get install psmisc

killall -o 1h $proc_name

psmiscユーティリティについて詳しく説明してもらえますか?OPはCentOSに言及しました。RPMとして利用できますか?
カスタリア

4

問題

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

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

このカスタムawkの機能は、すべてのフォーマットをサポートetime(例えば、列03-12:30:5900: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を秒に変換します
  • T[[dd-]hh:]mm:ss形式の時間指定(例etime
  • CフィールドのカウントT(awkのNF変数に相当)
  • Aフィールドの配列T(awkの$変数に相当)
  • A[C>3?C-3:99]これは、4番目の値(日数)を逆順で参照する安全な方法です。このアプローチは、日と時間はオプションであるため便利です。配列の長さが足りない場合は、参照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文字列をgrepできるように、「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

正規表現は、2種類の2番目の引数を検索します。

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

それはフォームを持つ若いプロセス以外のすべてと一致するはずminutes:secondsです。


あるいは、PSが行うように行うこともできます。/ proc / * / statの22番目の引数から/ proc / uptimeの最初の引数を引きます。
LatinSuD

0

これはおそらくやり過ぎかもしれませんが、私はそれを終了し、それが機能することをテストするのに十分興味を持ちました(もちろん、私のシステム上の別のプロセス名で)。あなたはのキャプチャを殺すことができる$user$pid私はデバッグのために追加の正規表現を、簡単にするために、バックをリッピングのように感じませんでした。perl 5.10からの名前付きキャプチャは、さらに数行を削除しますが、これは古いperlで動作するはずです。

もちろん、印刷物をキルに置き換える必要がありますが、実際に自分のシステムで何かをキルするつもりはありませんでした。

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

のプロセスエントリの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

この単純なスクリプトを使用します。プロセスの名前と秒単位の経過時間の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

これは動作するはずです

killall --older-than 1h $proc_name


1
これにより、[既存の回答]がどのように追加または改善されますか?
Reaces

2
@Reaces:公平を期して、言及され--older-than ている答えを1つ検索する必要がありましたが、見落としがちです。他の回答と比較すると、これははるかに簡単であり、EL7でも利用できるようになりました。
スヴェン

これは単にプロセスを殺すためにはawk / sedをなどを使用してスクリプトを書くよりも、それが容易になり、私が思う、これははるかに簡単かつきれいです@Reaces
ジャービル・アーメド

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
そうかもしれませんが、読むことや学ぶことはかなり困難です。いくつかの改行やもので再フォーマットすることを検討してください...スクリプトは、一行学習よりも優れています。
ファルコンモモット
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.