Contents

如何计算与dd一起使用的最佳块大小

1. 概述

在本教程中,我们将了解如何获取设备的块大小。当我们使用dd 或任何其他读取/写入存储设备的程序时,这很有用。如果我们选择最佳块大小,我们可以获得更快的速度。

为此,我们可以使用不同的块大小运行dd,然后使用最快的。此外,我们还可以使用stattune2fs 来获得最佳块大小的提示。

2. 尝试不同的价值观并使用最好的

我们的第一个选择是尝试不同的值,看看哪个是最好的。这种方法是最慢的替代方法,但会为我们提供实际的最优值

我们可以使用dd从*/dev/zero*复制到一个临时文件。**为了计算速度,我们使用timeout 命令限制执行时间。**在这段时间内写入最多字节的块大小是最快的。

让我们首先创建我们的calculate_best_bs.sh脚本:

#!/bin/bash
IF=/dev/zero
OF=/tmp/calculate_best_bs.temp
TEST_BLOCK_SIZES=(256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144)
TIMEOUT=20s
BEST_BLOCK_SIZE=0
BEST_BLOCK_SIZE_WROTE=0
for BS in "${TEST_BLOCK_SIZES[@]}"; do
    rm "$OF" >/dev/null 2>&1
    echo 3 >/proc/sys/vm/drop_caches
    timeout "$TIMEOUT" dd "if=$IF" "of=$OF" "bs=$BS" >/dev/null 2>&1
    SIZE=$(stat -c "%s" "$OF")
    if [ "$SIZE" -gt "$BEST_BLOCK_SIZE_WROTE" ]; then
        BEST_BLOCK_SIZE_WROTE="$SIZE"
        BEST_BLOCK_SIZE="$BS"
    fi
done
rm "$OF" >/dev/null 2>&1
echo Fastest Block Size: $BEST_BLOCK_SIZE

**请注意,我们需要以 root 身份运行此脚本,以便它可以在每次运行前删除磁盘缓存。*此外,我们可能希望修改输出文件$OF*以便脚本写入所需的文件系统。

该脚本有一组我们要测试的块大小,还有 20 秒的超时。我们可以通过添加或删除块大小值以及更改超时来限制脚本运行所需的时间。

让我们运行它,看看我们得到了什么:

$ ./calculate_best_bs.sh
Fastest Block Size: 32768

3.使用stat命令

或者,我们可以在任何文件或目录上使用stat命令,它将打印文件系统的块大小。请注意,这只是一个提示,它可能不是真正最快的

$ stat /tmp/inputfile.bin
  File: /tmp/inputfile.bin
  Size: 16350           Blocks: 32         IO Block: 4096   regular file
Device: fd03h/64771d    Inode: 20971538    Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/    nico)   Gid: (  100/   users)
Access: 2021-02-13 19:24:01.682329376 -0300
Modify: 2021-02-13 19:24:01.682329376 -0300
Change: 2021-02-13 19:24:15.581233839 -0300
 Birth: 2021-02-13 19:24:15.581233839 -0300

正如我们所见,它打印了值IO Block: 4096那只是文件(或目录)所在存储的块大小。

stat接受一个参数*-c*(或*–format*),它允许我们指定我们想要的信息。如果我们使用参数-c %ostat将只打印块大小**。

让我们改进上一行,将块大小存储在一个名为BLOCKSIZE的变量中:

$ BLOCKSIZE=$(stat -c "%o" /tmp/inputfile.bin)
$ echo $BLOCKSIZE
4096

最后,我们可以使用刚刚学到的知识编写一个小脚本,以使用dd和上一个命令找到的块大小。让我们创建一个函数,它将输入和输出文件作为参数并打印dd所需的参数:

$ dd_with_bs() {
    OUT_DIR=$(dirname "$2")
    if [ ! -e "$1" -o ! -e "$OUT_DIR" ]; then
        echo "$1 or $OUT_DIR doesn't exist"
        return 1
    fi
    IN_BS=$(stat -c "%o" "$1")
    OUT_BS=$(stat -c "%o" "$OUT_DIR")
    echo dd \"if=$1\" \"of=$2\" \"ibs=$IN_BS\" \"obs=$OUT_BS\"
}

请注意,我们使用目录名 以防输出文件尚不存在。现在让我们运行我们的新功能:

$ dd_with_bs /tmp/inputfile.bin /tmp/outputfile.bin
dd "if=/tmp/inputfile.bin" "of=/tmp/outputfile.bin" "ibs=4096" "obs=4096"

我们可能希望使用先前的输出作为模板,使用更多参数来完成dd命令。

4. 使用tune2fs

最后,我们还可以通过运行tune2fs -l partition获得分区的块大小 。在这种情况下,我们还需要有 root 权限,文件系统必须是ext3ext4

让我们尝试针对*/dev/sda1运行它并使用grep *过滤信息:

$ tune2fs -l /dev/sda1 | grep "Block size:"
Block size:               4096

此外,我们可以使用awk 来获取值。当我们想要运行 oneliner 命令或将值存储在变量中时,这会很有用。让我们将值存储在一个名为BLOCKSIZE的变量中:

$ BLOCKSIZE=$(tune2fs -l /dev/sda1 | awk '/Block size:/{print $3}')
$ echo $BLOCKSIZE
4096

有一个名为dumpe2fstune2fs替代品。它与tune2fs属于同一个包,也需要以 root权限运行。在这种情况下,我们可以使用dumpe2fs -h partition 来获取块大小

$ dumpe2fs -h /dev/sda1 | grep "Block size:"
dumpe2fs 1.46.0 (29-Jan-2020)
Block size:               4096