Saya menonton file untuk perubahan menggunakan acara inotify (seperti yang terjadi, dari Python, memanggil libc).
Untuk beberapa file selama git clone
, saya melihat sesuatu yang aneh: Saya melihat suatu IN_CREATE
peristiwa, dan saya melihat ls
bahwa file tersebut memiliki konten, namun, saya tidak pernah melihat IN_MODIFY
atau IN_CLOSE_WRITE
. Ini menyebabkan masalah bagi saya karena saya ingin merespons IN_CLOSE_WRITE
pada file: khususnya, untuk memulai pengunggahan konten file.
File yang berperilaku aneh ada di .git/objects/pack
direktori, dan berakhir di .pack
atau .idx
. File lain yang dibuat git memiliki rantai IN_CREATE
-> IN_MODIFY
-> yang lebih teratur IN_CLOSE_WRITE
(Saya tidak menonton IN_OPEN
acara).
Ini ada di dalam docker pada MacOS, tapi saya telah melihat bukti yang sama pada docker di Linux dalam sistem jarak jauh, jadi kecurigaan saya adalah aspek MacOS tidak relevan. Saya melihat ini jika menonton dan git clone
berada di wadah buruh pelabuhan yang sama .
Pertanyaan saya:
Mengapa acara ini hilang pada file-file ini?
Apa yang bisa dilakukan? Secara khusus, bagaimana saya bisa menanggapi penyelesaian penulisan ke file-file ini? Catatan: idealnya saya ingin menjawab ketika penulisan "selesai" untuk menghindari pengunggahan yang tidak perlu / (salah) mengunggah tulisan "belum selesai".
Sunting: Membaca https://developer.ibm.com/tutorials/l-inotify/ sepertinya yang saya lihat konsisten dengan
- file sementara yang terpisah, dengan nama seperti
tmp_pack_hBV4Alz
, sedang dibuat, dimodifikasi dan, ditutup; - a keras link dibuat untuk file ini, dengan akhir
.pack
nama; tmp_pack_hBV4Alz
nama aslinya dihapus.
Saya pikir masalah saya, yang mencoba menggunakan tidak sah sebagai pemicu untuk mengunggah file, kemudian mengurangi untuk memperhatikan bahwa .pack
file tersebut merupakan tautan keras ke file lain, dan mengunggah dalam kasus ini?
Jawaban:
Untuk menjawab pertanyaan Anda secara terpisah untuk
git
2.24.1 di Linux 4.19.95:Anda tidak melihat
IN_MODIFY
/IN_CLOSE_WRITE
acara karenagit clone
akan selalu mencoba menggunakan tautan keras untuk file di bawah.git/objects
direktori. Ketika kloning melalui jaringan atau melintasi batas-batas sistem file, peristiwa ini akan muncul lagi.Untuk mengetahui modifikasi tautan keras, Anda harus mengatur handler untuk
CREATE
acara inotify yang mengikuti dan melacak tautan tersebut. Harap dicatat bahwa yang sederhanaCREATE
juga dapat berarti bahwa file yang kosong dibuat. Kemudian, padaIN_MODIFY
/IN_CLOSE_WRITE
ke salah satu file Anda harus memicu tindakan yang sama pada semua file yang terhubung juga. Jelas Anda juga harus menghapus hubungan itu diDELETE
acara tersebut.Pendekatan yang lebih sederhana dan lebih kuat mungkin hanya dengan hash semua file secara berkala dan memeriksa apakah konten file telah berubah.
Koreksi
Setelah memeriksa
git
kode sumber erat dan berjalangit
denganstrace
, saya menemukan bahwagit
memang menggunakan file yang dipetakan memori, tetapi sebagian besar untuk membaca konten. Lihat penggunaanxmmap
yang selalu dipanggil denganPROT_READ
saja. . Karenanya jawaban saya sebelumnya di bawah BUKAN jawaban yang benar. Namun demikian untuk tujuan informasi saya masih ingin menyimpannya di sini:Anda tidak melihat
IN_MODIFY
acara karenapackfile.c
digunakanmmap
untuk akses file daninotify
tidak melaporkan modifikasi untukmmap
file ed.Dari halaman manual inotify :
sumber
IN_CLOSE_WRITE
, yang menurut saya masih akan terpicu ketika menutup file yang ditulis untuk digunakanmmap
, karena file tersebut harus dibuka dalam mode tulis?mmap
file hal-hal bisa mendapatkan sedikit rusak. Misalnya, Anda masih dapat menulis ke deskriptor file tertutup saat file dipetakan ke dalam memori.CLOSE_WRITE_CLOSE
bahkan jika saya menghapusclose
danmunmap
pada akhirnya. Harus menggali lebih dalam implementasi git yang sebenarnya ..inotifywait
dangit clone
(2.24.1) saya mendapatkanOPEN
->CLOSE_NOWRITE,CLOSE
untuk*.idx
file. Mungkin Anda lupa mengatur handlerCLOSE_NOWRITE,CLOSE
? Catatan: Anda akan mendapatkan*NOWRITE*
karena semua penulisan terjadi melalui memori yang dipetakan.CLOSE_NOWRITE
: masalahnya adalah saya tidak melihatIN_CLOSE_WRITE
, dan saya ingin menanggapi file "perubahan" untuk memicu unggahan, tetapi abaikan file "baca". Catatan, saya benar-benar berpikir saat ini keterbatasan mmap + inotify sedikit herring merah. Saya pikir masalahnya adalah bahwa.pack
/.idx
file pada awalnya dibuat sebagai tautan keras ke file lain, dan hanya memicuIN_CREATE
(danOPEN
->CLOSE_NOWRITE
terjadi kemudian ketika git benar-benar membaca file).Saya dapat berspekulasi bahwa Git sebagian besar waktu menggunakan pembaruan file atom yang dilakukan seperti ini:
mktemp
-style).rename(2)
d-d lebih dari yang asli; operasi ini menjamin bahwa setiap pengamat yang mencoba membuka file menggunakan namanya akan mendapatkan konten lama atau baru.Pembaruan seperti itu dilihat
inotify(7)
sebagaimoved_to
peristiwa — karena file "muncul kembali" dalam direktori.sumber
IN_MOVED_FROM
danIN_MOVED_TO
acara. Namun, saya tidak melihat ini terjadi untuk.pack
dan.idx
fileBerdasarkan jawaban yang diterima ini, saya berasumsi mungkin ada beberapa perbedaan dalam peristiwa berdasarkan protokol yang digunakan (yaitu ssh atau https).
Apakah Anda mengamati perilaku yang sama saat memantau kloning dari sistem file lokal dengan
--no-hardlinks
opsi?Perilaku Anda yang diamati saat menjalankan percobaan pada linux dan host Mac mungkin menghilangkan masalah terbuka ini sebagai penyebab https://github.com/docker/for-mac/issues/896 tetapi menambahkan hanya memetikan.
sumber
Ada kemungkinan lain (dari laki-laki tidak tahu):
Dan sementara
git clone
dapat menghasilkan aliran acara besar, ini bisa terjadi.Bagaimana cara menghindari ini:
sumber
Mungkin Anda membuat kesalahan yang sama yang saya buat bertahun-tahun yang lalu. Saya hanya menggunakan dua kali inotify. Pertama kali, kode saya hanya berfungsi. Kemudian, saya tidak lagi memiliki sumber itu dan mulai lagi, tetapi kali ini, saya kehilangan acara dan tidak tahu mengapa.
Ternyata ketika saya membaca sebuah acara, saya benar-benar membaca sekumpulan kecil acara. Saya parsing yang saya harapkan, berpikir itu saja, itu saja. Akhirnya, saya menemukan ada lebih banyak data yang diterima, dan ketika saya menambahkan sedikit kode untuk mem-parsing semua peristiwa yang diterima dari satu pembacaan, tidak ada lagi peristiwa yang hilang.
sumber