• ベストアンサー

時間がかかり過ぎたプロセスをキルする方法

system関数を用いて、ループ内で外部プログラムを連続的に実行しています。ところが、時々、無限ループに近い状態に陥ってしまうデータがあるので、時間制限を設けて、その時間内に終了しない場合には、そのプロセス(外部プログラム)を強制終了させたいのです。 また、もし、強制終了させた場合には、それと分かるように戻り値を返してもらえると、なお良いです。 この仕組みを実現する手法、もしくは、モジュール等を教えて頂けないでしょうか。

  • Perl
  • 回答数2
  • ありがとう数14

質問者が選んだベストアンサー

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

自前のsystemであるmysystemを自作します。 これは、第1引数にタイムアウト時間(秒)を取り、 第2引数以降は、systemを呼び出すときのパラメータの集合をとります。 mysystemの戻り値は -1:fork失敗(通常あり得ない) -2:タイムアウト(第1引数で指定された時間内にコマンドが終了しなかった) 255:execエラー(第2引数以降が正しくないのでコマンドとして実行できない)(但し、この仕様は255を終了ステータスで返すコマンドがあるとそのステータスと区別ができない、ということがあるが、まず、これが問題になることはないだろうという前提で作成。対策が無いわけではないが、ソースが複雑になるので、とりあえず、簡易版) とします。 以下ソースです。 ------------------------------------------ #! /usr/bin/perl $stime = time(); $result = &mysystem(60,@ARGV); $etime = time(); printf ("result=%d,excuted time=%d\n",$result,$etime-$stime); #自前のsystem # P1:タイムアウト時間(単位:秒) # P2:systemへ渡す文字列 # 戻り値: -1:fork error # 255:exec error(コマンド文字列不正) # -2:timeout # 以外:コマンドの終了ステータス sub mysystem { use POSIX qw( SIGKILL ); my $timeout = shift(@_); #タイムアウト時間 my @cmd = @_; #コマンドリスト my $pid = fork(); # fork失敗 if (!defined($pid)){ return -1; } #子プロセスの場合 if ($pid == 0){ exec(@cmd); # execが成功すれば戻ってこない # 下記の文が実行されるのはexec失敗の場合だけ exit(255); } #親プロセスの場合 while($timeout>0){ #my $ret = POSIX::waitpid($pid,&POSIX::WNOHANG); my $ret = waitpid($pid,&POSIX::WNOHANG); #プロセス終了時(プロセスの終了ステータスは$?に格納されている) if ($ret != 0){ #プロセスの終了ステータスを返す printf("ret=%d,pid=%d,sts=%d\n",$ret,$pid,$?); return ($?/256); } # プロセスが終了していない場合1秒待つ $timeout--; sleep(1); } #タイムアウト検出時 #子プロセスをKILLする kill(SIGKILL,$pid); #殺した子プロセスをみとる(成仏させる) waitpid($pid,0); # タイムアウトで終了 return -2; } ------------------------------------------ 上記のスクリプトをsampl.plで保存し、 sampl.pl 実行したいコマンド名 と入力して下さい。 その 実行したいコマンド名を実行し、60秒以内に完了しなければ、 そのコマンドをKILLし、-2で戻ります。(linux(cent-os4.4))で動作確認済みです。

rafysta
質問者

お礼

希望していたものを遥かに上回る素晴らしいプログラムを書いていただき、ありがとうございます。 使いやすさの点や、戻り値の値など、とても素晴らしいです。 おかげさまで、やりたい処理ができそうです。 ありがとうございました。

その他の回答 (1)

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.1

>この仕組みを実現する手法、もしくは、モジュール等を教えて頂けないでしょうか。 unix系なら、fork,exec,killの組み合わせでなんとかなりそうですが、OSはなんでしょうか?

rafysta
質問者

お礼

回答ありがとうございます。 OSはLinuxです。 よろしくお願いします。

