14

私は基本的に2つのことを達成する必要があります、

  1. Windows サーバーで実行されているすべての「firefox.exe」プロセスを見つける
  2. 30分以上走っているものを殺す

私は小片を持っていますが、すべてを統合してWindowsサービスとして機能させる方法がわかりません。

私がこれまでに持っているもの -

1) 実行中のすべての firefox プロセスを見つける方法

wmic process get name,creationdate, processid | findstr firefox

2) PID に基づいてプロセスを強制終了する方法

taskkill /PID 827

他に何が残っていますか?

  • 30 分以上実行されているcreationdateに基づいて計算しますPID
  • コマンドを使用してtaskkill、上記の基準に適合するすべての PID を順次強制終了します
  • これはサービスであると設定します(これはおそらく理解できます)
4

2 に答える 2

22

「.batではできない」と考えがちです。それが私の最初の反応だったことを知っています。問題は、直接サポートされておらず、自明ではない日付操作が必要なことです。しかし、Ritchie Lawrenceが助けに来て、必要な日付関数を作成するという大変な作業をすべて完了しました。

WMIProcessクラスはCreationDateUTC 形式で提供されます。Win32_OperatingSystem LocalDateTime現在の時刻を UTC 形式で返します。CutOffTime を取得するには、LocalDataTime から最大有効期間 (この場合は 30 分) を差し引く必要があります。次に、それを使用して をフィルタリングProcessし、最後にcall terminate(の代わりにtaskkill) を使用できます。ではなくfindstr、WMIwhereフィルターを使用します (はるかに高速です)。

次のコードは機能しているようです。これはKILLING TASKSであるため、自分でテストする必要があります。

注:if "%%p" GEQ "0"は、空ではないが改行文字を含む wmic の結果の末尾にある「空白」行を除外するために使用されます。数値を期待しているので、これは単純で効果的なテストのように見えました (ただし、これを処理するためのより良い方法があるかもしれません)。

@echo off
setlocal ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS

set MaxRunningMinutes=30
set ProcessName=firefox.exe

for /f "usebackq skip=1" %%t in (
  `wmic.exe path Win32_OperatingSystem get LocalDateTime`) do (
    if "%%t" GEQ "0" set T=%%t)

rem echo !T!
rem echo !T:~,4!/!T:~4,2!/!T:~6,2! !T:~8,2!:!T:~10,2!:!T:~12,2!
rem echo !T:~15,-4! !T:~-4!

set fsec=!T:~15,-4!
set tzone=!T:~-4!

call :DateToSecs !T:~,4! !T:~4,2! !T:~6,2! !T:~8,2! !T:~10,2! !T:~12,2! UNIX_TIME
rem echo !UNIX_TIME!

set /a CutOffTime=UNIX_TIME-MaxRunningMinutes*60
rem echo !CutOffTime!

call :SecsToDate !CutOffTime! yy mm dd hh nn ss
rem echo !yy!/!mm!/!dd! !hh!:!nn!:!ss!
set UTC=!yy!!mm!!dd!!hh!!nn!!ss!.!fsec!!tzone!
rem echo !UTC!

wmic process where "name='%ProcessName%' AND CreationDate<'%UTC%'" call terminate

rem * Alternate kill method. May be useful if /F flag is needed to
rem * to forcefully terminate the process. (Add the /F flag to
rem * taskill cmd if needed.)

rem for /f "usebackq skip=1" %%p in (
rem   `wmic process where "name='%ProcessName%' AND CreationDate<'%UTC%'" get processid`) do (
rem   if "%%p" GEQ "0" taskkill /PID %%p)

goto :EOF

