特定のPIDが実行されているかどうかを確認するにはどうすればよいですか?


16

ログファイルを解析してPIDを収集し、そのPIDが実行されているかどうかを確認するPerlスクリプトを作成しています。私はそのチェックを行うための最良の方法を考えようとしています。明らかに、私は次のようなことができます:

system("ps $pid > /dev/null") && print "Not running\n";

ただし、可能な場合はシステムコールを避けたいと思います。そのため、/procファイルシステムを使用できると考えました(移植性は問題ではありません。これは常にLinuxシステムで実行されます)。例えば:

if(! -d "/proc/$pid"){
    print "Not running\n";
}

それは安全ですか?/proc/$pid/ディレクトリがない場合、関連するPIDが実行されていないと常に想定できますか?AFAIK ps自体は/procとにかくその情報を取得するので、私はそう期待していますが、これは本番コード用であるため、確実にしたいです。

それで、実行中のプロセスに/proc/PIDディレクトリがない場合や、/proc/PIDディレクトリが存在し、プロセスが実行されていない場合がありますか?psディレクトリの存在を確認するよりも解析を好む理由はありますか?


2
killシグナル0を使用するperl 関数もあります。この関数は、強制終了はしませんが、強制終了できるかどうかを示します(つまり、そのプロセスにシグナルを送信する許可が必要です)。
-meuh

1
Linuxでこれを行う場合は、「/ proc / $ PID」で十分です。
likewhoa

7
@terdon使用するメソッドが何であっても(kill -0最高のメソッド)、これは指定されたPIDで実行中のプロセスがあるかどうかだけを通知することに注意してください。プロセスがまだ1ミリ秒後に実行されるかどうかはわかりません。また、興味のあるプロセスか、興味深いプロセスが終了した後に同じPIDが割り当てられた無関係のプロセスかどうかはわかりません。ほとんどの場合、特定のPIDが実行されているかどうかをテストするのは間違いです。競合状態になりにくい状況はほとんどありません。
ジル 'SO-悪であるのをやめる'

1
@Gilles、確かに、プロセス名も確認する必要があります。ただし、この場合、ミリ秒後にステータスが変更されてもかまいません。dBでアクティブとしてリストされているプロセスと、pidを持つ対応するファイルがあります。DBが実行していると考えているものが実際に実行されていないかどうかを確認し、ランダムに再起動できないことを確認するためにセットアップを十分に制御する必要があります。
テルドン

3
@MickLHうわー、それは私に言われました。それが実際にあなたが自分の輝きを祝うのではなく、何がそんなに悪くて危険なのかを説明しようと思ったら便利なコメントだったでしょう。私はあなたが正しいことを疑いません、私はプログラマーであると主張したことがないので、私は質問をしましたが、あなたはなんとかin辱的で役に立たないことになりました。
テルドン

回答:


20

perl関数kill(0,$pid)を使用できます。

戻りコードが1の場合、PIDが存在し、シグナルを送信できます。

戻りコードが0の場合、$!を確認する必要があります。プロセスが存在することを意味するEPERM(許可が拒否された)またはプロセスが存在しない場合はESRCHである可能性があります。

チェックコードが実行されているroot場合は、killの戻りコードをチェックするだけに簡単にできます。0 =>エラー、1 => ok

例えば:

% perl -d -e 0

Loading DB routines from perl5db.pl version 1.37
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(-e:1):   0
  DB<1> print kill(0,500)
0
  DB<2> print $!
No such process
  DB<3> print kill(0,1)
0
  DB<4> print $!
Operation not permitted
  DB<5> print kill(0,$$)
1

これは単純な関数にすることができます

use Errno;

sub test_pid($)
{
  my ($pid)=@_;

  my $not_present=(!kill(0,$pid) && $! == Errno::ESRCH);

  return($not_present);
}

print "PID 500 not present\n" if test_pid(500);
print "PID 1 not present\n" if test_pid(1);
print "PID $$ not present\n" if test_pid($$);

FWIW、これを行う方法を示す簡単な関数を追加しました。
スティーブンハリス

ええ、私はこれで行くと思います。必要なものはすべてif (!kill(0,$pid) && $! =~ /No such process/){ exit; }またはそれに類似していることに気付いたので、コメントを削除しました。あなたのErrnoソリューションの方が好きです、ありがとう。私はおそらくこれを使用しますが、基礎となるLinuxの質問に誰かが答えられるようになるまでしばらく待ちます。
テルドン

2
/procがマウントされている場合、名前空間に表示されるすべてのPIDが存在するため、-d /proc/$pidテスト機能しますが、ネイティブシステムコールを使用するのではなく、ファイルシステムにアクセスする必要があります。
スティーブンハリス

