vimとともにinotifywaitを使用する


14

ファイルの変更を監視し、リモートコピーでrsyncする簡単なスクリプトがあります。

#!/bin/bash

while inotifywait -e close_write somefile
do
    rsync somefile user@host.domain:./somefile
done

nanoでは問題なく動作しますが、vimでは失敗します。nanoを使用すると、次のように出力されます。

somefile CLOSE_WRITE,CLOSE   

次のループを開始して、別のエディションを待機します。

vimを使用すると、出力はなく、スクリプトは終了コード0で終了します。

私はいくつかの研究を行い、close_writeはvimと一緒にinititofywaitを使用するための正しいパラメータであることを発見しました(最初にmodifyイベントを使用したかった)が、何らかの理由で失敗します。


わたしにはできる。あなたはやった変更を保存するだけではなく、編集のためにそれを開く前に、vimの中のファイルを?
ロアイマ

@roaima backupcopyオプションがオフの場合のみ機能します。
ジル 'SO-悪であるのをやめる'

回答:


14

編集者は、いくつかの戦略に従ってファイルを保存できます。2つの主な変種は、既存のファイルを上書きするか、新しいファイルに書き込んで所定の場所に移動することです。新しいファイルへの書き込みとその場所への移動には、任意の時点でファイルから読み取ることでファイルの完全なバージョン(1つのインスタントが古いファイル、次のインスタントが新しいファイル)を提供するという素晴らしい特性があります。ファイルが所定の場所に上書きされると、ファイルが不完全になる時間があります。それは、他のプログラムがそのファイルにアクセスした場合やシステムがクラッシュした場合に問題となります。

ナノは明らかに既存のファイルを上書きします。スクリプトは、書き込みが終了した時点(close_writeイベント)を検出し、その時点で実行rsyncします。rsyncが最初の保存からジョブを完了する前に、2回続けて保存すると、rsyncが不完全なバージョンのファイルを取得する可能性があることに注意してください。

一方、Vimはwrite-then-move戦略を使用します。

echo 'new content' >somefile.new
mv -f somefile.new somefile

ファイルの古いバージョンに何が起こるかは、新しいバージョンが所定の場所に移動した時点で削除されることです。この時点で、inotifywait監視するように指示されたファイルが存在しないため、コマンドが返されます。(新しいsomefileファイルは同じ名前の別のファイルです。)Vimがバックアップファイルを作成するように構成されていた場合は、次のようになります

echo 'new content' >somefile.new
ln somefile somefile.old
mv -f somefile.new somefile

そしてinotifywait今、バックアップを見ています。

ファイルの保存方法の詳細については、プログラムの実行中にライブ更新を実行する方法を参照してくださいおよびファイルのアクセス許可と保存

Vimに上書き戦略を使用するように指示することができます:backupcopyオプションをオフにします(:set nobackupcopy)。上記のように、これは危険です。

両方の保存戦略を処理するには、ディレクトリを監視し、両方のイベントclose_writeとのmoved_toイベントをフィルタリングしsomefileます。

inotifywait -m -e close_write,moved_to --format %e/%f . |
while IFS=/ read -r events file; do
  if [ "$file" = "somefile" ]; then
    …
  fi
done

ここで提案する方法の欠点は、複数のファイルを「一度に」書き込むと、コマンドが各ファイルに対して1回実行されることです。コードを編集しているので、ヘッダーと他のいくつかの翻訳単位とを変更することがあり:waます。次に、書き込まれたすべてのファイルに対してビルドが1回実行されます。
限定A

@LimitedAtonementこれは、この質問のユースケースよりもはるかに複雑なユースケースです。ユースケースでは、1つのファイルが保存されてから少し待つ必要があります。ファイルが実際に「一度に」変更されることはありません。で複数のファイルを保存すると:wa、連続したinotifyイベントが発生します。他の人が来ているかどうかを確認するには、最初の人の後に待つ必要があります。ただし、ここに示されているコードを使用できます。追加の複雑さはに含まれます。
ジル 'SO-悪であるのをやめる'

@Gillesで決めましwhile true; do inotifywait ... [no -m]; make; sleep .1; done;た。いくつかの落とし穴がありますが、私はかなり実用的なものに到達しました。
限定的な償い
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.