ऐसे प्रोग्राम जो असफल फ़ाइल स्थानांतरण को फिर से शुरू कर सकते हैं, उन्हें पता है कि कहां से डेटा जोड़ना शुरू करना है?


23

कुछ फाइल कॉपी करने वाले प्रोग्राम जैसे rsyncऔर curlफेल ट्रांसफर / कॉपी फिर से शुरू करने की क्षमता रखते हैं।

यह देखते हुए कि इन विफलताओं के कई कारण हो सकते हैं, कुछ मामलों में कार्यक्रम "क्लीनअप" कर सकता है कुछ कार्यक्रम जो नहीं कर सकते हैं।

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

उदाहरण के लिए, फ़ाइल के टुकड़े का आकार जो "गंतव्य पर बना है" 1378 बाइट्स है, इसलिए वे मूल पर बाइट 1379 से पढ़ना शुरू करते हैं और टुकड़े में जोड़ते हैं।

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

गंतव्य फ़ाइल को लिखते समय किसी तरह का बफ़रिंग या "ट्रांज़ेक्शन" SQL डेटाबेस के समान होता है, या तो प्रोग्राम में, कर्नेल या फाइलसिस्टम स्तर पर यह सुनिश्चित करने के लिए कि केवल साफ, अच्छी तरह से बनाई गई बाइट्स इसे अंतर्निहित ब्लॉक डिवाइस में बनाती हैं?
या क्या कार्यक्रम मान लेते हैं कि नवीनतम बाइट संभावित रूप से अधूरी होगी, इसलिए वे इसे अपनी खराब धारणा पर हटाते हैं, बाइट को फिर से याद करते हैं और वहां से एपिंग शुरू करते हैं?

यह जानते हुए कि सभी डेटा बाइट्स के रूप में नहीं दिखाए जाते हैं, ये अनुमान गलत लगते हैं।

जब ये कार्यक्रम "फिर से शुरू" करते हैं, तो उन्हें कैसे पता चलेगा कि वे सही जगह पर शुरू कर रहे हैं?


21
"सभी फ़ाइलों को साफ बाइट के आकार के टुकड़ों में खंडित नहीं किया गया है?" आप एक बाइट से कम किसी फ़ाइल में कैसे लिखते हैं?
मुरु

17
मुझे पता है कि कोई सिस्टम कॉल नहीं है जो बाइट से कम कुछ भी लिख सकता है, और डिस्क के रूप में, मुझे लगता है कि कोई डिस्क आज 512 बाइट ब्लॉक (या 4096 बाइट ब्लॉक) से कम नहीं लिखती है।
मुरु

8
नहीं, मैं कह रहा हूं कि न्यूनतम एक बाइट है। साने एप्लिकेशन 4KB या 8KB चंक्स का उपयोग कर रहे होंगे: head -c 20480 /dev/zero | strace -e write tee foo >/dev/nullऔर फिर OS उन्हें बफ़र करेगा और डिस्क को और भी बड़े चंक्स में भेजेगा।
मुरु

9
@the_velour_fog: आप केवल एक बिट के साथ कैसे लिखते हैं fwrite()?
psmears

9
सभी व्यावहारिक उद्देश्यों के लिए, डेटा बाइट्स से बना है और सब कुछ उनके साथ सबसे छोटी इकाई के रूप में संचालित होता है। कुछ सिस्टम (ज्यादातर संपीड़न से संबंधित है जैसे gzip, h264) बाइट्स से अलग-अलग बिट्स को अनपैक करें, लेकिन ऑपरेटिंग सिस्टम और मेमोरी ऑपरेशन बाइट्स के स्तर पर है।
pjc50

जवाबों:


40