それはまさに私が避けたかったことです。
テルドン

2
@terdon:「システムコール」とは、実際には「systemコール」、つまり「システムコール」systemではなく、関数自体へのコールを意味するという事実から混乱が生じたことに気付きました。後者は避けることができませんが、前者は確かにできます。今理にかなっています!
Mehrdad

6
  • 存在するかどうか(ディレクトリであるかどうか)をチェックすることは、テクニックと同じように98%信頼できると私は99.9%確信しています。98%が100%ではない理由は、Stephen Harrisがコメントで触れた(そしてバウンスした)ことです。つまり、ファイルシステムがマウントされていない可能性があります。Linuxシステム が破損、劣化したシステムであると主張するのは妥当かもしれません。結局、、などのようなもので、おそらく動作しないでしょう。したがって、これは本番システムの問題ではないかもしれません。しかし、(理論的には)マウントされていない可能性があります(これにより、システムが正常な状態にならない場合があります)が、マウント解除される可能性があります(テスト済みです1/proc/PIDkill 0/proc/procpstoplsof)そして、私はそれが存在するという保証がないと信じています(すなわち、POSIXによって要求されていない)。そして、システムが完全にホース接続されていない限り、kill動作します。
  • Stephenのコメントは、「ファイルシステムに行く」と「ネイティブシステムコールを使用する」ことについて語っています。これは主にニシンだと思います。
    • はい、アクセスしようとする/proc と、ルートディレクトリを読み取ってファイルシステムを見つける必要あり/procます。これは、アクセスしようとするために真である任意の中のものを含む絶対パス名でファイルを、/bin/etc、と/dev。これは非常に頻繁に発生するため、ルートディレクトリはシステムの全有効期間(稼働時間)にわたってメモリに確実にキャッシュされるため、この手順はディスクI / Oなしで実行できます。そして、のiノードを取得すると/proc、発生する他のすべてはメモリ内にあります。
    • どのようにアクセスします/procか?など、ネイティブシステムであるが限りすべてのビットを呼び出します。statopenreaddirkill
  • 質問では、実行中のプロセスについて説明します。これは滑りやすいフレーズです。プロセスが実行されているかどうかを実際にテストする場合 (つまり、実行キュー内、おそらくCPU上の現在のプロセス、スリープ、待機、または停止ではない場合)、aを実行して出力を読み取るか、。しかし、あなたがこれに関係しているというあなたの質問やコメントにはヒントがありません。ps PID /proc/PID/stat

    ただし、部屋にいる象は、ゾンビ2プロセスを、生きているプロセスと区別するのが難しい場合があります。  kill 0ゾンビで動作し、存在します。前の段落に記載されている手法(出力の実行と読み取り、または)でゾンビを識別できます。私は非常に迅速&カジュアル(すなわち、非常に徹底していない)の試験はあなたにも行うことで、これを行うことができますことを示唆しているか に、または-これらは、ゾンビに失敗します。(ただし、所有していないプロセスでも失敗します。)/proc/PIDps PID/proc/PID/statreadlinklstat/proc/PID/cwd/proc/PID/root/proc/PID/exe

____________
1  の場合-fF ORCE)オプションしない作業、トライ-lリットル azy)。
2、  つまり、終了/終了/終了したが、その親がまだ実行していないプロセスwait


私の答えに対するコメントをありがとう。それは間違っていたので削除した。kill(2)マンページがあなたが指摘した動作を直接示しているとは思わないが、マンページは示しperlfuncている。Michael Kerriskにメールを送って、システムのマンページについて彼が言っていることを確認します。
jrw32982がモニカをサポートする

私はのmanページを明確にするためにバグレポートを提出しkill(2)、「送信」信号0にアクセス権について
jrw32982サポートモニカ

@ jrw32982:まあ、マニュアルページには、「sig引数…0の場合があります。この場合、エラーチェックが実行されます…」および「エラーkill()システムコールは失敗し、次の場合はシグナルが送信されません。 …送信プロセスはスーパーユーザーではなく、その有効ユーザーIDは受信プロセスの有効ユーザーIDと一致しません。…」と言われましたが、これは複数の方法で解釈できると思いますが、残念ながら、多くのUnixマニュアルページはこのスタイルで書かれており、行間を読む必要があります。マイケルは、それが十分に明確であると信じるかもしれません。
G-Manが「Reinstate Monica」と言う

Michaelはkill(2)マンページに変更を加えました(まだオンラインでは表示されていません):「sigが0の場合、シグナルは送信されませんが、存在と許可のチェックは実行されます。これを使用して、呼び出し元がシグナルを送信することを許可されているプロセスIDまたはプロセスグループID。」
jrw32982はモニカをサポートします
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.