it-swarm.cn

dd vs cat-这些天dd仍然有用吗?

我最近意识到,我们可以使用catdd一样多,它的 实际上比dd

我知道dd对于处理块大小实际上与正确性(而不仅仅是性能)有关的磁带很有用。但是,在这些日子里,dd可以做cat做不到的事情吗? (在这里,我认为小于20%的性能差异无关紧要。)

具体的例子会很好!

129
kizzx2

在外观上, dd 是IBM操作系统中的一种工具,该工具保留了其外观(参数传递),该工具执行一些很少使用的功能(例如EBCDIC)到ASCII转换或字节序反转……如今已不常见。

曾经认为dd在同一磁盘上复制大型数据块更快(由于更有效地使用了缓冲),但是 至少在当今的Linux系统上不是

我认为dd的某些选项在处理磁带时很有用,在这种情况下,读取实际上是在块中执行的(磁带驱动程序不会像磁盘驱动程序那样将块隐藏在存储介质上)。但我不知道具体情况。

dd可以(但不容易)通过任何其他POSIX工具完成的一件事是获取流的前N个字节。许多系统都可以使用head -c 42来做到这一点,但是head -c虽然很常见,但它不在POSIX中(并且今天在例如OpenBSD中不可用)。 (tail -c是POSIX。)此外,即使存在head -c,它也可能会从源中读取太多字节(因为它在内部使用了stdio缓冲),如果您正在从特殊文件,仅读取即可起作用。 (当前GNU coreutils使用head -c读取了确切的计数,但是FreeBSD和NetBSD使用stdio。)

更一般而言,dd提供了在Unix工具中唯一的基础文件API的接口:只有dd可以覆盖或截断文件在任何情况下点搜索在文件中。 (这是dd的独特功能,这是一个很大的功能;奇怪的是,dd以其他工具可以做的事情而闻名。)

  • 大多数Unix工具会覆盖其输出文件,即擦除其内容并从头开始。当您在Shell中也使用>重定向时,就会发生这种情况。
  • 您可以在Shell中使用>>重定向或tee -a将文件内容附加到文件的内容之后。
  • 如果要通过删除所有数据在某个点之后=来缩短文件,则底层内核和C API通过 truncate 函数,但不由任何命令行工具 公开,但dd 除外:

    dd if=/dev/null of=/file/to/truncate seek=1 bs=123456  # truncate file to 123456 bytes
    
  • 同样,如果您想覆盖文件中间的数据,则可以在底层API中通过 打开 文件进行写入而不会截断(并调用 _lseek 移至所需位置),但是只有dd可以打开文件而不会截断或追加,或者 seek 从Shell( 更复杂的示例 )。

    # zero out the second kB block in the file (i.e. bytes 1024 to 2047)
    dd if=/dev/zero of=/path/to/file bs=1024 seek=1 count=1 conv=notrunc
    

因此,作为系统工具,dd几乎没有用。作为文本(或二进制文件)处理工具,它非常有价值!

167

dd命令包含很多cat无法容纳的选项。也许在您的使用情况下,cat是一种可行的替代品,但它不是dd替代品。

一个示例是使用dd复制某些内容,而不是整个内容。也许您想根据设备上的已知位置从iso映像的中间部分或硬盘驱动器的分区表中提取一些位。使用dd,您可以指定允许执行这些操作的开始,停止和数量选项。

dd的这些选项使它对于细粒度的数据操作必不可少,而cat *只能在整个文件对象,设备或流上操作。

*正如Gilles在评论中所指出的,可以将cat与其他工具组合起来以隔离某些部分,但是cat仍然可以在整个对象上运行。

22
Caleb

还没有人提到可以使用dd创建 稀疏文件 ,尽管truncate也可以用于相同的目的。

dd if=/dev/zero of=sparse-file bs=1 count=1 seek=10GB

这几乎是即时的,并会创建一个任意的大文件,例如,该文件可用作回送文件:

loop=`losetup --show -f sparse-file`
mkfs.ext4 $loop
mkdir myloop
mount $loop myloop

令人高兴的是,它最初仅使用单个磁盘空间块,然后仅根据需要增长(10GB文件的ext4格式在我的系统上消耗291 MB)。使用du查看实际使用了多少磁盘空间-ls仅报告文件可能增长到的最大大小。

21
Lauritz V. Thaulow

