web-dev-qa-db-ja.com

UnixでのPIDファイルの適切な処理に関するリファレンス

UnixでのPIDファイルの適切な処理の詳細を示す尊敬される参照はどこにありますか?

Unixオペレーティングシステムでは、特別なロックファイル(PIDファイル)を使用してプログラム(多くの場合はデーモン)を「ロック」するのが一般的です。

これは予測可能な場所にあるファイルで、多くの場合「/var/run/foo.pid」です。プログラムは、起動時にPIDファイルが存在するかどうかを確認し、ファイルが存在する場合はエラーで終了します。つまり、一種の助言的で協調的なロックメカニズムです。

ファイルには、現在ロックを保持しているプロセスの数値プロセスID(つまり「PIDファイル」という名前)である1行のテキストが含まれています。これにより、ロックを保持しているプロセスへのシグナルの送信を自動化する簡単な方法が可能になります。

私が見つけることができないのは、PIDファイルを処理するための予想される動作または「ベストプラクティス」の動作に関する適切なリファレンスです。さまざまなニュアンスがあります。実際にファイルをロックする方法(気にしないでください。カーネルを使用しますか?プラットフォームの非互換性についてはどうでしょうか)、古いロックの処理(サイレントに削除しますか?チェックするタイミング?)、正確にロックを取得して解放するタイミングなど。

この小さなトピックの尊敬され、最も権威のある参照(理想的にはW.リチャードスティーブンスのレベル)はどこにありますか?

58
bignose

私の知る限り、PIDファイルは、信頼できる、ほとんどの場合信頼できるソースを見つけることができるものではなく、規則です。私が見つけることができる最も近いものは、ファイルシステム階層標準の このセクション です。

このPerlライブラリ は、作成者が少なくとも発生する可能性のある問題を考えているように見えるため、役立つかもしれません。

/ var/run以下のファイルは、デーモンの作成者ではなく、ディストリビューションのメンテナーによって処理されることが多いと思います。すべてのinitスクリプトが一緒にNiceを実行することを確認するのは、ディストリビューションのメンテナーの責任だからです。 DebianとFedoraの開発者向けドキュメントをチェックしたところ、詳細なガイドラインは見つかりませんでしたが、開発者向けのメーリングリストで詳細情報を入手できる可能性があります。

17
Josh Kelley

まず、最近のすべてのUNIXでは、/var/runは再起動後も保持されません。

PIDファイルを処理する一般的な方法は、初期化中に作成し、通常のハンドラーまたはシグナルハンドラーのいずれかの出口から削除することです。

ファイルをアトミックに作成/チェックするには、2つの標準的な方法があります。最近の主な問題は、O_EXCLフラグを使用してファイルを開くことです。ファイルがすでに存在する場合、呼び出しは失敗します。古い方法(O_EXCLがないシステムでは必須)は、ランダムな名前で作成し、それにリンクすることです。ターゲットが存在する場合、リンクは失敗します。

21
Joshua

Kerriskの The Linux Programming Interface のセクション55.6 "Running Just One Instance of a Program" を参照してください。これは、StevensのUnixネットワークプログラミングv2のpidfile実装に基づいています。

また、pidfileの場所は通常、ディストリビューションによって(initスクリプトを介して)処理されるため、適切に記述されたデーモンはコマンドライン引数を使用してpidfileを指定し、これが構成ファイルによって誤って上書きされないようにします。また、古いpidファイルを単独で正常に処理する必要があります(O_EXCLは使用しないでください)。 fcntl()ファイルロックを使用する必要があります。デーモンのpidfileがローカル(非NFS)ファイルシステムにあると想定する場合があります。

11
John Hammond

ディストリビューションによって異なりますが、実際には、pidfileを処理するinitスクリプトです。開始時に存在を確認し、停止時に削除するなど、私はそのようにするのが好きではありません。私は自分のinitスクリプトを作成し、通常は標準のinit関数を使用しません。

適切に作成されたプログラム(デーモン)には、このpidfile(存在する場合)を書き込む場所を示す何らかの構成ファイルがあります。また、シグナルを処理できる場合は常に、正常または異常終了時にPIDファイルがクリーンアップされるように、シグナルハンドラーを確立するように注意します。その後、PIDファイルはinitスクリプトに正しいPIDを提供し、停止できるようにします。

したがって、起動時にpidfileがすでに存在する場合、それは以前にクラッシュし、何らかのリカバリ作業(該当する場合)を実行する必要があることをプログラムに示す非常に優れた指標です。 PIDの存在をチェックするか、リンクを解除するinitスクリプト自体がある場合は、そのロジックを足元で撃ちます。

名前空間に関しては、プログラム名の後に続く必要があります。 「foo-daemon」を開始している場合は、foo-daemon.pidになります。

/ var/lock/subsysも調べる必要がありますが、これは主にRed Hatフレーバーで使用されます。

7
Tim Post

Red Hat 7のsystemdパッケージは、「[システムデーモンの書き込みとパッケージ化]」というヘッダー行を含むdaemon(7)のマニュアルページを提供します。

このmanページでは、「古いスタイル」(SysV)と「新しいスタイル」(systemd)の両方のデーモン化について説明しています。新しいスタイルでは、systemd自体がPIDファイルを処理します(そのように構成されている場合)。ただし、古いスタイルでは、manページには次のように書かれています。

  1. デーモンプロセスで、デーモンのPID(getpid()によって返される)をPIDファイル、たとえば/run/foobar.pid(架空のデーモン「foobar」の場合)に書き込んで、デーモンが2回以上起動できないようにします。 。これは競合のない方法で実装する必要があります。これにより、以前にPIDファイルに格納されたPIDが存在しないか、外部プロセスに属していることが確認されたときにのみPIDファイルが更新されます。

このマニュアルページ online も読むことができます。

1
Wildcard