|
1 | 1 | #!/bin/bash |
2 | | -# Тест дисков NVMe |
3 | | - |
| 2 | +# Тест дисков NVMe (профиль CrystalDiskMark: SEQ1M Q8T1, SEQ128K Q32T1, RND4K Q32T8, RND4K Q1T1) |
| 3 | +# Парсинг через JSON-вывод fio + jq, все значения в MB/s (десятичные, как у fio/CDM) |
4 | 4 | set -u |
5 | 5 | set -o pipefail |
6 | 6 |
|
7 | | -# Проверка: установлен ли fio |
8 | | -if ! command -v fio >/dev/null 2>&1; then |
9 | | - echo "Ошибка: 'fio' не найден (команда отсутствует в PATH). Установите fio и повторите." |
10 | | - echo "Debian/Ubuntu: sudo apt install -y fio" |
11 | | - exit 127 |
12 | | -fi |
| 7 | +# --- Проверка зависимостей --------------------------------------------------- |
| 8 | +for cmd in fio jq; do |
| 9 | + if ! command -v "$cmd" >/dev/null 2>&1; then |
| 10 | + echo "Ошибка: '$cmd' не найден (команда отсутствует в PATH)." |
| 11 | + echo "Debian/Ubuntu: sudo apt install -y $cmd" |
| 12 | + exit 127 |
| 13 | + fi |
| 14 | +done |
13 | 15 |
|
| 16 | +# --- Параметры ---------------------------------------------------------------- |
14 | 17 | TESTFILE_PATH='/980PRO/fiotest.tmp' |
15 | 18 | TESTFILE_SIZE='1000m' |
16 | 19 | TEST_LOOPS='5' |
17 | 20 |
|
| 21 | +# --- Проверка каталога --------------------------------------------------------- |
| 22 | +TESTDIR=$(dirname "$TESTFILE_PATH") |
| 23 | +if [ ! -d "$TESTDIR" ] || [ ! -w "$TESTDIR" ]; then |
| 24 | + echo "Ошибка: каталог '$TESTDIR' не существует или недоступен для записи." |
| 25 | + exit 1 |
| 26 | +fi |
| 27 | + |
| 28 | +# --- Уборка тестового файла при любом выходе ----------------------------------- |
| 29 | +trap 'rm -f "$TESTFILE_PATH"' EXIT |
| 30 | + |
18 | 31 | FIO_BASE=(fio |
19 | 32 | --loops="$TEST_LOOPS" |
20 | 33 | --size="$TESTFILE_SIZE" |
21 | 34 | --filename="$TESTFILE_PATH" |
22 | 35 | --ioengine=libaio |
23 | 36 | --direct=1 |
| 37 | + --group_reporting |
| 38 | + --output-format=json |
24 | 39 | ) |
25 | 40 |
|
26 | 41 | pause_io() { sync; sleep 3; } |
27 | 42 |
|
28 | | -# Оставляем исходную логику парсинга: 3-е поле и вырезаем "bw=...MiB/s" |
29 | | -# (как было: substr($3, 2, length($3)-3)) |
30 | | -extract_bw() { |
31 | | - grep -E "$1" | awk '{print substr($3, 2, length($3)-3)}' |
| 43 | +# run_test <read|write> <доп. параметры fio...> |
| 44 | +# Возвращает скорость в MB/s (десятичных, bw_bytes/1e6) или "ERR" при сбое. |
| 45 | +run_test() { |
| 46 | + local direction="$1"; shift |
| 47 | + local json bw |
| 48 | + if ! json=$("${FIO_BASE[@]}" "$@" 2>/dev/null); then |
| 49 | + echo "ERR"; return 1 |
| 50 | + fi |
| 51 | + bw=$(jq -r --arg d "$direction" '.jobs[0][$d].bw_bytes' <<<"$json" 2>/dev/null) |
| 52 | + if [ -z "$bw" ] || [ "$bw" = "null" ]; then |
| 53 | + echo "ERR"; return 1 |
| 54 | + fi |
| 55 | + awk -v b="$bw" 'BEGIN { printf "%.1f", b / 1000000 }' |
32 | 56 | } |
33 | 57 |
|
34 | 58 | print_header() { |
35 | | - echo " +----------------------------------------+" |
36 | | - printf " | %12s | %10s | %10s |\n" "Mode" "Read" "Write" |
37 | | - echo " +----------------------------------------+" |
| 59 | + echo " +------------------------------------------------+" |
| 60 | + printf " | %12s | %14s | %14s |\n" "Mode" "Read, MB/s" "Write, MB/s" |
| 61 | + echo " +------------------------------------------------+" |
38 | 62 | } |
39 | 63 | print_row() { |
40 | | - printf " | %12s | %10s | %10s |\n" "$1" "$2" "$3" |
41 | | - echo " +----------------------------------------+" |
| 64 | + printf " | %12s | %14s | %14s |\n" "$1" "$2" "$3" |
| 65 | + echo " +------------------------------------------------+" |
42 | 66 | } |
43 | 67 |
|
| 68 | +# --- Тесты --------------------------------------------------------------------- |
44 | 69 | pause_io |
45 | | -SEQ1MQ8T1R=$("${FIO_BASE[@]}" --name=SeqReadQ8 --bs=1m --iodepth=8 --rw=read | extract_bw 'READ:') |
| 70 | +SEQ1MQ8T1R=$(run_test read --name=SeqReadQ8 --bs=1m --iodepth=8 --rw=read) |
46 | 71 | pause_io |
47 | | -SEQ1MQ8T1W=$("${FIO_BASE[@]}" --name=SeqWriteQ8 --bs=1m --iodepth=8 --rw=write | extract_bw 'WRITE:') |
48 | | - |
| 72 | +SEQ1MQ8T1W=$(run_test write --name=SeqWriteQ8 --bs=1m --iodepth=8 --rw=write) |
49 | 73 | print_header |
50 | 74 | print_row "SEQ1MQ8T1" "$SEQ1MQ8T1R" "$SEQ1MQ8T1W" |
51 | 75 |
|
52 | 76 | pause_io |
53 | | -SEQ128KQ32T1R=$("${FIO_BASE[@]}" --name=SeqReadQ32 --bs=128k --iodepth=32 --rw=read | extract_bw 'READ:') |
| 77 | +SEQ128KQ32T1R=$(run_test read --name=SeqReadQ32 --bs=128k --iodepth=32 --rw=read) |
54 | 78 | pause_io |
55 | | -SEQ128KQ32T1W=$("${FIO_BASE[@]}" --name=SeqWriteQ32 --bs=128k --iodepth=32 --rw=write | extract_bw 'WRITE:') |
| 79 | +SEQ128KQ32T1W=$(run_test write --name=SeqWriteQ32 --bs=128k --iodepth=32 --rw=write) |
56 | 80 | print_row "SEQ128KQ32T1" "$SEQ128KQ32T1R" "$SEQ128KQ32T1W" |
57 | 81 |
|
58 | 82 | pause_io |
59 | | -RND4KQ32T8R=$("${FIO_BASE[@]}" --name=RandReadQ32 --bs=4k --iodepth=32 --numjobs=8 --rw=randread | extract_bw 'READ:') |
| 83 | +RND4KQ32T8R=$(run_test read --name=RandReadQ32 --bs=4k --iodepth=32 --numjobs=8 --rw=randread) |
60 | 84 | pause_io |
61 | | -RND4KQ32T8W=$("${FIO_BASE[@]}" --name=RandWriteQ32 --bs=4k --iodepth=32 --numjobs=8 --rw=randwrite | extract_bw 'WRITE:') |
| 85 | +RND4KQ32T8W=$(run_test write --name=RandWriteQ32 --bs=4k --iodepth=32 --numjobs=8 --rw=randwrite) |
62 | 86 | print_row "RND4KQ32T8" "$RND4KQ32T8R" "$RND4KQ32T8W" |
63 | 87 |
|
64 | 88 | pause_io |
65 | | -RND4KQ1T1R=$("${FIO_BASE[@]}" --name=RandReadQ1 --bs=4k --iodepth=1 --rw=randread | extract_bw 'READ:') |
| 89 | +RND4KQ1T1R=$(run_test read --name=RandReadQ1 --bs=4k --iodepth=1 --rw=randread) |
66 | 90 | pause_io |
67 | | -RND4KQ1T1W=$("${FIO_BASE[@]}" --name=RandWriteQ1 --bs=4k --iodepth=1 --rw=randwrite | extract_bw 'WRITE:') |
| 91 | +RND4KQ1T1W=$(run_test write --name=RandWriteQ1 --bs=4k --iodepth=1 --rw=randwrite) |
68 | 92 | print_row "RND4KQ1T1" "$RND4KQ1T1R" "$RND4KQ1T1W" |
0 commit comments