質問: fopenでファイルにログ等を書き込んでいますが、 fopenで開く予定のファイルを、ログの確認等で Apacheではなく管理者ユーザー等が先に開いていた場合、 Win環境では、permission denyでWarningエラーになりますが Linux環境では、viでもlessでも問題なくApacheが 書き込んで行きます。 この違いはviやlessが読みとり専用で開いていたりするからでしょうか。 また、Win環境で当該permission denyを防ぐ方法として どのような方法が一般的でしょうか。 個人的には、fopen失敗したら、開く予定のファイル名に連番をふって そこに書き込むなどを考えていますが。
回答: だいたいのことは、Wikipedia の以下のページで解説されています。 →「ファイルロック - Wikipedia」 Windows での fopen は WIN32API の CreateFile のラッパーです。 CreateFile API は、その第三引数で共有モードが決まります。 → CreateFile 関数 Microsoft の fopen のソースを見たことはありませんが、第三引数の dwShareMode は、ゼロが設定されているでしょう。 つまり、排他がかかる。 unix 系の fopen は、open システムコールのラッパーです。 open には、ファイルのロックの機能がありません。 明示的に fctrl なんかでロックをかけないと、ファイルは共有される。 POSIX だと、ファイルの共有モードを指定してファイルを開くのは、sopen 。 デフォルトが「ファイルは、共有される」なので、sopen を使うケースは、ファイル共有に制限をかけたい場合。 個別のコマンドに着目すると、その実装によるので、また事情がちょっと違います。 vi もしくは、そのクローンの場合。 初期の vi は違ったと思いますが、vim に代表される vi のクローンだと、編集ファイルを直接いじるのではなく、ワークファイルを作って、それに編集内容や履歴を保持します。 編集対象には、明示的にロックをかけていませんから、他のプロセスも書き込めます。 でも、vi を触っていると、その他のプロセスからの変更内容が分からない(対象のファイルを、逐一見ているわけでは無いから)。 明示的に、:e! としないと、その時点でのファイルの内容は、編集画面に反映されません。 less の場合。 読み取り専用で開いているとは思いますが、それはファイルの排他を意識してのことでは無くて、ファイルに書き込む機能が無いから、という理由にすぎません。 less が早いのは、一度に対象のファイルをすべて読み込むわけでは無いから。 大きなファイルを開いた直後に、別のプロセスが、ファイルの末尾に追加書込みをした場合、less で、G でファイルの末尾を表示すると、その追加書込みを参照できます。 G は、実ファイルの読み直しもやっています。 ファイルの末尾を表示している状態で、別のプロセスが、ファイルの末尾に追加書込みをする。 less で、G とすると、追加書込みされた内容が表示されます。 それは、そういうふうに実装されているから。 > また、Win環境で当該permission denyを防ぐ方法として > どのような方法が一般的でしょうか。 > > Windows のアプリは、ほぼ全てと言って良いくらい、排他をかけてファイルをオープンします。 なので、一般的なのは、なるべく早くファイルをつかんで、つかみっぱなしにしておく(つまり、fclose しない)ことです。 自分が最初にファイルをつかむことが期待できない場合には、質問の文面にも書かれている通り、別ファイルに書き出すしかないでしょうね。