Sử dụng inotifywait cùng với vim


14

Tôi có tập lệnh đơn giản theo dõi tập tin để thay đổi và rsyncs nó với bản sao từ xa:

#!/bin/bash

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

Nó chỉ hoạt động tốt với nano, nhưng thất bại với vim. Khi tôi sử dụng nano, nó xuất ra:

somefile CLOSE_WRITE,CLOSE   

và bắt đầu vòng lặp tiếp theo chờ đợi một phiên bản khác.

Khi tôi sử dụng vim, không có đầu ra, tập lệnh chỉ đóng với mã thoát 0.

Tôi đã thực hiện một số nghiên cứu và phát hiện ra rằng close_write là tham số phù hợp cho uing initofywait cùng với vim (đầu tiên tôi muốn sử dụng sửa đổi sự kiện), nhưng vì một số lý do, nó thất bại đối với tôi.


Nó làm việc cho tôi. Bạn đã thay đổi tập tin trong vim trước khi lưu nó, thay vì chỉ mở nó để chỉnh sửa?
roaima

@roaima Nó chỉ hoạt động nếu backupcopytùy chọn tắt.
Gilles 'SO- ngừng trở nên xấu xa'

Câu trả lời:


14

Người chỉnh sửa có thể theo một số chiến lược để lưu tệp. Hai biến thể chính là ghi đè lên tệp hiện có hoặc ghi vào tệp mới và di chuyển nó vào vị trí. Viết vào một tệp mới và di chuyển nó vào vị trí có một đặc tính tốt là tại bất kỳ thời điểm nào, việc đọc từ tệp sẽ cung cấp cho bạn một phiên bản hoàn chỉnh của tệp (một bản tức là bản cũ, bản tiếp theo là bản mới). Nếu tệp được ghi đè tại chỗ, có một thời gian trong đó nó không đầy đủ, đó là vấn đề nếu một số chương trình khác truy cập vào nó ngay sau đó hoặc nếu hệ thống gặp sự cố.

Nano dường như ghi đè lên tập tin hiện có. Kịch bản của bạn phát hiện điểm khi nó viết xong ( close_writesự kiện) và chạy rsynctại điểm đó. Lưu ý rằng rsync có thể lấy một phiên bản chưa hoàn chỉnh của tệp, nếu bạn lưu hai lần liên tiếp, trước khi rsync hoàn thành công việc của mình từ lần lưu đầu tiên.

Vim, mặt khác, sử dụng chiến lược viết rồi di chuyển - một cái gì đó ảnh hưởng đến

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

Điều xảy ra với phiên bản cũ của tệp là nó bị xóa tại thời điểm phiên bản mới được di chuyển vào vị trí. Tại thời điểm này, inotifywaitlệnh trả về, vì tệp được bảo là không còn tồn tại. (Cái mới somefilelà một tệp khác có cùng tên.) Nếu Vim đã được cấu hình để tạo tệp sao lưu, điều sẽ xảy ra là một cái gì đó như

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

inotifywaitbây giờ sẽ xem bản sao lưu.

Để biết thêm thông tin về các chiến lược lưu tệp, hãy xem Làm thế nào có thể thực hiện cập nhật trực tiếp trong khi chương trình đang chạy? quyền và lưu tệp

Vim có thể được yêu cầu sử dụng chiến lược ghi đè: tắt backupcopytùy chọn ( :set nobackupcopy). Điều này là rủi ro, như chỉ ra ở trên.

Để xử lý cả hai chiến lược lưu, hãy xem thư mục và lọc cả hai close_writemoved_tocác sự kiện cho somefile.

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

Hạn chế của phương pháp được đề xuất ở đây là khi bạn viết một số tệp "cùng một lúc", các lệnh của bạn sẽ được chạy một lần cho mỗi tệp. Tôi đang chỉnh sửa mã, vì vậy tôi có thể sửa đổi một tiêu đề và một vài đơn vị dịch thuật khác và :wa. Sau đó, bản dựng của tôi được chạy một lần cho mỗi tệp được viết.
Chuộc tội có giới hạn

@LrictAtonement Đó là trường hợp sử dụng phức tạp hơn nhiều so với trường hợp trong câu hỏi này. Đối với trường hợp sử dụng của bạn, bạn cần đợi một chút sau khi một tệp được lưu. Các tập tin không bao giờ thực sự được sửa đổi trong một lần. Nếu bạn lưu nhiều tệp với :wa, bạn sẽ nhận được các sự kiện inotify liên tiếp. Bạn cần đợi sau người đầu tiên để xem người khác có đến không. Nhưng bạn có thể sử dụng mã được trình bày ở đây: sự phức tạp bổ sung sẽ đi vào bên trong .
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles Tôi quyết định while true; do inotifywait ... [no -m]; make; sleep .1; done;hay như vậy. Có một số vấn đề, nhưng tôi đã đến một nơi khá khả thi.
Chuộc tội có giới hạn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.