常见的例子是用某些东西覆盖硬盘驱动器的特定段。例如,您可能要使用以下命令删除MBR:

dd if=/dev/zero of=/dev/sda bs=446 count=1

您也可以使用它创建空文件(例如,用于循环磁盘映像):

dd if=/dev/zero of=10mb.file bs=1024k count=10
10
XQYZ

dd对于备份硬盘驱动器或其他存储设备(dd if=/dev/sda of=boot_sector.bin bs=512 count=1),然后将其重写(_dd if=boot_sector.bin of=/dev/sda)。备份加密卷的标头同样有用。

cat也许可以这样做,但是在重写部分我不相信它。很难获得cat只读/写一定数量的字节。

9
LawrenceC

最近,在我的Linux历史记录中,我第一次有理由克隆了多个GB的多个分区(c.f cp -arrsync对我很有帮助)。当然,我求助于dd,因为每个人都知道这就是您所使用的...并且对此表现感到震惊。不久之后,我使用了一些谷歌搜索功能 ddrescue ,该功能我已经使用了几次,并且表现出色(比dd快得多)。

5
timday

这些年来,我想出了一些dd技巧。

在不友好的tty或非交互模式bash上剪切并粘贴

如果您未检测到EOF/^ D/^ F,则可以使用dd将文本文件传输到主机。因为它将在指定的字节数后自动停止读取。

我是在去年的一次安全演习中使用此功能的,我们能够在远程主机上获取非tty外壳,并且需要将文件传输进来。

实际上,我什至通过base64对它们进行编码,并使用缓慢但可靠的纯bash base64解码脚本对了几个二进制文件。

dd of=textfile.txt bs=1 count=<size_of_data_in_paste_buffer>

一个超酷的技巧是,在dd运行时,如果向其发送USR1信号,它将发出其当前状态(读取的字节,每秒的字节。)

通用吞吐量状态过滤器

我编写此代码的目的是,它可以作为任何通过stdout发射数据的程序的纯bash进度过滤器。 (注意:几乎所有东西都会通过stdout发出数据-对于不这样做的程序,如果不使用/ dev/stdout作为文件名,则可以欺骗它们,但是基本上,每次获得X字节数,打印哈希标记(如启用哈希模式的老式FTP)

(注)进度文件是la脚的,这主要是概念的证明。如果重做,我只会使用一个变量。

 dd bs=$BLKSZ of=${TMPFILE} 2>&1 \
                | grep --line-buffered -E '[[:digit:]]* bytes' \
                | awk '{ print $1 }' >> ${PROGRESS} &

 while [[ $(pidof dd) -gt 1 ]]; do

        # PROTIP: You can sleep partial seconds
        sleep .5

        # Force dd to update us on it's progress (which gets
        # redirected to $PROGRESS file.    
        pkill -USR1 dd
        local BYTES_THIS_CYCLE=$(tail -1 $PROGRESS)
        local XFER_BLKS=$(((BYTES_THIS_CYCLE-BYTES_LAST_CYCLE)/BLKSZ))

        if [ $XFER_BLKS -gt 0 ]; then
                printf "#%0.s" $(seq 0 $XFER_BLKS)
                BYTES_LAST_CYCLE=$BYTES_THIS_CYCLE
        fi
done

使用匿名Shell文件句柄对切片文件进行切片

这是一个极其伪代码的示例,说明如何拥有一个签名的tar文件,该文件可以通过匿名文件句柄提供tar输入而不会出现错误,而无需使用任何tmp文件来存储部分文件数据,而不会出错。

generate_hash() {
    echo "yay!"
}

# Create a tar file, generate a hash, append it to the end
tar -cf log.tar /var/log/* 2>/dev/null
TARFILE_SIZE=$(stat -f "%z" log.tar)
SIGNATURE=$(generate_hash log.tar)
echo $SIGNATURE >>log.tar

# Then, later, extract without getting an error..

tar xvf <(dd if=$OLDPWD/log.tar bs=1 count=${TARFILE_SIZE})

Tl; dr是:我发现dd非常有用。这些只是我能想到的三个例子。

5
synthesizerpatel

您可以重定向一些输出内容。如果您需要使用Sudo进行编写,则它特别有用:

echo some_content | Sudo dd status=none of=output.txt

除了Sudo,它还等效于:

echo some_content > output.txt

或对此:

echo some_content | Sudo tee output.txt > /dev/null
5
Alexey