web-dev-qa-db-ja.com

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

ログファイルを解析して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を解析する方がよい理由はありますか?

16
terdon

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($$);
20
Stephen Harris
  • 99.9%は、/proc/PIDが存在する(およびディレクトリである)かどうかを確認することで、kill 0手法と比較して98%の信頼性があると確信しています。 98%が100%ではない理由は、Stephen Harrisが触れた(そして跳ね返った) コメントで —つまり、/procファイルシステムがマウントされていない可能性があるということです。 /procのないLinuxシステムは、損傷した、機能が低下したシステムであると主張するのは有効かもしれません。結局のところ、pstoplsofなど動作しません—したがって、これは本番システムでは問題にならない可能性があります。しかし、(理論的には)マウントされていない可能性があります(これにより、システムが通常の状態になるのを妨げる可能性があります)が、確実にマウント解除される可能性があります(私はテストしました)1)、そしてそれが存在するという保証はありません(つまり、POSIXでは必要ありません)。そして、システムが完全にホースされない限り、killは機能します。
  • Stephenのコメントは、「ファイルシステムに出かける」と「ネイティブシステムコールを使用する」について語っています。これは主に赤いニシンだと思います。
    • はい、/procにアクセスするには、ルートディレクトリを読み取ってfind/procファイルシステムにアクセスする必要があります。これは、/bin/etc、および/devにあるものを含め、絶対パス名でanyファイルにアクセスしようとする場合に当てはまります。これは頻繁に発生するため、システムの全ライフタイム(稼働時間)の間、ルートディレクトリが確実にメモリにキャッシュされるため、ディスクI/Oなしでこの手順を実行できます。そして、/procのiノードを取得すると、それ以外のすべてのことはメモリ内にあります。
    • /procにどのようにアクセスしますか? statopenreaddirなどは、killと同じくらいビットごとにネイティブシステムコールです。
  • 質問は実行中のプロセスについて話します。これはつるつるしたフレーズです。プロセスがrunningであるかどうかを実際にテストする場合(つまり、実行キュー内;あるCPU上の現在のプロセス;スリープしていない、待機している) 、または停止)、ps PIDを実行して出力を読み取るか、/proc/PID/statを確認する必要がある場合があります。しかし、あなたの質問やコメントに、あなたがこれに関心を持っているというヒントはありません。

    部屋の象は、しかし、それはゾンビ2 プロセスは、生きているプロセスと区別するのが難しい場合があります。 kill 0はゾンビで動作し、/proc/PIDが存在します。前の段落にリストされている手法(ps PIDを実行して出力を読み取るか、/proc/PID/statを見る)を使用してゾンビを識別できます。私の非常に迅速でカジュアルな(つまり、完全ではない)テストでは、/proc/PID/cwd/proc/PID/root、またはreadlinkまたはlstatを実行してこれを実行することもできます。 /proc/PID/exe —ゾンビでは失敗します。 (ただし、所有していないプロセスでも失敗します)。

____________
1-ff orce)オプションが機能しない場合は、-ll azy)を試してください。
2つまり、終了/終了/終了したが、その親がwaitをまだ実行していないプロセス。