स्पष्टता के लिए - वास्तविक यांत्रिकी बेहतर सुरक्षा देने के लिए अधिक जटिल है - आप इस तरह के राइट-टू-डिस्क की कल्पना कर सकते हैं:

  • आवेदन बाइट्स लिखता है (1)
  • कर्नेल (और / या फ़ाइल सिस्टम IOSS) उन्हें बफ़र करता है
  • एक बार बफर भर जाने के बाद, यह फाइल सिस्टम में फ्लश हो जाता है:
    • ब्लॉक आवंटित किया गया है (2)
    • ब्लॉक लिखा है (3)
    • फ़ाइल और ब्लॉक जानकारी अपडेट की गई है (4)

यदि प्रक्रिया (1) में बाधित हो जाती है, तो आपको डिस्क पर कुछ भी नहीं मिलता है, फ़ाइल पिछले ब्लॉक पर बरकरार और छंटनी होती है। आपने 5000 बाइट भेजे, केवल 4096 डिस्क पर हैं, आप ऑफसेट को 4096 पर फिर से शुरू करें।

यदि (2) पर, स्मृति में कुछ भी नहीं होता है। समान (१)। यदि (3) पर, डेटा लिखा है लेकिन किसी को इसके बारे में याद नहीं है । आपने 9000 बाइट भेजीं, 4096 लिखीं, 4096 लिखीं और खोईं , बाकी बस खो गईं। स्थानांतरण 4096 ऑफसेट पर फिर से शुरू।

यदि (4) पर, डेटा अब डिस्क पर प्रतिबद्ध होना चाहिए। धारा में अगले बाइट्स खो सकते हैं। आपने 9000 बाइट भेजीं, 8192 लिखीं, बाकी खो गई, ऑफसेट 8192 पर स्थानांतरण फिर से शुरू।

