Спеціальний файл, який викликає помилку вводу / виводу


13

Я хочу автоматично перевірити, чи частина програмного забезпечення реагує, як очікувалося, якщо істотний файл DB SQLite не вдалося прочитати (викликаючи помилку вводу / виводу). Саме так сталося кілька днів тому у клієнта. Ми вручну виправили це, але тепер я хочу створити автоматичний код, щоб виправити його, і для перевірки цього потрібен доступ до зламаного файлу.

Як і все у файлі Unix, я підозрював, що може бути спеціальний файл, який завжди спричиняє помилки вводу-виводу при спробі його прочитати (наприклад, в / dev).

Деякі подібні файли (imo):

  • /dev/full який завжди говорить "Не залишається місця на пристрої", якщо ви спробуєте написати це
  • /dev/null і /dev/zero

тож я припустив, що просто має бути такий файл (але його ще не знайшли).

Хтось знає такий файл чи будь-який інший метод для мене, щоб отримати бажаний результат (навмисно несправне зображення розділу, обгортка навколо open () за допомогою LD_PRELOAD, ...)?
Який найкращий спосіб поїхати сюди?


Наскільки я знаю, в Linux немає спеціального файлу, який дає SIGIO, коли ви читаєте з нього. Востаннє я отримав SIGIO через USB-накопичувач, який оголосив ємність набагато більшою, ніж реальна, фізична. Може, це може бути ймовірність?
lgeorget

хммм, я можу спробувати це з невеликим зображенням розділу, який я
обрізаю

SIGIO не означає, що сталася помилка, це програма, яка може попросити отримувати сповіщення про те, що зараз не можливе блокування IO, а не виклик select () або anketa ().
psusi

Двічі, так, ти маєш рацію, звичайно. Я писав SIGIO, але думав про код помилки EIO. Але, можливо, і ОП? Чому невдача читання дала SIGIO?
lgeorget

ой, я зробив ту саму помилку у питанні ... Відредагував це ...
mreithub

Відповіді:


8

Ви можете використовувати dmsetupдля створення пристрою-картографічного пристрою, використовуючи errorабо flakeyцілі для імітації збоїв.

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

Де 123 - довжина пристрою, в секторах і / dev / loop0 - оригінальний пристрій, на якому ви хочете імітувати помилки. Для помилки вам не потрібні наступні аргументи, оскільки вона завжди повертає помилку.


1
У цій команді я знаходжу щонайменше дві помилки: Відсутнє ім’я пристрою, помилка цитування та що має означати "1 0 / dev / null"?
Хоуке Лагінг

@HaukeLaging, ах, так, я покинув ім'я та якось потрапив у неправильну цитату. 1 0 / dev / null означає 1 ціль, починаючи з зміщення 0, підкріплене пристроєм / dev / null. Він потрібен для відшарування, але, мабуть, необов’язковий для помилок.
psusi

Мені здається, що це не "необов'язково", а просто ігнорується. Ви можете перевірити dmsetup table test. Можна навіть писати foo barпозаду error; це просто не хвилює (і тому його слід видалити).
Хоуке Лагінг

@HaukeLaging, відредаговано.
psusi

Дякую за відповідь, я думаю, що саме зараз я піду. Єдине незначне питання, яке я маю з цим, - це те, що він вимагає кореневого доступу, але, мабуть, вам знадобляться такі речі або такі речі з низьким рівнем ... (я буду вникати в ідею LD_PRELOAD, коли встигну).
mreithub

14

На це вже великий набір відповідей щодо переповнення стека та помилки сервера, але деякі методи відсутні. Щоб полегшити життя, ось перелік блоку VM / Linux блочного пристрою / файлової системи Linux / бібліотеки користувача Linux, механізми введення вводу / виводу несправностей:

Факт бонусу: SQLite має драйвер VFS для імітації помилок, завдяки чому він може отримати хороший тестовий покрив.

Пов'язані:


5

Ви хочете, щоб механізм введення несправностей вводу / виводу.

У Linux ось метод, який не потребує попередніх налаштувань і генерує незвичну помилку (не "Помилка вводу / виводу" EIO, а ESRCH "Немає такого процесу"):

cat /proc/1234/mem

де 1234 - PID процесу, який працює тим самим користувачем, що і процес, який ви протестуєте, але не сам процес. Кредити rubasov для мислення про /proc/$pid/mem.

Якщо ви використовуєте PID самого процесу, ви отримуєте EIO, але тільки якщо ви читаєте з області, яка не відображена в пам'яті процесу. Перша сторінка ніколи не відображається, тому добре, якщо ви читаєте файл послідовно, але не підходить для процесу бази даних, який шукає безпосередньо до середини файлу.

З додатковими налаштуваннями як root, ви можете використовувати карту пристроїв для створення файлів з допустимими та поганими секторами.

Іншим підходом було б впровадження невеликої файлової системи FUSE . EIO - це код помилки за замовчуванням, коли ваш драйвер файлової системи користувача робить щось не так, тому його легко досягти. І прив'язки Perl, і Python мають приклади для початку. Ви можете швидко написати файлову систему, яка в основному відображає наявні файли, але вводить EIO у ретельно вибрані місця. Існує така файлова система: petardfs ( стаття ), я не знаю, наскільки добре вона працює з поля.

Ще один метод - LD_PRELOADобгортка. Існуючий - Libfiu (введення несправностей у користувальницький простір). Це працює, попередньо завантаживши бібліотеку, яка перевантажує виклики POSIX API. Ви можете написати прості директиви або довільний код C, щоб змінити нормальну поведінку.


Libfiu виглядає дійсно багатообіцяючою (і це в репозі Debian). Чудова відповідь, спасибі, +1
mreithub

1

Рішення набагато простіше, якщо нормально використовувати файл пристрою як "файл з помилками вводу / виводу". Моя пропозиція стосується тих випадків, коли звичайний файл має такі помилки.

> 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 та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.