ログファイルを解析して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
を解析する方がよい理由はありますか?
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($$);
/proc/PID
が存在する(およびディレクトリである)かどうかを確認することで、kill 0
手法と比較して98%の信頼性があると確信しています。 98%が100%ではない理由は、Stephen Harrisが触れた(そして跳ね返った) コメントで —つまり、/proc
ファイルシステムがマウントされていない可能性があるということです。 /proc
のないLinuxシステムは、損傷した、機能が低下したシステムであると主張するのは有効かもしれません。結局のところ、ps
、top
、lsof
など動作しません—したがって、これは本番システムでは問題にならない可能性があります。しかし、(理論的には)マウントされていない可能性があります(これにより、システムが通常の状態になるのを妨げる可能性があります)が、確実にマウント解除される可能性があります(私はテストしました)1)、そしてそれが存在するという保証はありません(つまり、POSIXでは必要ありません)。そして、システムが完全にホースされない限り、kill
は機能します。/proc
にアクセスするには、ルートディレクトリを読み取ってfind/proc
ファイルシステムにアクセスする必要があります。これは、/bin
、/etc
、および/dev
にあるものを含め、絶対パス名でanyファイルにアクセスしようとする場合に当てはまります。これは頻繁に発生するため、システムの全ライフタイム(稼働時間)の間、ルートディレクトリが確実にメモリにキャッシュされるため、ディスクI/Oなしでこの手順を実行できます。そして、/proc
のiノードを取得すると、それ以外のすべてのことはメモリ内にあります。/proc
にどのようにアクセスしますか? stat
、open
、readdir
などは、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-f
(f orce)オプションが機能しない場合は、-l
(l azy)を試してください。
2つまり、終了/終了/終了したが、その親がwait
をまだ実行していないプロセス。