यह एक सरलीकृत टेक है। उदाहरण के लिए, 3-4 चरणों में प्रत्येक "तार्किक" लिखना "परमाणु" नहीं है, लेकिन एक और अनुक्रम को जन्म देता है (चलो इसे # 5 संख्या दें) जिससे ब्लॉक, उप-खंडों में गंतव्य डिवाइस के लिए उपयुक्त (जैसे हार्ड डिस्क) ) डिवाइस के मेजबान नियंत्रक के लिए भेजा जाता है, जिसमें एक कैशिंग तंत्र भी होता है , और अंत में चुंबकीय थाली पर संग्रहीत होता है। यह उप-अनुक्रम हमेशा पूरी तरह से सिस्टम के नियंत्रण में नहीं होता है, इसलिए हार्ड डिस्क पर डेटा भेजना कोई गारंटी नहीं है कि यह वास्तव में लिखा गया है और वापस पढ़ने योग्य होगा।

कई फ़ाइल सिस्टम जर्नलिंग को लागू करते हैं , यह सुनिश्चित करने के लिए कि सबसे कमजोर बिंदु, (4), वास्तव में असुरक्षित नहीं है, में मेटा-डेटा लिखकर, आपने अनुमान लगाया, लेनदेन जो कि चरण (5) में लगातार काम करेगा।

यदि सिस्टम लेन-देन के बीच में रीसेट हो जाता है, तो यह निकटतम बरकरार चेकपॉइंट के लिए अपना रास्ता फिर से शुरू कर सकता है। डेटा लिखा अभी भी खो गया है, केस (1) के समान है, लेकिन फिर से शुरू करने से उस पर ध्यान जाएगा। वास्तव में कोई जानकारी नहीं मिलती है


1
महान व्याख्या। यह सब समझ में आता है। इसलिए यदि कोई प्रक्रिया इसे (4) फ़ाइल ब्लॉक जानकारी को अद्यतन करने के लिए सभी रास्ते बनाती है, तो आप जानते हैं कि वे सभी बाइट अच्छे हैं। तब किसी भी बाइट्स जो किसी भी पिछले चरण में थे, या तो इसे डिस्क में नहीं बनाया है या - अगर उन्होंने किया - तो उन्हें "अन-याद" (उनके लिए कोई संदर्भ नहीं) होगा
the_velour_fog

4
@the_velour_fog और बस पारंगत पैराग्राफ को पूरक करने के लिए - यदि आप एक फ़ाइल सिस्टम का उपयोग कर रहे हैं जो जर्नलिंग को लागू नहीं करता है , तो आप वास्तव में "टूटा हुआ" डेटा प्राप्त कर सकते हैं, जिससे रिज्यूमे विफल हो सकता है और आपको त्रुटि दिए बिना एक विकृत फ़ाइल का उत्पादन कर सकता है। यह अतीत में हर समय होता था, खासकर उच्च-विलंबता उपकरणों (जैसे फ्लॉपी) के लिए डिज़ाइन किए गए फ़ाइल-सिस्टम के साथ। फ़ाइल-सिस्टम इस तरह विश्वसनीय नहीं था, तब भी इससे बचने के लिए कुछ तरकीबें थीं, लेकिन इसकी भरपाई के लिए एक चतुर अनुप्रयोग की आवश्यकता थी और कुछ मान्यताओं जो कि कुछ प्रणालियों पर गलत थीं।
16

यह उत्तर फाइल सिस्टम में जर्नलिंग की उपयोगिता को खत्म कर देता है। यह तब तक मज़बूती से काम नहीं करता है जब तक कि सब कुछ ट्रांसएक्शनल शब्दार्थों को लागू नहीं करता है , जिसमें यूज़रस्पेस एप्लिकेशन (थ्रू fsync) और हार्ड ड्राइव कंट्रोलर (अक्सर टूट जाता है, यहां तक ​​कि माना जाता है कि "एंटरप्राइज" ड्राइव भी शामिल है)। fsyncकई फ़ाइल संचालन के बिना , जो कि सहज रूप से आदेश दिए गए हैं और परमाणु को POSIX द्वारा इस तरह के होने की गारंटी नहीं है : फाइलें, O_APPENDआदि के बिना अलग-अलग व्यवहार कर सकते हैं के साथ खोला गया है । अभ्यास में फ़ाइल संगतता के लिए सबसे महत्वपूर्ण कुंजी कर्नेल VFS प्रणाली और डिस्क कैश हैं। बाकी सब कुछ ज्यादातर फुलाना है।
user1643723

11

नोट: मैंने इसके स्रोतों को नहीं देखा है rsync या किसी अन्य फ़ाइल स्थानांतरण उपयोगिता ।

यह एक सी प्रोग्राम लिखने के लिए तुच्छ है जो एक फ़ाइल के अंत में कूदता है और बाइट्स में उस स्थान की स्थिति प्राप्त करता है।

दोनों संचालन मानक सी लाइब्रेरी फ़ंक्शन के लिए एक कॉल के साथ किया जाता है lseek()( lseek(fd, 0, SEEK_END)फाइल डिस्क्रिप्टर के लिए खोली गई फ़ाइल की लंबाई देता है fd, बाइट्स में मापा जाता है)।

एक बार जब यह लक्ष्य फ़ाइल के लिए किया जाता है, lseek()तो उपयुक्त स्थिति पर जाने के लिए स्रोत फ़ाइल पर एक समान कॉल किया जा सकता है lseek(fd, pos, SEEK_SET):। तब हस्तांतरण उस बिंदु पर जारी रह सकता है, यह मानते हुए कि स्रोत फ़ाइल के पहले भाग को अपरिवर्तित के रूप में पहचाना गया है (विभिन्न उपयोगिताओं यह अलग-अलग तरीकों से हो सकता है)।

कोई फ़ाइल खंडित हो सकती है डिस्क पर , लेकिन फाइल सिस्टम यह सुनिश्चित करेगा कि कोई एप्लिकेशन फ़ाइल को बाइट्स के अनुक्रमिक अनुक्रम के रूप में मानता है।


बिट्स और बाइट्स के बारे में टिप्पणियों में चर्चा के बारे में: डेटा की सबसे छोटी इकाई जो डिस्क पर लिखी जा सकती है, वह एक बाइट है । एक एकल बाइट के लिए कम से कम एक ब्लॉक की आवश्यकता होती है डिस्क पर आवंटित किए जाने वाले डेटा के की । एक ब्लॉक का आकार फाइलसिस्टम के प्रकार पर निर्भर करता है और संभवत: फाइल सिस्टम को शुरू करते समय प्रशासक द्वारा उपयोग किए जाने वाले मापदंडों पर भी होता है, लेकिन यह आमतौर पर 512 बाइट्स और 4 केबी के बीच होता है। लिखें कार्रवाई को कर्नेल, अंतर्निहित सी लाइब्रेरी या एप्लिकेशन द्वारा ही बफर किया जा सकता है और डिस्क पर वास्तविक लेखन अनुकूलन के रूप में उपयुक्त ब्लॉक आकार के गुणकों में हो सकता है।

एकल बिट्स को किसी फ़ाइल में लिखना संभव नहीं है और यदि कोई लेखन ऑपरेशन विफल हो जाता है, तो यह फ़ाइल में "आधा-लिखित बाइट्स" नहीं छोड़ेगा।


धन्यवाद, तो यह क्या है जो यह सुनिश्चित करता है कि अगर एक लिखित ऑपरेशन विफल हो जाता है - यह आधे लिखित बाइट्स को नहीं छोड़ेगा? क्या यह कर्नेल बफरिंग मुरु का वर्णन था? - यानी यदि एक प्रक्रिया को कर्नेल को 8KB चंक भेजने के बीच में बाधित किया जाता है और अप्रत्याशित रूप से समाप्त कर दिया जाता है - कि 8KB का हिस्सा कभी भी कर्नेल तक नहीं पहुंचेगा - लेकिन कर्नेल और फाइलसिस्टम तक पहुंचने वाले किसी भी पिछले को अच्छा माना जा सकता है?
the_velour_fog

6
@the_velour_fog उस प्रकार की अनपेक्षित समाप्ति नहीं हो सकती है, क्योंकि I / O सिस्टम कॉल के बीच में यह प्रक्रिया अबाधित होगी (इसीलिए यह NFS फाइल के लिए फाइलसिस्टम एक्सेस कॉल पर अटूट प्रक्रिया को देखने के लिए असामान्य नहीं है)। इसे भी देखें: unix.stackexchange.com/q/62697/70524
muru

2
यदि सिस्टम गलत समय पर बिजली खो देता है, तो ऐसे मुद्दे हो सकते हैं। यह कभी-कभी किसी फ़ाइल के अंतिम लेखन बिंदु पर कचरे का परिणाम हो सकता है। यह डेटाबेस डिजाइन में एक बहुत मुश्किल समस्या है। लेकिन फिर भी सामान्य छोटी इकाई जो "वैध" या "अमान्य" है, एक डिस्क ब्लॉक है।
pjc50

1
@the_velour_fog यह इतना नहीं है जितना आप " आधा लिखित बाइट्स " प्राप्त नहीं कर सकते (या, अधिक सटीक, बाइट्स का एक आधा लिखित ब्लॉक ) एक आधे-लिखित ब्लॉक के रूप में दर्ज नहीं किया जाएगा जैसा कि लिखा गया है (इसकी संपूर्णता में) ) - लेसनरी के उत्तर के चरण (3) और (4) देखें ।
ट्रिपहाउंड