rem From: http://www.commandline.co.uk/lib/treeview/index.php
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DateToSecs %yy% %mm% %dd% %hh% %nn% %ss% secs
::
:: By:   Ritchie Lawrence, updated 2002-08-13. Version 1.1
::
:: Func: Returns number of seconds elapsed since 1st January 1970 00:00:00
::       for a given calendar date and time of day. For NT4/2000/XP/2003.
::
:: Args: %1 year to convert, 2 or 4 digit (by val)
::       %2 month to convert, 1/01 to 12, leading zero ok (by val)
::       %3 day of month to convert, 1/01 to 31, leading zero ok (by val)
::       %4 hours to convert, 1/01 to 12 for 12hr times (minutes must be
::          suffixed by 'a' or 'p', 0/00 to 23 for 24hr clock (by val)
::       %5 mins to convert, 00-59 only, suffixed by a/p if 12hr (by val)
::       %6 secs to convert, 0-59 or 00-59 (by val)
::       %7 var to receive number of elapsed seconds (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

setlocal ENABLEEXTENSIONS
set yy=%1&set mm=%2&set dd=%3&set hh=%4&set nn=%5&set ss=%6
if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
set /a dd=100%dd%%%100,mm=100%mm%%%100
set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2
set /a j=j/5+dd+y*365+y/4-y/100+y/400-2472633
if 1%hh% LSS 20 set hh=0%hh%
if {%nn:~2,1%} EQU {p} if "%hh%" NEQ "12" set hh=1%hh%&set/a hh-=88
if {%nn:~2,1%} EQU {a} if "%hh%" EQU "12" set hh=00
if {%nn:~2,1%} GEQ {a} set nn=%nn:~0,2%
set /a hh=100%hh%%%100,nn=100%nn%%%100,ss=100%ss%%%100
set /a j=j*86400+hh*3600+nn*60+ss
endlocal&set %7=%j%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:SecsToDate %secs% yy mm dd hh nn ss
::
:: By:   Ritchie Lawrence, updated 2002-07-24. Version 1.1
::
:: Func: Returns a calendar date and time of day from the number of
::       elapsed seconds since 1st January 1970 00:00:00. For
::       NT4/2000/XP/2003.
::
:: Args: %1 seconds used to create calendar date and time of day (by val)
::       %2 var to receive year, 4 digits for all typical dates (by ref)
::       %3 var to receive month, 2 digits, 01 to 12 (by ref)
::       %4 var to receive day of month, 2 digits, 01 to 31 (by ref)
::       %5 var to receive hours, 2 digits, 00 to 23 (by ref)
::       %6 var to receive minutes, 2 digits, 00 to 59 (by ref)
::       %7 var to receive seconds, 2 digits, 00 to 59 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set /a i=%1,ss=i%%60,i/=60,nn=i%%60,i/=60,hh=i%%24,dd=i/24,i/=24
set /a a=i+2472632,b=4*a+3,b/=146097,c=-b*146097,c/=4,c+=a
set /a d=4*c+3,d/=1461,e=-1461*d,e/=4,e+=c,m=5*e+2,m/=153,dd=153*m+2,dd/=5
set /a dd=-dd+e+1,mm=-m/10,mm*=12,mm+=m+3,yy=b*100+d-4800+m/10
(if %mm% LSS 10 set mm=0%mm%)&(if %dd% LSS 10 set dd=0%dd%)
(if %hh% LSS 10 set hh=0%hh%)&(if %nn% LSS 10 set nn=0%nn%)
if %ss% LSS 10 set ss=0%ss%
endlocal&set %7=%ss%&set %6=%nn%&set %5=%hh%&^
set %4=%dd%&set %3=%mm%&set %2=%yy%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Powershell の使用

元の質問は「バッチファイル」でタグ付けされていたので、最初に Windows バットの回答を提供しました。ただし、30 分以上実行されている名前付きプロセスを強制終了することは、Powershell では簡単なことです。

Get-Process firefox | 
    Where StartTime -lt (Get-Date).AddMinutes(-30) | 
    Stop-Process -Force

繰り返しますが、これはKILLING TASKSなので注意してください。Powershell に慣れていない場合は、1 つのライナーの内訳を次に示します。

  1. コマンドレットを使用しGet-Processて、ローカル コンピューターで実行されているプロセスを取得します。ここでは、プロセスの名前firefoxが渡されます。必要に応じて、名前のリストを渡すことができ、ワイルドカードを使用できます。
  2. によって返されるプロセス オブジェクトは、StartTime プロパティでフィルター処理するためにGet-Processパイプされます。WhereこのGet-Dateコマンドレットは、現在の日付と時刻をDateTime型として取得するために使用されます。AddMinutes メソッドが呼び出されて -30 分が追加され、DateTime30 分前を表す が返されます。演算子 (技術的には、この-ltコンテキストではスイッチ パラメーター) は、Less-than 演算を指定します。
  3. によって返されたフィルター処理されたプロセス オブジェクトは、コマンドレットWhereにパイプされます。パラメータは、確認プロンプトを回避するために使用されますStop-Process-Force

上記では、Powershell 3 で導入された簡略化されたWhere構文を使用しました。Powershell 2 との互換性 (Windows XP で実行される最新バージョン) が必要な場合は、次の構文が必要です。

Get-Process firefox | 
    Where { $_.StartTime -lt (Get-Date).AddMinutes(-30) } | 
    Stop-Process -Force

ここでは、中かっこで ScriptBlock を囲んでいます。$_現在のオブジェクトを明示的に参照するために使用されます。

于 2013-01-17T23:27:09.380 に答える
2

ある種のテストの自動化を行っていると思いますが、ハングしているFirefoxがたくさんあるので、30分以上実行しているすべての人を殺すには、次のようにします。

foreach ($process in Get-Process firefox*){If((New-TimeSpan -Start $process.StartTime).TotalHours -gt 0.5) {Stop-Process $process.Id -Force}}

それは実際に私たちがやっていることです。

于 2016-09-13T15:27:42.300 に答える