I / O 오류를 일으키는 특수 파일 (/ dev와 같은)

필수 SQLite DB 파일을 읽지 못하면 (I / O 오류로 인해) 소프트웨어가 예상대로 반응하는지 자동으로 테스트하고 싶습니다. 정확히 며칠 전에 클라이언트에서 일어났습니다. 수동으로 수정했지만 이제는 자동 코드를 작성하여 수정하고 손상된 파일에 액세스하여 테스트해야합니다.

유닉스의 모든 것이 파일이기 때문에, 나는 파일을 읽으려고 할 때 항상 (/ dev와 같은) I / O 오류를 일으키는 특수 파일이있을 수 있다고 생각했습니다.

유사한 파일 (imo)은 다음과 같습니다.

  • /dev/full 작성하려고하면 항상 “장치에 남은 공간이 없습니다”라고 표시됩니다.
  • /dev/null/dev/zero

그래서 나는 그런 파일이 있어야한다고 가정했지만 아직 찾지 못했습니다.

누구든지 원하는 결과 (의도적으로 결함이있는 파티션 이미지, LD_PRELOAD를 사용하여 open () 주위 래퍼)를 얻을 수있는 그러한 파일이나 다른 방법을 알고 있습니까?
가장 좋은 방법은 무엇입니까?



답변

또는 대상을 사용하여 오류를 시뮬레이션 dmsetup하는 장치 매퍼 장치를 만드는 데 사용할 수 있습니다 .errorflakey

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

여기서 123은 장치의 길이이며 섹터 단위이며 / dev / loop0은 오류를 시뮬레이트하려는 원래 장치입니다. 오류의 경우 항상 오류를 반환하므로 후속 인수가 필요하지 않습니다.


답변

Stack Overflow 및 Server Fault에 대해서는 이미 많은 답변이 있지만 일부 기술이 누락되었습니다. 보다 쉽게 ​​사용할 수 있도록 VM / Linux 블록 장치 / Linux 파일 시스템 / Linux 사용자 공간 라이브러리 I / O 결함 주입 메커니즘 목록이 있습니다.

보너스 사실 : SQLite에는 오류를 시뮬레이션하기위한 VFS 드라이버가 있으므로 테스트 범위를 넓힐 수 있습니다.

관련 :


답변

당신은 원하는 오류 분사 I / O에 대한 메커니즘을.

Linux의 경우 사전 설정이 필요하지 않고 비정상적인 오류 (EIO “입력 / 출력 오류”가 아니라 ESRCH “이러한 프로세스 없음”)를 생성하는 방법이 있습니다.

cat /proc/1234/mem

여기서 1234는 테스트중인 프로세스와 동일한 사용자로 실행되는 프로세스의 PID이지만 해당 프로세스 자체는 아닙니다. 크레딧하는 rubasov 에 대한 생각/proc/$pid/mem.

프로세스 자체의 PID를 사용하는 경우 EIO를 얻을 수 있지만 프로세스 메모리에 매핑되지 않은 영역에서 읽는 경우에만 가능합니다. 첫 번째 페이지는 매핑되지 않으므로 파일을 순차적으로 읽지 만 파일 중간을 직접 찾는 데이터베이스 프로세스에는 적합하지 않습니다.

루트로 더 설정 하면 장치 매퍼활용하여 유효한 섹터와 불량 섹터가있는 파일을 만들 수 있습니다.

또 다른 방법은 작은 FUSE 파일 시스템 을 구현하는 것 입니다. EIO는 사용자 공간 파일 시스템 드라이버가 잘못했을 때의 기본 오류 코드이므로 달성하기 쉽습니다. 모두 파이썬 바인딩 예제 시작하기로 빠르게 주로 거울 엄선 된 장소에있는 파일 만 주입하는 EIO 기존의 파일 시스템을 작성할 수 있습니다 온다. petardfs ( article ) 와 같은 기존 파일 시스템 이 있습니다. 상자에서 얼마나 잘 작동하는지 모르겠습니다.

또 다른 방법은 LD_PRELOAD래퍼입니다. 기존의 것은 Libfiu (사용자 공간의 결함 주입)입니다. POSIX API 호출을 오버로드하는 라이브러리를 미리로드하여 작동합니다. 간단한 지시어 나 임의의 C 코드를 작성하여 정상적인 동작을 무시할 수 있습니다.


답변

장치 파일을 “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=...) 파일에서 단일 섹터를 읽을 수 없기 때문에 약간 혼란 스럽다는 것을 인정해야합니다 . 아마도 미리 읽기 문제 일 수 있습니다.


답변

이런 종류의 목적을 위해 만들어진 CharybdeFS를 사용할 수 있습니다.

PetardFS와 같은 패스 스루 퓨즈 파일 시스템이지만 훨씬 더 구성 가능합니다.

CharybdeFS 쿡북을 참조하십시오 : http://www.scylladb.com/2016/05/02/fault-injection-filesystem-cookbook/

데이터베이스를 테스트하기에 충분히 발전했습니다.


답변