5

यह मूल रूप से दो प्रश्न हैं, क्योंकि कर्ल और rsync जैसे कार्यक्रम बहुत अलग हैं।

कर्ल जैसे HTTP क्लाइंट के लिए वे वर्तमान फ़ाइल के आकार की जांच करते हैं और फिर Content-Rangeउनके अनुरोध के साथ हेडर भेजते हैं। सर्वर या तो (सफ़लता 206) के बजाय स्टेटस कोड (आंशिक सामग्री) का उपयोग करके फ़ाइल की रेंज भेजना 200शुरू कर देता है और डाउनलोड फिर से शुरू हो जाता है या यह हेडर को अनदेखा करता है और शुरू से शुरू होता है और HTTP क्लाइंट के पास सब कुछ फिर से डाउनलोड करने के अलावा और कोई विकल्प नहीं है। फिर।

इसके अलावा सर्वर Content-Lengthहेडर भेज भी सकता है और नहीं भी । आपने देखा होगा कि कुछ डाउनलोड प्रतिशत और फाइल नहीं दिखा रहे हैं। ये वे डाउनलोड होते हैं जहां सर्वर क्लाइंट को लंबाई नहीं बताता है, इसलिए क्लाइंट को केवल डाउनलोड की गई राशि पता है, लेकिन कितने बाइट्स का पालन करेंगे।

