G / Ç hatasına neden olan Özel Dosya


13

Temel bir SQLite DB dosyası okunamıyor (bir G / Ç hatasına neden olur) bir yazılım parçası beklendiği gibi tepki verirse otomatik olarak test etmek istiyorum. Tam olarak birkaç gün önce bir müşteriydi. Manuel olarak düzelttik, ancak şimdi düzeltmek için otomatik kod oluşturmak istiyorum ve bunu test etmek için bozuk bir dosyaya erişmem gerekiyor.

Unix'teki her şey bir dosya olduğundan, bir tanesi okumaya çalıştığında her zaman G / Ç hatalarına neden olan özel bir dosya olabileceğinden şüphelendim (örn. / Dev).

Bazı benzer dosyalar (imo) şöyle olur:

  • /dev/full Bu, yazmaya çalışırsanız her zaman "Cihazda yer kalmaz" yazıyor
  • /dev/null ve /dev/zero

bu yüzden böyle bir dosya olması gerektiğini varsaydım (ama henüz bir tane bulamadım).

Herkes böyle bir dosya veya istenen sonucu elde etmek için benim için başka bir yöntem biliyor mu (kasıtlı olarak hatalı bir bölüm görüntü, LD_PRELOAD kullanarak bir sarmalayıcı etrafında open), ...)?
Buraya gitmenin en iyi yolu nedir?


Bildiğim kadarıyla, Linux'ta okuduğunuzda SIGIO veren özel bir dosya yok. En son bir SIGIO'yu aldığımda, gerçek, fiziksel olandan çok daha büyük bir kapasite bildiren bir USB çubuğu vardı. Belki bu bir olasılık olabilir?
lgeorget

hmmm, ben ortada bir yerde
kırpacağım

SIGIO bir hata olduğu anlamına gelmez, bir programın select () veya poll () çağırmak yerine engellemeyen G / Ç'nin artık mümkün olduğu konusunda bilgilendirilmesini istemenin bir yoludur.
psusi

Ups, evet, haklısın elbette. SIGIO'yu yazdım ama EIO hata kodunu düşünüyordum. Ama belki OP de mi? Neden okuma yapılmazsa SIGIO verilir?
lgeorget

oh, aynı hatayı soruda yaptım ...
Düzenledi

Yanıtlar:


8

Arızaları simüle etmek dmsetupiçin errorveya flakeyhedeflerini kullanarak bir aygıt eşleyici cihazı oluşturmak için kullanabilirsiniz .

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

123, aygıtın uzunluğu, sektörlerde ve / dev / loop0 hataları simüle etmek istediğiniz orijinal aygıttır. Hata için, her zaman bir hata döndürdüğü için sonraki bağımsız değişkenlere ihtiyacınız yoktur.


1
Bu komutta en az iki hata buldum: Eksik cihaz adı, alıntı yazım hatası ve "1 0 / dev / null" ne anlama geliyor?
Hauke ​​Laging

@HaukeLaging, ahh, evet, adı bıraktım ve bir şekilde yanlış alıntıya çarptım. 1 0 / dev / null, 0 ofsetinden başlayarak / dev / null aygıtı tarafından desteklenen 1 hedef anlamına gelir. Pul pul için gereklidir, ancak görünüşe göre hata için isteğe bağlıdır.
psusi

Bana öyle geliyor ki "isteğe bağlı" değil, sadece göz ardı ediliyor. İle kontrol edebilirsiniz dmsetup table test. foo barArkada bile yazabilirsiniz error; sadece umursamaz (ve bu nedenle silinmelidir).
Hauke ​​Laging

@HaukeLaging, düzenlendi.
psusi

Cevabınız için teşekkürler, sanırım şimdilik böyle gideceğim. Bununla ilgili tek küçük sorun root erişimi gerektirmesidir, ancak sanırım buna veya düşük seviyeli şeylere ihtiyacınız olacak ... (Zamanım olduğunda LD_PRELOAD fikrini inceleyeceğim).
mreithub

14

Stack Overflow ve Server Fault'ta buna çok sayıda cevap var, ancak bazı teknikler eksikti. Hayatı kolaylaştırmak için VM / Linux blok cihazı / Linux dosya sistemi / Linux kullanıcı alanı kütüphanesi I / O arıza enjeksiyon mekanizmalarının bir listesi:

Bonus gerçek: SQLite, hataları simüle etmek için bir VFS sürücüsüne sahiptir, böylece iyi bir test kapsamı elde edebilir.

İlişkili:


5

I / O için bir hata enjeksiyon mekanizması istiyorsunuz .

Linux'ta, önceden herhangi bir kurulum gerektirmeyen ve olağandışı bir hata oluşturan bir yöntem (EIO “Giriş / çıkış hatası” değil ESRCH “Böyle bir işlem yok”):

cat /proc/1234/mem

burada 1234, test ettiğiniz işlemle aynı kullanıcıyla çalışan bir işlemin PID'sidir, ancak bu işlemin kendisi değildir. Kredi için rubasov için düşünme arasında /proc/$pid/mem.

İşlemin PID'sini kullanırsanız, EIO alırsınız, ancak yalnızca işlemin belleğinde eşlenmemiş bir alandan okuyorsanız. İlk sayfa hiçbir zaman eşlenmez, bu nedenle dosyayı sırayla okursanız sorun olmaz, ancak doğrudan dosyanın ortasına giden bir veritabanı işlemi için uygun değildir.

Kök olarak daha fazla kurulumla, geçerli sektörlere ve bozuk sektörlere sahip dosyalar oluşturmak için cihaz eşleştiriciden yararlanabilirsiniz.

Başka bir yaklaşım, küçük bir FUSE dosya sistemi uygulamak olacaktır . Kullanıcı alanı dosya sistemi sürücünüz yanlış bir şey yaptığında EIO varsayılan hata kodudur, bu nedenle elde edilmesi kolaydır. Hem Perl hem de Python bağlamaları başlamak için örneklerle birlikte gelir, çoğunlukla mevcut dosyaları yansıtan ancak dikkatle seçilmiş yerlerde bir EIO enjekte eden bir dosya sistemi hızlı bir şekilde yazabilirsiniz. Böyle bir dosya sistemi var: petardfs ( makale ), kutunun dışında ne kadar iyi çalıştığını bilmiyorum.

Yine başka bir yöntem bir LD_PRELOADsargıdır. Mevcut olan Libfiu'dur (kullanıcı alanında arıza enjeksiyonu). POSIX API çağrılarını aşırı yükleyen bir kitaplığı önceden yükleyerek çalışır. Normal davranışı geçersiz kılmak için basit yönergeler veya rastgele C kodu yazabilirsiniz.


Libfiu gerçekten umut verici görünüyor (ve debian depolarında). Harika cevap, teşekkürler, +1
mreithub

1

Bir aygıt dosyasını "G / Ç hatalarına sahip dosya" olarak kullanmak uygunsa çözüm çok daha kolaydır. Benim önerim, normal bir dosyanın bu tür hatalara sahip olacağı durumlar için.

> 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

Biraz karışık olduğumu itiraf etmeliyim çünkü o dosyadan tek kesimleri hatasız (ile dd .. seek=...) okumayı başaramadım . Belki de bu, devam eden bir sorundur.


Dosya sisteminizin blokları en az 4096 bayt boyutundadır, bu nedenle dosya küçük olsa bile birden çok sektöre yayılır.
Anon

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.