関連するQ&A

  • 指定プログラムのプロセスを監視・killするには?

    CGIが不正終了(もしくは無限ループ)して、CPUに負担をかけ続けることで悩んでいます。 topコマンドで負担をかけているプロセスを発見してkillすることは可能ですが、これを自動で実行するようなことはできないでしょうか。 cronを使って1分間に1度チェックし、3分以上同じプロセスが動いている場合にkillしたり、もしくは不具合の起こる特定のプログラム(hoge.cgi等)を監視してkillするということができるようにしたいのです。 自分で考えたのは「top -n 1」で出力して、3分間同じプロセスがCPUに負担をかけ続けている場合にkillできるようにphpなどでプログラミングすることでしたが、もっと簡単にできるような方法がありますでしょうか。

  • プロセス監視の方法

    どのたかよい方法をご存知の方いらっしゃいましたら、 助力お願いします。 .NETのアプリケーションで、ある特定のプロセスが起動した時に 処理を実行するアプリを作りたいと思っています。 この場合のあるプロセスとは、Notepadとか、Wordとかです。 無限ループで、プロセスを監視しようと思ったのですが、 メモリの消費が多く重たいので、何かよい方法はないでしょうか? 例えば、ある特定のプロセスが起動したら、 それがトリガーとなるような仕組みとか、可能でしょうか? よろしくお願いします。

  • fork()で作られた子プロセスから親プロセスの生存を知る方法は?

    タイトルの通りなのですが、プロセスAから fork()で子プロセスBを作り、Bには無限ループで処理をさせます。 Aはユーザからの入力を受け、処理を行います。 Aが終了要求をされプロセスを終了するときに、 Bも同時に終了したいのですが、BからAの生存を判定して Aのプロセスが切れていたBも終了する、ということは可能でしょうか? Bの無限ループ処理では、ファイルの書き換えを行っているので AからBのPIDを指定してKillする、ということはせずに B自身で判定して終了するようにしたいのですが。。

  • UWSCに制限時間を付けたいです

    UWSCでループの中のループで無限ループにハマってしまいプログラムが終わらなくなった時のために 一定時間経ったら最期の判定に行く前であっても読み込んだUWS自体を強制的に終了させれるようにしたいです REPEAT REPEAT xxxxxxxx  ←ここで無限ループに UNTIL UNTIL 上のようになります また最期のUNTILに t=GETTIME() UNTIL ((GETTIME()-t)>=3) //3秒以内に終わらなかったら終了 上のように制限時間を付けても、判定のある最期まで行けないと動かなくなり 使うループの数が多いため 最初の方か最期のほうに数行書くだけでいいように作りたいです ご教授お願いしますm(__)m

  • プロセスの終了

    密かに容量を食っているプログラム(CLIexe svchost.exe等)を開放したいのですが、 タスクマネージャーの「プロセスの終了」で強制終了した場合、 そのプログラムは二度と使用する事が出来なくなってしまうのでしょうか? どなたかご教示願います。

  • プロセスがタスクマネージャーに残るのは、なぜ?

    vbのプログラムから、GetExitCodeProcessとDo Whileを使用し外部プログラム(メモ帳など)の実行、監視しています。何かの表示しに、外部プログラムが終了しているにもかかわらず終了コードが取れないことがあり、タスクマネージャーを見ると、プロセスが残っている状態です。 なぜ、終了コードが取れずに、プロセスが残るのでしょうか? 何か参考があればよろしくお願いします。

  • プロセス?

    こんばんは、え~と「Ctel+Alt+Ddelete」キーを押すとプログラムを強制終了できるウィンドウがでますよね それでウィンドウが出るはいいんですが、なぜかプロセスだけ表示されるんです。どうしたら元に戻せますか?

  • タスクマネージャのプロセスについて

    最近パソコンの動作が遅くデフラグやウィルス検索をしても 速くならないので、タスクマネージャのプロセスを見ているところです。 質問なんですが ・プロセスの終了で強制終了させていいのはどのプロセスでしょうか? SYSTEMは触っちゃいけませんよね? ・どのプロセス(イメージ名)がどのプログラムのものなのか調べる方法はありますか? よろしくお願いします。

  • Process.Startの戻り値を後で取得

    お世話になっております。 作業マシン:WINDOWS Server2008 (仮想) 開発ツール:VWD2010(VB) 使用DB:SQLServer2008R2 にて、Webアプリを開発しております。 ASP.NET開発の経験はおおよそ1ヶ月半程です。 現在、Process.Startで外部exeを実行しております。 この外部実行ファイルは3分くらい掛かる処理で、 WaitForExit() で結果を待たずに 次の画面(待機用画面)に遷移しています。 処理が終了したら、待機画面から結果画面へと遷移させたいのですが、 プロセスの完了と、その結果(戻り値)を、 Process.Startをコールした画面以外で受け取る事が出来るのでしょうか。 WaitForExitを使用するならば、 素直に終了を待ち、終了後にExitCodeを取得、 Ret = Process.Start() で戻り値も取得できましたが… WaitForExit( ) をしない場合、どのようにして取得できるのでしょうか。 http://dobon.net/vb/dotnet/process/openfile.html こちら等、Process.Start 非同期 などのキーワードで出てくるのは Processを実行した同画面内での待機のケースが多く、 今自分が遭遇しているケースに応用するには どうにも自分の理解が追いつけず質問いたします。 実行する画面でプロセスIDを取得し、セッションに持たせ、 終了を判断したい画面でプロセスIDを元にチェックをする… と言うことも考えてみましたが、プロセスIDを頼りに、 終了したプロセスの戻り値を突き止める方法も見つからず (発想自体が間違っているかもしれません) 皆様のお力を貸して頂けないでしょうか。何卒よろしくお願いします。

  • プログラムが終了しているのにプロセスにプログラムが残る

    日本語がおかしいような気がしますがすみません。 先ほどまでプログラムを組んでいたのですが、WinMainがしっかりと return 0; を返しているのにウィンドウは消えるのですがタスクマネージャーにはしっかりとプロセスが表示されています。 現在はreturn 0;の前でexit(0);でごまかしているのですが・・・。 無限ループしているわけでもないのにアプリケーションが終了しないなんてことはあるのでしょうか?? 現在やっていることといえばSTLのリストとnewで領域の確保、管理をしている程度です。 ご教授願います。

専門家に質問してみよう