एक का उपयोग करते हुए Content-Rangeशुरुआत के साथ शीर्ष लेख और स्टॉप स्थिति जो स्थानांतरण को गति करता है, तो अपने आप में प्रत्येक दर्पण अपने नेटवर्क कनेक्शन की तुलना में धीमी है एक बार में विभिन्न स्रोतों से एक फाइल डाउनलोड करने के लिए, कुछ डाउनलोड प्रबंधक द्वारा किया जाता है।

दूसरी ओर rsync वृद्धिशील फ़ाइल स्थानांतरण के लिए एक उन्नत प्रोटोकॉल है। यह सर्वर और क्लाइंट पक्ष पर फ़ाइल के कुछ हिस्सों का चेकसम उत्पन्न करता है ताकि यह पता लगाया जा सके कि कौन से बाइट समान हैं। तब यह केवल अंतर भेजता है। इसका मतलब यह है कि यह न केवल डाउनलोड को फिर से शुरू कर सकता है, बल्कि अगर आप फ़ाइल को फिर से डाउनलोड किए बिना एक बहुत बड़ी फ़ाइल के बीच में कुछ बाइट्स बदल दिया है, तो यह भी बदल बाइट्स डाउनलोड कर सकते हैं।

स्थानांतरण को फिर से शुरू करने के लिए बनाया गया एक और प्रोटोकॉल बिटोरेंट है, जहां .torrentफ़ाइल में ब्लॉक से ब्लॉक के लिए चेकसमों की एक सूची है, इसलिए ब्लॉक को मनमाने ढंग से क्रम में और विभिन्न स्रोतों से समानांतर में डाउनलोड और सत्यापित किया जा सकता है।

ध्यान दें कि rsync और बिटकोरेंट आपकी डिस्क पर आंशिक डेटा को सत्यापित करेगा, जबकि HTTP डाउनलोड फिर से शुरू नहीं होगा। इसलिए यदि आपको संदेह है कि आंशिक डेटा दूषित है तो आपको अखंडता की जांच करने की आवश्यकता है अन्यथा, अर्थात अंतिम फ़ाइल के चेकसम का उपयोग करना। लेकिन केवल डाउनलोड को बाधित करना या नेटवर्क कनेक्शन को खोना आमतौर पर आंशिक फ़ाइल को भ्रष्ट नहीं करता है जबकि हस्तांतरण के दौरान बिजली की विफलता हो सकती है।


4

टीएल; डीआर: वे नहीं कर सकते, जब तक कि वे जिस प्रोटोकॉल का उपयोग करते हैं वह इसके लिए अनुमति देता है।

प्रोग्राम हमेशा एक अनियंत्रित स्थान से फिर से शुरू नहीं कर सकते हैं: उदाहरण के लिए, HTTP अनुरोध केवल पुनरारंभ करने योग्य हैं यदि सर्वर इसका समर्थन करता है और क्लाइंट इसे लागू करता है: यह सार्वभौमिक नहीं है, इसलिए अपने प्रोग्राम के प्रलेखन की जांच करें। यदि सर्वर इसका समर्थन करता है, तो प्रोग्राम केवल प्रोटोकॉल के भाग के रूप में पूछकर स्थानांतरण को फिर से शुरू कर सकते हैं। आप आमतौर पर अपनी डाउनलोड निर्देशिका में आंशिक स्थानान्तरण देखेंगे (वे आमतौर पर ".partial" एक्सटेंशन या कुछ इसी तरह के रूप में चिह्नित होते हैं।)

