विशेष फ़ाइल जो I / O त्रुटि का कारण बनती है


13

मैं स्वचालित रूप से परीक्षण करना चाहता हूं कि क्या सॉफ़्टवेयर का एक टुकड़ा अपेक्षित रूप से प्रतिक्रिया करता है यदि एक आवश्यक SQLite DB फ़ाइल को पढ़ने में विफल रहता है (I / I त्रुटि के कारण)। कुछ दिनों पहले एक ग्राहक के साथ हुआ था। हमने इसे मैन्युअल रूप से तय किया था, लेकिन अब मैं इसे ठीक करने के लिए स्वचालित कोड बनाना चाहता हूं और परीक्षण करने के लिए टूटी हुई फ़ाइल तक पहुंच की आवश्यकता है।

यूनिक्स की एक फ़ाइल में सब कुछ के रूप में, मुझे संदेह था कि एक विशेष फ़ाइल हो सकती है जो हमेशा I / O त्रुटियों का कारण बनती है जब कोई इसे पढ़ने की कोशिश करता है (जैसे / in / dev)।

कुछ समान फाइलें (imo) होंगी:

  • /dev/full यदि आप हमेशा यह कहते हैं कि "डिवाइस पर कोई जगह नहीं बची है" यदि आप इसे लिखने की कोशिश करते हैं
  • /dev/null तथा /dev/zero

इसलिए मैंने मान लिया कि बस एक फाइल की तरह है (लेकिन अभी तक नहीं मिला है)।

क्या किसी को वांछित परिणाम (जानबूझकर दोषपूर्ण विभाजन छवि, खुले के आसपास एक आवरण) (LD_PRELOAD, ... का उपयोग करके) प्राप्त करने के लिए इस तरह की फ़ाइल या किसी अन्य विधि के बारे में पता है?
यहां जाने का सबसे अच्छा तरीका क्या है?


जहां तक ​​मुझे पता है, लिनक्स पर कोई विशेष फाइल नहीं है जो आपको पढ़ने से SIGIO देता है। पिछली बार मुझे एक SIGIO मिला था क्योंकि एक USB स्टिक थी जो वास्तविक, भौतिक एक की तुलना में बहुत बड़ी क्षमता की घोषणा करती थी। शायद यह एक संभावना हो सकती है?
lgeorget

हम्म, मैं एक छोटे से विभाजन की छवि के साथ कोशिश कर सकता हूँ कि मैं बीच में कहीं फसल
लूंगा

SIGIO का मतलब यह नहीं है कि कोई त्रुटि हुई है, यह एक तरीका है कि कोई कार्यक्रम यह सूचित करने का अनुरोध कर सकता है कि चयन () या पोल () को कॉल करने के बजाय गैर अवरुद्ध IO अब संभव है।
psusi

अप, हाँ, आप सही हैं, बिल्कुल। मैंने SIGIO लिखा था लेकिन EIO त्रुटि कोड के बारे में सोच रहा था। लेकिन शायद ओपी भी? एक SIGIO को पढ़ने में असफलता क्यों मिलेगी?
लार्जेट

ओह, मैंने प्रश्न में वही गलती की ... संपादित किया ...
mreithub

जवाबों:


8

आप विफलताओं का अनुकरण करने के dmsetupलिए errorया तो flakeyलक्ष्य का उपयोग करके डिवाइस-मैपर डिवाइस बनाने के लिए उपयोग कर सकते हैं ।

dmsetup create test --table '0 123 flakey 1 0 /dev/loop0'

जहां 123 डिवाइस की लंबाई है, सेक्टरों में और / dev / loop0 मूल डिवाइस है जिस पर आप त्रुटियों को अनुकरण करना चाहते हैं। त्रुटि के लिए, आपको बाद के तर्कों की आवश्यकता नहीं है क्योंकि यह हमेशा एक त्रुटि देता है।


1
मुझे उस कमांड में कम से कम दो त्रुटियां मिलती हैं: लापता डिवाइस का नाम, कोटिंग टाइपो, और "1 0 / dev / null" का क्या अर्थ है?
हौके लैजिंग

@HaLLaging, आह, हाँ, मैंने नाम छोड़ दिया और किसी तरह गलत उद्धरण मारा। 1 0 / dev / null का अर्थ है 1 लक्ष्य, ऑफसेट 0 पर शुरू, डिवाइस / देव / नल द्वारा समर्थित। यह परतदार के लिए आवश्यक है, लेकिन स्पष्ट रूप से त्रुटि के लिए वैकल्पिक है।
Psusi

यह मुझे लगता है कि यह "वैकल्पिक" नहीं है, लेकिन इसे अनदेखा किया गया है। आप के साथ जाँच कर सकते हैं dmsetup table test। तुम foo barपीछे भी लिख सकते हो error; यह सिर्फ परवाह नहीं करता है (और इस तरह हटा दिया जाना चाहिए)।
हौके लैजिंग

@ हॉकिंग, संपादित
psusi

जवाब के लिए धन्यवाद, मुझे लगता है कि अब मैं जिस तरह से जाऊंगा। मेरे पास एकमात्र मामूली मुद्दा यह है कि इसके लिए रूट एक्सेस की आवश्यकता है, लेकिन मुझे लगता है कि आपको वैसे भी या इस तरह के लोवेल सामान की आवश्यकता होगी ... (जब मेरे पास समय होगा तो मैं LD_PRELOAD विचार में खुदाई करूँगा)।
मेरीथूब

14

