ईनोट घटनाओं को मिस करना


11

मैं इनॉटिफाई इवेंट्स का उपयोग करके बदलावों के लिए फाइलें देख रहा हूं (जैसा कि यह होता है, पायथन से, लिबाक में कॉलिंग)।

एक के दौरान कुछ फ़ाइलों के लिए git clone, मुझे कुछ विषम दिखाई देता है: मुझे एक IN_CREATEघटना दिखाई देती है , और मैं देखता हूं lsकि फ़ाइल में सामग्री है, हालांकि, मैं कभी नहीं देखता IN_MODIFYया IN_CLOSE_WRITE। यह मेरे लिए समस्याएँ पैदा कर रहा है क्योंकि मैं IN_CLOSE_WRITEफ़ाइलों पर प्रतिक्रिया देना चाहूंगा : विशेष रूप से, फ़ाइल सामग्री के अपलोड को आरंभ करने के लिए।

अजीब तरह से व्यवहार करने वाली फाइलें .git/objects/packनिर्देशिका में हैं, और वे अंत में .packया .idx। अन्य फाइलें जो गिट बनाती हैं, वे अधिक नियमित होती हैं IN_CREATE-> IN_MODIFY-> IN_CLOSE_WRITEश्रृंखला (मैं IN_OPENघटनाओं के लिए नहीं देख रही हूं )।

यह मैकओएस पर डॉकटर के अंदर है, लेकिन मैंने रिमोट सिस्टम में लिनक्स पर डॉकटर पर उसी का सबूत देखा है, इसलिए मेरा संदेह मैकओएस पहलू प्रासंगिक नहीं है। अगर देख रहे हैं और मैं इस देख रहा हूँ git cloneमें हैं एक ही डोकर कंटेनर।

मेरे सवाल:

  • ये फाइलें इन घटनाओं को क्यों याद कर रही हैं?

  • इस विषय में क्या किया जा सकता है? विशेष रूप से, मैं इन फ़ाइलों को लिखने के पूरा होने पर कैसे प्रतिक्रिया दे सकता हूं? नोट: आदर्श रूप से मैं जवाब देना चाहूंगा जब लेखन "समाप्त" होता है तो अनावश्यक रूप से बचने के लिए "(गलत तरीके से)" अधूरा "लेखन अपलोड करना।


संपादित करें: https://developer.ibm.com/tutorials/l-inotify/ पढ़ना ऐसा लग रहा है कि मैं जो देख रहा हूं वह संगत है

  • नाम के साथ एक अलग अस्थायी फ़ाइल, tmp_pack_hBV4Alzबनाई जा रही है, संशोधित और, बंद;
  • इस फ़ाइल के लिए एक हार्ड लिंक बनाया गया है, अंतिम .packनाम के साथ;
  • मूल tmp_pack_hBV4Alzनाम हटा दिया गया है।

मुझे लगता है कि मेरी समस्या, जो फ़ाइलों को अपलोड करने के लिए एक ट्रिगर के रूप में उपयोग करने की कोशिश कर रही है, फिर यह नोट करना कम कर देता है कि .packफ़ाइल किसी अन्य फ़ाइल की कड़ी है, और इस मामले में अपलोड हो रही है?


इसका जवाब यहाँ कहीं हो सकता है ...
कोरोबा

@choroba आप सही हो सकते हैं ... मैं बहुत सारे संदर्भ देख रहा हूं, और मिमीोट फाइलों में
मिमीप

1
BTW मूल समस्या क्या है जिसे आप हल करने की कोशिश कर रहे हैं (inotify के साथ)? हो सकता है कि कुछ और अधिक मजबूत समाधान मौजूद हों जो दूसरे अनुमान लगाने की कोशिश कर रहे हों कि एक Git प्रक्रिया क्या कर रही है / एक रिपॉजिटरी ने की है?
कोस्टिक्स