यदि कोई फ़ाइल डाउनलोड रुका हुआ है या अन्यथा रुका हुआ है, तो क्लाइंट फ़ाइल को डिस्क पर लिख सकता है और निश्चित विचार कर सकता है कि कहां से फिर से शुरू करें। यदि, दूसरी ओर, क्लाइंट क्रैश हो जाता है या फ़ाइल में कोई त्रुटि लेखन होता है, तो क्लाइंट को यह मान लेना होगा कि फ़ाइल दूषित है और शुरू हो गई है। बिटटोरेंट कुछ हद तक फाइलों को "विखंडू" में तोड़कर और उन पर नज़र रखता है जिन्हें सफलतापूर्वक डाउनलोड किया गया है; सबसे अधिक है कि यह कभी कभी फिर से करना होगा कुछ हिस्सा है। Rsync कुछ ऐसा ही करता है।

प्रोग्राम कैसे जानते हैं कि सामग्री समान है? एक विधि यह सत्यापित करने के लिए है कि क्लाइंट और सर्वर के बीच कुछ पहचानकर्ता समान हैं। इसके कुछ उदाहरण टाइमस्टैम्प और आकार होंगे, लेकिन ऐसे तंत्र हैं जो एक प्रोटोकॉल के लिए विशिष्ट हो सकते हैं। यदि पहचानकर्ता मेल खाते हैं, तो ग्राहक मान सकता है कि फिर से शुरू करना काम करेगा।

यदि आप अधिक निश्चित सत्यापन चाहते हैं, तो HTTP और दोस्तों को आपकी पहली पसंद नहीं होना चाहिए। आप एक ऐसे प्रोटोकॉल का उपयोग करना चाहेंगे जिसमें पूरी फाइल के लिए एक चेकसम या हैश भी हो और प्रत्येक ट्रांस्फ़र्ड क्रंक हो ताकि आप डाउनलोड के चेकसम की तुलना सर्वर के कंप्यूटर चेकसम से कर सकें: जो कुछ भी मेल नहीं खाता है वह फिर से डाउनलोड हो जाएगा। फिर, बिटटोरेंट इस तरह के प्रोटोकॉल का एक उदाहरण है; rsync वैकल्पिक रूप से भी ऐसा कर सकता है।


rsync उदाहरण के लिए, यह सीधा होने वाला है क्योंकि केवल एक rsync प्रोटोकॉल है। http डाउनलोड के लिए, एक मानक के रूप में सीमा-अनुरोध है। मैं यह जानने के लिए उत्सुक हूं कि वास्तव में फिर से शुरू-अपलोड पर कर्ल क्या करता है, क्योंकि अपलोड का मानक शब्दार्थ मल्टीपर्ट / फॉर्म-डेटा (wget और कर्ल के लिए) है, लेकिन मुझे विश्वास नहीं है कि अपलोड फिर से शुरू होने वाले शब्दार्थ सार्वभौमिक रूप से सहमत हैं। उदाहरण के लिए YouTube और Nginx इसे अलग तरीके से कर सकते हैं।
Rob

1

हस्तांतरण करने के लिए उपयोग किए गए प्रोटोकॉल पर निर्भर करता है। लेकिन कर्ल http का उपयोग करता है और यह उस क्रम में डेटा को क्रमिक रूप से स्थानांतरित करता है जिसमें यह फ़ाइल में दिखाई देता है। इसलिए कर्ल आंशिक रूप से पूर्ण किए गए स्थानांतरण के फ़ाइल आकार के आधार पर फिर से शुरू हो सकता है। वास्तव में, आप इसे लंबाई N (किसी भी चीज़) की फ़ाइल बनाकर पहले N बाइट्स को छोड़ने के लिए ट्रिक कर सकते हैं और उस फ़ाइल को आंशिक रूप से पूर्ण डाउनलोड (और फिर पहले N बाइट्स को त्यागने) के रूप में मान सकते हैं।

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