dd 与 cat - 这些天 dd 仍然相关吗?

kiz*_*zx2 147 dd cloning cat

我最近意识到我们可以使用cat尽可能多的dd,而且它实际上比dd

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

具体的例子会很好!

Gil*_*il' 184

在外观上,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给底层文件的API,它是众多Unix工具独特的接口:仅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
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果您想覆盖文件中间的数据,同样,这可以在底层 API 中通过打开文件进行写入而不截断(并lseek在必要时调用以移动到所需位置),但只能dd打开文件而无需截断或追加,或从 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
    
    Run Code Online (Sandbox Code Playgroud)

所以……作为系统工具,dd几乎没什么用。作为一个文本(或二进制文件)处理工具,非常有价值!

  • 另一个特殊用途:`dd` 可以从不可搜索的文件描述符中读取二进制数据,而不会由于 stdio 缓冲而破坏未读数据。请参见此处的示例:http://www.etalabs.net/sh_tricks.html (4认同)
  • @R..:是的。在 GNU coreutils 6.10 中,`head -c N` 调用 `read` 并且永远不会超过 N。在 NetBSD 5.1 中,`head -c` 调用 `getc`。在 FreeBSD 7.4 中,`head -c` 调用 `fread`。 (2认同)
  • Coreutils `dd` 还将 O_DIRECT(等)暴露给 shell 脚本,我认为这也是独一无二的。 (2认同)

Lau*_*low 24

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

dd if=/dev/zero of=sparse-file bs=1 count=1 seek=10GB
Run Code Online (Sandbox Code Playgroud)

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

loop=`losetup --show -f sparse-file`
mkfs.ext4 $loop
mkdir myloop
mount $loop myloop
Run Code Online (Sandbox Code Playgroud)

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

  • @frostschutz:`man dd` 说:`MB =1000*1000,M =1024*1024` 等等。而`man truncate` 说:`MB 1000*1000, M 1024*1024`,所以**没有区别。**我使用GNU coreutils 中的`dd` 和`truncate`。你也应该这样做!:-) (5认同)
  • `ls -ls` 显示稀疏大小。 (4认同)
  • 您的命令将一个无用的字节写入文件。`dd of=sparse-file bs=1 count=0 seek=10G` 等价于 `truncate -s 10GB sparse-file`。令人困惑的是,`truncate` 和 `dd` 对 `GB` 和 `G` 的解释完全相反...... (2认同)

Cal*_*leb 23

dd命令包含大量 cat 无法容纳的选项。也许在您的使用案例中 cat 是一个可行的替代品,但它不是 dd 替代品。

一个例子是dd用来复制某些东西的一部分,而不是整个东西。也许您想根据设备上的已知位置从iso 映像的中间或硬盘驱动器的分区表中删除一些位。随着dd您可以指定启动,停止和数量的选项,允许这些行动。

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

*正如 Gilles 在评论中所指出的,可以cat与其他工具结合使用来隔离某些部分,但cat仍然对整个对象进行操作。

  • 当然。;-) 当我将 1.6TB 磁盘映像输入`cat | 头| tail` 来获取磁盘旋转的最后几 MB 会将月球吸到离地球更近的地方。 (18认同)
  • `dd` 实际上与低级设备无关,它需要像其他设备一样在 `/dev` 中添加一个条目。你可以用`cat`复制整个分区,或者用`tail +c $(($start+1)) |复制它的一部分。head -c $count`。 (6认同)
  • @Gilles 抱歉,我确实想承认我使用的“低级别”一词并不是很好的用词,尽管我指的是设备上的数据,而不是设备上的数据。也许“微调数据操作”会比“操作低级数据”更好。 (2认同)

XQY*_*QYZ 10

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

dd if=/dev/zero of=/dev/sda bs=446 count=1
Run Code Online (Sandbox Code Playgroud)

你也可以用它创建空文件(比如循环磁盘映像):

dd if=/dev/zero of=10mb.file bs=1024k count=10
Run Code Online (Sandbox Code Playgroud)

  • @Kevin:比`head -c` 快吗?请分享一个[基准](http://unix.stackexchange.com/questions/9432/is-there-a-way-to-determine-the-optimal-value-for-the-bs-parameter-to-dd /9492#9492)! (3认同)

Law*_*ceC 9

dd对于备份硬盘驱动器或其他存储设备的引导扇区 ( dd if=/dev/sda of=boot_sector.bin bs=512 count=1) 并随后重写它 ( dd if=boot_sector.bin of=/dev/sda)非常有用。它对于备份加密卷的标头同样有用。

cat可能会被扭曲到这样做,但我不会相信它在重写部分。很难cat只读/写一定数量的字节。


tim*_*day 6

我最近有理由在我的 linuxing 历史上第一次克隆一些多个 100s-of-GB 的分区(参见cp -arrsync多次为我服务)。当然,我转向dd'因为每个人都知道这就是你使用的......并且对性能感到震惊。谷歌搜索很快让我找到了ddrescue,我现在已经使用了几次并且效果非常好(比 dd 快得多)。

  • 为了使用“dd”获得良好的性能,您必须设置块大小。例如,`bs=1M`。 (3认同)
  • **`ddrescue`** 很棒,特别是用于从故障磁盘中获取数据。 (2认同)

syn*_*tel 5

这是我多年来想出的一些 dd 技巧。

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

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

我最近在去年的一次安全练习中使用了它,在那里我们能够在远程主机上获得非 tty shell 并需要传输文件。

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

dd of=textfile.txt bs=1 count=<size_of_data_in_paste_buffer>
Run Code Online (Sandbox Code Playgroud)

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

通用吞吐量状态过滤器

我写这个是为了作为任何通过标准输出发出数据的程序的纯 bash 进度过滤器。(注意:几乎任何东西都会通过 stdout 发出数据 - 对于不发出数据的程序,如果他们不使用 /dev/stdout 作为文件名对你发出警告,你可以作弊。但这个想法基本上是,每次你得到 X字节数,打印散列标记(就像打开散列模式时的老式 FTP)

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

 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
Run Code Online (Sandbox Code Playgroud)

使用匿名 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})
Run Code Online (Sandbox Code Playgroud)

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


小智 5

您可以重定向一些输出内容。如果您需要使用以下内容编写,它特别有用sudo

echo some_content | sudo dd status=none of=output.txt
Run Code Online (Sandbox Code Playgroud)

除此之外,sudo它相当于:

echo some_content > output.txt
Run Code Online (Sandbox Code Playgroud)

或者到这个:

echo some_content | sudo tee output.txt > /dev/null
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

41021 次

最近记录:

7 年,6 月 前