@kostix यह github.com/uktrade/mobius3 का हिस्सा है , AWS फारगेट में JupyterLab या RStudio से चलने वाले कंटेनरों से उपयोगकर्ताओं के होम फ़ोल्डर्स को सिंक करना, और S3 से, और उन होम पेज में .git फ़ोल्डर्स हो सकते हैं। मुझे पता है कि inotify समाधान कभी भी "मजबूत-मजबूत" नहीं होगा ... लेकिन मुझे उम्मीद है कि यह "पर्याप्त मजबूत" हो सकता है।
मिशैल चार्मेज़ा

1
@tink ऐसा लगता है कि स्वीकृत उत्तर लिनक्स कर्नेल पर एक पैच है? यह सामान्य रूप से मुझे संदेह होगा, लेकिन फ़रगेट पर मेरे मामले में मेरा नियंत्रण नहीं है। (और मैं स्वीकार करता हूं कि मुझे लंबे समय में एक पैच कर्नेल पर निर्भर रहने का थोड़ा डर है, भले ही मेरे पास वह शक्ति हो ...)
मिशाल चार्मेज़ा

जवाबों:


5

gitलिनक्स 4.19.95 पर 2.24.1 के लिए अलग से अपने प्रश्न का उत्तर देने के लिए :

  • ये फाइलें इन घटनाओं को क्यों याद कर रही हैं?

आप IN_MODIFY/ IN_CLOSE_WRITEईवेंट नहीं देखते हैं क्योंकि निर्देशिका के git cloneअंतर्गत फ़ाइलों के लिए हमेशा हार्ड लिंक का उपयोग करने का प्रयास करेंगे .git/objects। नेटवर्क या फ़ाइल सिस्टम सीमाओं पर क्लोनिंग करते समय, ये ईवेंट फिर से दिखाई देंगे।

  • इस विषय में क्या किया जा सकता है? विशेष रूप से, मैं इन फ़ाइलों को लिखने के पूरा होने पर कैसे प्रतिक्रिया दे सकता हूं? नोट: आदर्श रूप से मैं जवाब देना चाहूंगा जब लेखन "समाप्त" होता है तो अनावश्यक रूप से बचने के लिए "(गलत तरीके से)" अधूरा "लेखन अपलोड करना।

हार्ड लिंक के संशोधन को पकड़ने के लिए आपको इनॉटिफाई CREATEइवेंट के लिए एक हैंडलर सेट करना होगा जो उन लिंक का अनुसरण करता है और उन पर नज़र रखता है। कृपया ध्यान दें कि एक साधारण CREATEका अर्थ यह भी हो सकता है कि एक गैर-रिक्त फ़ाइल बनाई गई थी। फिर, किसी भी फाइल पर IN_MODIFY/ पर IN_CLOSE_WRITEआपको सभी लिंक की गई फ़ाइलों पर समान क्रिया को ट्रिगर करना होगा। जाहिर है कि आपको उस रिश्ते को DELETEघटना पर भी उतारना होगा।

एक सरल और अधिक मजबूत दृष्टिकोण शायद समय-समय पर सभी फाइलों को हैश करना होगा और जांचें कि क्या किसी फाइल की सामग्री बदल गई है।


भूल सुधार

gitस्रोत कोड को बारीकी से जांचने और उसके gitसाथ चलने के बाद strace, मैंने पाया कि gitमेमोरी मैप्ड फ़ाइलों का उपयोग करता है, लेकिन ज्यादातर सामग्री पढ़ने के लिए। उपयोग देखें xmmapजिसे PROT_READकेवल हमेशा कहा जाता है । । इसलिए नीचे अपने पिछले जवाब है नहीं सही जवाब। फिर भी जानकारी के उद्देश्य से मैं इसे यहां रखना चाहूंगा:

  • आप फ़ाइल एक्सेस के लिए उपयोग नहीं करते हैं और ईडी फ़ाइलों के लिए संशोधनों की रिपोर्ट नहीं करते हैं IN_MODIFYक्योंकि आप घटनाओं को नहीं देखते हैं ।packfile.cmmapinotifymmap

    से inotify मैनपेज :

    Inotify API फ़ाइल एक्सेस और संशोधनों की रिपोर्ट नहीं करता है जो mmap (2), msync (2), और munmap (2) के कारण हो सकते हैं।