स्टैक ओवरफ्लो और सर्वर फाल्ट पर इसके जवाब का एक बड़ा सेट पहले से ही है लेकिन कुछ तकनीकें गायब थीं। जीवन को आसान बनाने के लिए यहाँ VM / Linux ब्लॉक डिवाइस / लिनक्स फाइल सिस्टम / लिनक्स यूजरस्पेस लाइब्रेरी I / O फॉल्ट इंजेक्शन तंत्रों की सूची दी गई है:

बोनस तथ्य: SQLite में त्रुटियों का अनुकरण करने के लिए VFS ड्राइवर है, ताकि इसे अच्छा परीक्षण कवरेज मिल सके।

सम्बंधित:


5

आप I / O के लिए एक दोष इंजेक्शन तंत्र चाहते हैं ।

लिनक्स पर, यहां एक विधि है जिसके लिए किसी भी पूर्व सेटअप की आवश्यकता नहीं है और एक असामान्य त्रुटि उत्पन्न करता है (EIO "इनपुट / आउटपुट त्रुटि नहीं" लेकिन ESRCH "ऐसी कोई प्रक्रिया नहीं"):

cat /proc/1234/mem

जहां 1234 एक प्रक्रिया का PID है, जो उसी उपयोगकर्ता के रूप में चल रही है जिस प्रक्रिया का आप परीक्षण कर रहे हैं, लेकिन वह प्रक्रिया स्वयं नहीं है। रबासोव को सोचने का श्रेय /proc/$pid/mem

यदि आप प्रक्रिया के पीआईडी ​​का उपयोग करते हैं, तो आपको ईआईओ मिलता है, लेकिन केवल तब जब आप उस क्षेत्र से पढ़ रहे हों जो प्रक्रिया की मेमोरी में मैप नहीं किया गया है। पहला पृष्ठ कभी मैप नहीं किया जाता है, इसलिए यदि आप फ़ाइल को क्रमिक रूप से पढ़ते हैं, तो यह ठीक है, लेकिन एक डेटाबेस प्रक्रिया के लिए उपयुक्त नहीं है जो सीधे फ़ाइल के मध्य में दिखती है।

रूट के रूप में कुछ और सेटअप के साथ, आप वैध क्षेत्रों और खराब क्षेत्रों के साथ फाइल बनाने के लिए डिवाइस मैपर का लाभ उठा सकते हैं ।

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

फिर भी एक अन्य विधि एक LD_PRELOADआवरण है। एक मौजूदा एक लिबफ्यू (यूजरस्पेस में दोष इंजेक्शन) है। यह एक लाइब्रेरी को प्री लोड करके काम करता है जो POSIX API कॉल को ओवरलोड करता है। आप सामान्य व्यवहार को ओवरराइड करने के लिए सरल निर्देश या मनमाना सी कोड लिख सकते हैं।


लिबफ्यू वास्तव में आशाजनक लग रहा है (और यह डेबियन रिपोज में है)। शानदार जवाब, धन्यवाद, +1
mreithub

1

यदि डिवाइस डिवाइस को "I / O त्रुटियों वाली फाइल" के रूप में उपयोग करना ठीक है, तो समाधान बहुत आसान है। मेरा प्रस्ताव उन मामलों के लिए है जहां एक नियमित फ़ाइल में ऐसी त्रुटियां होंगी।

> dd if=/dev/zero of=/path/to/ext2.img bs=10M count=10
> losetup /dev/loop0 /path/to/ext2.img
> blockdev --getsz /dev/loop0
204800
> echo "0 204800 linear /dev/loop0 0" | dmsetup create sane_dev
> mke2fs /dev/mapper/sane_dev # ext2 reicht
> mount -t ext2 /dev/mapper/sane_dev /some/where
> dd if=/dev/zero of=/some/where/unreadable_file bs=512 count=4
> hdparm --fibmap /some/where/unreadable_file
/mnt/tmp/unreadable_file:
 filesystem blocksize 1024, begins at LBA 0; assuming 512 byte sectors.
 byte_offset  begin_LBA    end_LBA    sectors
           0       2050       2053          4
> umount /dev/mapper/sane_dev
> dmsetup remove sane_dev
> start_sector=$((204800-2053-1))
> echo $'0 2053 linear /dev/loop0 0\n2053 1 error\n2054 '"${start_sector} linear /dev/loop0 2054" | 
>   dmsetup create error_dev
> mount -t ext2 /dev/mapper/error_dev /some/where
> cat /some/where/unreadable_file # 3rd sector of file is unreadable
cat: /some/where/unreadable_file: Input/output error

मुझे यह स्वीकार करना चाहिए कि मैं थोड़ा उलझन में हूँ क्योंकि मैंने उस फ़ाइल से एक त्रुटि के साथ एकल क्षेत्रों को पढ़ने में कामयाब नहीं किया है dd .. seek=...। हो सकता है कि यह एक आगे की समस्या है।


आपके फाइलसिस्टम के ब्लॉक कम से कम 4096 बाइट्स के आकार के हैं, इसलिए वे फाइल को छोटा होने पर भी कई सेक्टरों में फैलाएंगे।
आयन

1

आप CharybdeFS का उपयोग कर सकते हैं जो इस तरह के उद्देश्य के लिए बिल्कुल बनाया गया था।

यह PetardFS की तरह एक पैशाच फ्यूज फाइल सिस्टम है, लेकिन बहुत अधिक विन्यास योग्य है।

CharybdeFS रसोई की किताब यहाँ देखें: http://www.scylladb.com/2016/05/02/fault-injection-filesystem-cookbook/

यह एक डेटाबेस का परीक्षण करने के लिए पर्याप्त उन्नत है।


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