ここ実行可能ファイルを書き換えてもプロセスは問題なく実行され、プロセスが再起動すると再度読み込まれるとのことです。
ただし、プロセスの実行中にバイナリ ファイルを置き換えようとすると (scp を使用して、dev からテスト サーバーへ)、「ファイルがビジーです」というメッセージが表示されます。また、共有ライブラリ ファイル (*.so) を置き換えると、それをリンクするすべてのプロセスがクラッシュします。
なぜでしょうか? 何か見落としているのでしょうか? プロセスを停止/クラッシュさせずにバイナリ ファイルを置き換えるにはどうすればよいのでしょうか?
答え1
前述の通りソフトウェア パッケージはアップグレード中でも正常に実行されるのはなぜですか?ロックはファイル名ではなく inode に対して行われます。バイナリをロードして実行すると、ファイルはビジー状態としてマークされます。そのため、ファイルに書き込もうとすると ETXTBSY (ファイル ビジー) エラーが発生します。
さて、共有ライブラリの場合は少し異なります。ライブラリは でプロセスのアドレス空間にメモリマップされますmmap()
。MAP_DENYWRITE
を指定することもできますが、少なくともLinuxのGlibcはそれを黙って無視します(マニュアルページによると、ソースを確認してください) - こちらを確認してください糸したがって、実際にファイルを書き込むことができ、メモリマップされているため、変更はほぼ即座に表示されます。つまり、十分に努力すれば、 レンガライブラリを上書きしてマシンを変更します。
したがって、正しい更新方法は次のとおりです。
ファイルを削除すると、ファイル システムからデータへの参照が削除され、そのデータを使用する可能性のある新しく生成されたアプリケーションからはアクセスできなくなりますが、既にファイルを開いている (またはマップされている) ユーザーにとってはデータにアクセスできる状態が維持されます。
更新された内容で新しいファイルを作成します。
新しく作成されたプロセスは更新されたコンテンツを使用し、実行中のアプリケーションは古いバージョンにアクセスします。これは、正常なパッケージ管理ユーティリティが行うことです。ただし、まったく危険がないわけではないことに注意してください。たとえば、コードを動的にロードするアプリケーション (dlsym()
および関連を使用) では、ライブラリの API が暗黙的に変更されると問題が発生します。
本当に行きたいなら、本当に安全のために、システムをシャットダウンし、別のオペレーティング システム インスタンスからファイル システムをマウントし、更新して、更新されたシステムを再度起動します。
答え2
rpm アップグレードでも同じことが行われ、何もクラッシュすることなくバイナリとライブラリが実行されます。
では違いは何でしょうか:
- ファイルのリンクを解除
- 同じ名前で新しいファイルを書き込む
これはファイルをその場で置き換えるものではありません。使用中のバイナリを参照する inode は、それを開いている最後のオブジェクトが終了するまで「ビジー」のままです。新しいファイルは、新しい inode 番号で作成されます。
ここでscp
、またははcp
ファイルをその場で置き換えようとします。これにより、inode が参照しているコンテンツが変更されます。これは、説明されているように機能しません。