मेरे परिवर्तन का पता लगाने का तंत्र निर्भर करता है IN_CLOSE_WRITE, जो मुझे लगता है कि अभी भी एक फ़ाइल को बंद करने के दौरान ट्रिगर किया जाएगा जिसे उपयोग करने के लिए लिखा गया था mmap, क्योंकि फ़ाइल को एक लेखन मोड में खोला जाना चाहिए था?
मिशाल चर्मेज़ा

मुझे इसकी जांच करनी है, लेकिन मुझे संदेह होगा कि एक मेमोरी मैप की गई फ़ाइल किसी भी इनोटिफ़ाइ इवेंट को ट्रिगर नहीं करती है। अधिकांश इंफ़ेक्ट इवेंट फ़ाइल डिस्क्रिप्टर की एक स्थिति से जुड़े होते हैं, लेकिन जब आप mmapफ़ाइल चीज़ों को ऑर्डर से थोड़ा बाहर निकाल सकते हैं। उदाहरण के लिए, आप अभी भी बंद फ़ाइल डिस्क्रिप्टर पर लिख सकते हैं जब आपके पास फ़ाइल को स्मृति में मैप किया गया हो।
Ente

स्क्रैच कि, मैं सिर्फ इस उदाहरण के कार्यान्वयन का परीक्षण किया और मैं एक CLOSE_WRITE_CLOSEभी मिलता है अगर मैं closeऔर munmapअंत में हटा दें । वास्तविक गिट कार्यान्वयन में गहरी खुदाई करनी है ..
Ente

हम्म मैं आपके मुद्दे को दोहराने के लिए थोड़ा संघर्ष कर रहा हूं। inotifywaitऔर git clone(2.24.1) के साथ मेरे परीक्षणों में मुझे फाइलों के लिए एक OPEN-> मिलता है । शायद आप के लिए एक हैंडलर स्थापित करना भूल गए ? नोट: आपको एक कारण मिलेगा क्योंकि सभी लेखन मेमोरी मैप के माध्यम से हुए हैं। CLOSE_NOWRITE,CLOSE*.idxCLOSE_NOWRITE,CLOSE*NOWRITE*
Ente

हाँ, वहाँ हैं CLOSE_NOWRITE: मुद्दा यह है कि मैं नहीं देख IN_CLOSE_WRITEरहा हूं, और मैं अपलोड को ट्रिगर करने के लिए "परिवर्तन" फ़ाइल का जवाब देना चाहूंगा, लेकिन फ़ाइल "रीड्स" को अनदेखा करें। ध्यान दें, मैं वास्तव में लगता है कि अभी mmap + inotify सीमा एक लाल-हेरिंग का एक सा है। मुझे लगता है कि मुद्दा यह है कि .pack/ .idxफ़ाइलें शुरू में किसी अन्य फ़ाइल के लिए हार्ड लिंक के रूप में बनाई जाती हैं, और इसलिए केवल ट्रिगर IN_CREATE(और OPEN-> CLOSE_NOWRITEबाद में होता है जब गिट वास्तव में फाइलों को पढ़ रहा होता है)।
मिशैल चर्मजा

2

