ps *very*が時々有効なプロセスを見つけられないのはなぜですか?

ps *very*が時々有効なプロセスを見つけられないのはなぜですか?

ps -o args -p <pid>コマンドの1つが奇妙な問題に遭遇しました。非常に時々そのプロセスがそのサーバーで確実に実行されているにもかかわらず、そのプロセスが見つかりません。これらのプロセスは、特定のJavaアプリケーションを実行するために使用される長期実行ラッパースクリプトです。

「野生」で発生する問題は常に早朝に発生しているように見えるため、サーバーの負荷がかなり重いため、サーバーのディスク負荷に関連しているという証拠がありますps。問題は繰り返すことができます。数百回ごとにエラーが発生するので実行します。

次のbashスクリプトを実行して、失敗した実行と成功した実行のstrace出力を正常に生成しました。

while [ $? == 0 ] ; do strace -o fail.out ps -o args -p <pid> >/dev/null ; done ; strace -o good.out ps -o args -p <pid>

fail.outとの出力を比較すると、実行時に失敗したシステムコールがシステムの実際のプロセス数よりはるかに小さい数を返すことがgood.outわかります(〜1100と比較して約〜500)。getdents

grep getdents good.out
  getdents(5, /* 1174 entries */, 32768)  = 32760
  getdents(5, /* 31 entries */, 32768)    = 992
  getdents(5, /* 0 entries */, 32768)     = 0

grep getdents fail.out
  getdents(5, /* 673 entries */, 32768)   = 16728
  getdents(5, /* 0 entries */, 32768)     = 0

...そしてその短いリストには問題の実際のpidが含まれていないため、見つかりません。

この部分は無視しても構いません。 ENOTTY エラーは以下の dave_thompson の説明で説明されており、関連性はありません。

また、失敗した実行には、ENOTTY正常な実行では発生しないいくつかのエラーが表示されます。出力の先頭の近くに表示されます。

ioctl(1, TIOCGWINSZ, 0x7fffe19db310) = -1 ENOTTY (ioctl はデバイスには適していません) ioctl(1, TCGETS, 0x7fffe19db280) = -1 ENOTTY (ioctl はデバイスには適していません)

ついに私は一つを見た

ioctl(1, TCGETS, 0x7fffe19db0d0) = -1 ENOTTY(ioctl はデバイスに適していません)

ioctl最後の失敗は返される前に発生しますが、空の結果セットが印刷されたps後に発生するため、関連があるかどうかはわかりません。ps失敗したすべてのstrace出力では一貫性がありますが、成功した出力ではそうではないことがわかります。

時々、プロセスの完全なリストが見つからない理由が全く分からず、getdentsラッパーをチェックする制御スクリプトを変更して、全体に絆創膏を貼り付けようとするところに達しました。最初に失敗した場合は、2番目の呼び出しが疑われますが、psここで何が起こっているのか知っている人がいるかどうかを知りたいです。

問題のシステムはCentOS 7およびprocps-ngバージョン3.3.10-17.el7_5.2.x86_64でカーネル4.16.13-1.el7.elrepo.x86_64を実行しています。

答え1

/procを介さずにファイルシステムから直接必要な情報を読むことを検討してください。空白の代わりにNULバイトで区切られたpsファイルで探している情報( "args")を見つけることができます。/proc/$pid/cmdline

このsed行を使用してプロセスパラメータを取得できます$pid

sed -e 's/\x00\?$/\n/' -e 's/\x00/ /g' "/proc/$pid/cmdline"

このコマンドは次のとおりです。

ps -o args= -p "$pid"

args=inを使用するとpsヘッダーは省略されます。)

このsedコマンドは最初に最後の末尾のNULバイトを見つけて改行に置き換え、次に他のすべてのNULバイトを空白(個々のパラメータ区切り)で置き換えることによって最終的にps


システムのプロセスリストを一覧表示する方法は、psシステムのディレクトリリストを一覧表示することです/proc。ただし、プロセスの実行中に開始および終了されるため、このプロセスには固有の競合条件があるため、取得できるのは実際のスナップショットではなく近似ですps。特に、ps結果を表示するときに終了したプロセスを表示したり、実行中に開始されたプロセスを無視したりできます(ただし、リストされている場合はカーネルは返されません/proc)。

私はいつも推定プロセスが開始する前に存在し、プロセスpsが完了した後もまだ存在する場合いいえ恋しい、私は推定カーネルは、多数の異なるプロセスが作成され削除されても、これらのプロセスが常に含まれることを保証します。あなたが説明する状況はそうではないことを示唆しています。私はまだこれについて懐疑的ですが、これがどのように機能するかについて既知の競合条件があることを考慮すると、これらのps競合条件のために、PIDリストが既存のPIDを見逃す可能性があることは少なくとも合理的であると思います。/proc

これはLinuxカーネルのソースコードを調べて確認できますが、まだやっていないので、説明したように、長期実行プロセスを見逃す可能性がある競合状態があるかどうかは実際にはわかりません。


他の部分はps動作方法です。パラメータを使用して単一のPIDを渡しても、-p単一のPIDにのみ興味がある場合でも、既存のすべてのPIDが引き続き一覧表示されます。この場合、ショートカットを使用してアイテムのリストをスキップし/procてすぐに移動できます/proc/$pid

なぜこのように実装されたのか言うことはできません。たぶん、ほとんどのpsオプションはプロセスの「フィルタ」なので、-p同じ方法で実装する方が簡単です。ショートカットを直接使用すると、別のコードパスまたはコードの重複が含まれる可能性があります...別の仮説は次のとおりです。プラスを/proc/$pid含むいくつかの状況-p最終的に追加のオプションをリストする必要があるため、特定の状況でショートカットを許可し、どの状況を許可しないかを決定するのは複雑な場合があります。


/proc/$pidこれにより、システムの完全なPIDセットを一覧表示せずにすぐに開始し、すべての既知の競合を回避し、ソースから直接必要な情報を取得する解決策を見つけることができます。

少し醜いが説明する問題が存在し、その情報を取得する信頼できる方法でなければなりません。

関連情報