मैं अनुमान लगा सकता हूं कि Git अधिकांश समय परमाणु फ़ाइल अपडेट का उपयोग करता है जो इस तरह से किए जाते हैं:

  1. एक फ़ाइल की सामग्री को मेमोरी (और संशोधित) में पढ़ा जाता है।
  2. संशोधित सामग्री एक अलग फ़ाइल में लिखी जाती है (आमतौर पर मूल एक के रूप में एक ही निर्देशिका में स्थित होती है, और एक यादृच्छिक ( mktemp-स्टाइल) नाम होता है।
  3. नई फ़ाइल तब rename(2)मूल d पर d -d होती है; यह ऑपरेशन गारंटी देता है कि हर पर्यवेक्षक अपने नाम का उपयोग करके फ़ाइल को खोलने की कोशिश कर रहा है या तो पुरानी सामग्री या नया मिलेगा।

इस तरह के अपडेट inotify(7)को moved_toघटनाओं के रूप में देखा जाता है - चूंकि एक निर्देशिका में एक फ़ाइल "पुन: प्रकट" होती है।


आह कुछ फ़ाइलों के लिए मुझे लगता है कि यह ऐसा करता है: मैं विभिन्न IN_MOVED_FROMऔर IN_MOVED_TOघटनाओं को देखता हूं । हालाँकि, मैं इसे .packऔर .idxफाइलों के लिए नहीं देख रहा हूँ
मिशाल चार्मेज़ा

पैक फाइलें बहुत बड़ी हो सकती हैं (कई गीगाबाइट्स, 2GiB तक कम से कम, मैं beleive); परमाणु अद्यतनों का उपयोग करके उन्हें उपज देना भंडारण की जगह पर निषेध हो सकता है, इसलिए उन्हें कुछ अन्य रणनीति का उपयोग करके अद्यतन किया जा सकता है।
कोस्टिक्स

2

इस स्वीकार किए गए उत्तर के आधार पर, मुझे लगता है कि इस्तेमाल किए जा रहे प्रोटोकॉल (यानी ssh या https) के आधार पर घटनाओं में कुछ अंतर हो सकता है।

क्या आप --no-hardlinksविकल्प के साथ स्थानीय फाइल सिस्टम से क्लोनिंग की निगरानी करते समय समान व्यवहार का निरीक्षण करते हैं ?

$ git clone git@github.com:user/repo.git
# set up watcher for new dir
$ git clone --no-hardlinks repo new-repo

लाइनक्स और मैक होस्ट दोनों पर प्रयोग चलाने पर आपका मनाया गया व्यवहार संभवत: इस खुले मुद्दे को खत्म करता है क्योंकि इसका कारण https://github.com/docker/for-mac/issues/896 है, लेकिन सिर्फ इन्सेक्ट जोड़ना।


2

एक और संभावना है (आदमी inotify से):

ध्यान दें कि घटना कतार अतिप्रवाह कर सकती है। इस मामले में, घटनाएं खो जाती हैं। मजबूत अनुप्रयोगों को खोई हुई घटनाओं की संभावना को इनायत से संभालना चाहिए। उदाहरण के लिए, भाग या सभी एप्लिकेशन कैश को फिर से बनाना आवश्यक हो सकता है। (एक सरल, लेकिन संभवतः महंगा है, दृष्टिकोण फ़ाइल डिस्क्रिप्टर को बंद करने के लिए है, कैशे खाली करें, एक नई इनोटिफ़ाइड फ़ाइल डिस्क्रिप्टर बनाएँ, और फिर निगरानी के लिए ऑब्जेक्ट्स के लिए घड़ियों और कैश प्रविष्टियों को फिर से बनाएँ।)

और जबकि git cloneभारी घटना प्रवाह उत्पन्न कर सकता है, यह हो सकता है।

इससे कैसे बचें:

  1. रीड बफ़र बढ़ाएं, fcntl (F_SETPIPE_SZ) आज़माएं (यह दृष्टिकोण एक अनुमान है, मैंने कभी कोशिश नहीं की है)।
  2. समर्पित थ्रेड में बड़े बफर में घटनाओं को पढ़ें, दूसरे धागे में घटनाओं को संसाधित करें।

2

हो सकता है आपने वही गलती की हो जो मैंने सालों पहले की थी। मैंने केवल दो बार Inotify का उपयोग किया है। पहली बार, मेरे कोड ने बस काम किया। बाद में, मेरे पास अब वह स्रोत नहीं था और फिर से शुरू हुआ, लेकिन इस बार, मैं घटनाओं को याद कर रहा था और पता नहीं क्यों।

यह पता चला है कि जब मैं एक घटना पढ़ रहा था, तो मैं वास्तव में घटनाओं के एक छोटे से बैच को पढ़ रहा था। मैंने जो उम्मीद की थी, वह सोचकर ही उसे छोड़ दिया। आखिरकार, मुझे पता चला कि प्राप्त आंकड़ों में और भी बहुत कुछ है, और जब मैंने एक एकल रीड से प्राप्त सभी घटनाओं को पार्स करने के लिए एक छोटा कोड जोड़ा, तो कोई और घटना नहीं हुई।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.