AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / computer / 问题 / 1470608
Accepted
Mona the Monad
Mona the Monad
Asked: 2019-08-13 17:23:17 +0800 CST2019-08-13 17:23:17 +0800 CST 2019-08-13 17:23:17 +0800 CST

文件重定向与 dd

  • 772

假设我想将一些命令的输出通过管道传输到一个文件中。有什么区别,无论多么小或细微差别,在简单......好吧,将它传递到一个文件之间

some-command > file

dd并像管道一样通过它

some-command | dd $MAYBE_SOME_OPTIONS_LIKE_BS of=file

这个问题主要是为了满足我的好奇心,除非后一种形式有一些不可忽视的好处或用例,否则在实践中我会省去我的手指练习并选择前者。

bash dd
  • 2 2 个回答
  • 509 Views

2 个回答

  • Voted
  1. Best Answer
    Kamil Maciorowski
    2019-08-14T01:50:48+08:002019-08-14T01:50:48+08:00

    直接访问file

    some-command > file
    some-command | dd $MAYBE_SOME_OPTIONS_LIKE_BS of=file
    

    在第一种情况下,some-command知道它写入file,因此它可以出于任何原因检索元数据(如 mtime 或 size)。这样的元数据对于普通文件很有用,但对于未命名的管道来说,它们毫无意义。

    some-command甚至可能有兴趣打开它的 stdout 指向的内容以供阅读,这对于常规文件来说是相当安全的,并且在第二种情况下显然不是正确的做法。

    但我认为这些情况非常罕见。


    可搜索与不可搜索

    的行为some-command可能取决于它的标准输出是否可搜索。通常情况并非如此,尽管有可能。常规文件是可搜索的(您可以在任何位置读/写)。管道是不可搜索的。

    dd本身就是一个有效的例子。考虑some-command是dd if=/dev/zero bs=1 count=1 seek=1。你的两个例子变成:

    dd if=/dev/zero bs=1 count=1 seek=1 > file
    dd if=/dev/zero bs=1 count=1 seek=1 | dd of=file
    

    第一个命令会起作用,它会留下file两个空字节。在第二个命令中,第一个命令dd会抱怨它无法寻找,它会退出;第二个dd什么也得不到,什么也不写,然后无错退出。

    我承认seek这并不是完全简单的“将某些命令的输出通过管道传输到文件中”。但通常some-command可以检测其标准输出是否可搜索,然后在不实际搜索的情况下流式传输不同的输出。这个 shell 函数有点像概念验证:

    is-seekable() {
      if </dev/null dd bs=1 count=0 seek=1 conv=notrunc 2>/dev/null; then
        echo seekable
      else
        echo non-seekable
      fi
      }
    

    尝试这些并在每一个之后检查文件:

    is-seekable > file
    is-seekable | dd of=file
    

    了解以上所有内容后,有一种情况我会考虑您的第二个命令:如果some-command在两种情况下确实表现不同(例如我们的is-seekable函数)并且我希望它“认为”它正在写入管道但我想要文件中的输出. 好的。尽管我宁愿使用cat而不是dd(这可能无关紧要)。例如,我可能想non-seekable从文件中获取is-seekable并将其写入文件:

    is-seekable | cat > file
    

    但前提是它有任何不同。否则它将是(在)著名的“无用的使用cat”。或者在你的情况下“无用的使用dd”;如果您处理退出状态不当,甚至是“有害使用”。


    退出状态

    现在试试这两个例子:

    false > file
    false | dd of=file
    

    如果你$?在第二个之后检查,你会发现它是0(除非dd失败)。您的第二个案例丢弃的退出状态some-command(通常;例如,在 Bash investigateset -o pipefail中,这是不可移植的)。

    因此,在第二种情况下some-command,无论出于何种原因都可能会失败,而您(或者更确切地说是脚本的逻辑)将不知道。这足以避免不必要的管道dd(或根本不需要管道)。


    权限

    另一个细微差别:some-command > file使(子)shell 在some-command生成(执行到)之前打开文件;dd of=file代表自己打开文件。

    有一些方法可以授予dd比任何其他“常规”命令更多的访问权限。换句话说,有一些方法可以让普通的dd行为更像sudo dd没有密码。你不应该这样做,希望没有人这样做,但这是可能的。

    您可以做的是按需授予访问权限:sudo dd. 它在尝试写入受限文件时很有用。分析一下:

    some-command > restricted_file               # doesn't work
    sudo some-command > restricted_file          # doesn't work
    some-command | sudo dd > restricted_file     # doesn't work
    sudo sh -c 'some_command > restricted_file'  # works, but it runs some_command as root
                                                 #  you may not want this
    some-command | sudo dd of=restricted_file    # works
    some-command | sudo tee restricted_file      # works, more common, possibly with
                                                 #  > /dev/null to suppress output to tty
    

    我认为这非常接近“不可忽视的好处或用例”。


    也许有一些选择

    显然$MAYBE_SOME_OPTIONS_LIKE_BS可以改变dd行为。我知道像这样conv=swab的选项超出了范围,因为您想file在两种情况下都接收相同的数据。

    仍然有一些选择可以有所作为。例子:

    • status=progress在处理每个输入块时,将在 stderr 上打印传输速率和体积统计信息;

    • oflag=noatime不会更新文件的访问时间戳;

    • oflag=nolinks如果文件有多个硬链接,将会失败;

    • 等等。_

    上面的示例是 GNU 扩展,不可移植。便携dd是这里的特点。


    吻

    最后是KISS 原则:保持简单。你的第一个案例很简单。

    • 6
  2. ddemuro
    2019-08-13T22:04:58+08:002019-08-13T22:04:58+08:00

    任何用户都不应注意到任何差异。从性能的角度来看,怀疑也会有差异。如果您同时考虑这两种情况,则各有利弊,但这在很大程度上取决于您要实现的目标。

    例如:cat 文件 | dd of=file2 vs cat file > file2. 这里的区别是,cat 将打开一个文件,dd 将继承流,除非您指定块大小或某种写入标志,它将立即开始写入 fs 堆栈。

    如果你不使用 dd 的任何功能,你几乎只是分叉一个中间人,添加一个进程,我认为这个双分叉与只让 dd 处理 if=file of=newfile 相比性能损失最小。在这种情况下,优点是您可以在 dd 中查找/跳过,而且只有一个进程。

    如果您严格来说只是文件重定向与 dd,我会说如果您不为 dd 提供任何标志/参数,则没有区别。在这种情况下,您可以将其用作中间人缓冲区,但还有更好的选择,例如:cat file | 缓冲区 | gzip > gzip 内容。例如,上面的堆栈调用,假设你有一个超快的源和一个慢速的目的地,中间有缓冲区,你可以确保接收方始终有一个繁忙的输入队列,如果你正在压缩,你可以确保让你的 CPU 不等待 IO。

    同样,所有边缘情况都需要单独的问题,但如您所见,如果我们严格地从一个到另一个来说,即使存在差异,也怀疑除了极端边缘情况外它是否会被注意到。

    希望这会有所帮助,我不得不说这个问题很有趣,我花了一些时间来考虑。

    • 1

相关问题

  • 在非 root 用户上用 bash 替换 zsh

  • 在 macOS High Sierra 的终端中设置环境变量时遇到问题

  • 对于 cp 或 mv,是否有等同于 cd - 的东西?

  • Notify-发送窗口下出现的通知

  • 如何从 WSL 打开 office 文件

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    Windows 照片查看器因为内存不足而无法运行?

    • 5 个回答
  • Marko Smith

    支持结束后如何激活 WindowsXP?

    • 6 个回答
  • Marko Smith

    远程桌面间歇性冻结

    • 7 个回答
  • Marko Smith

    Windows 10 服务称为 AarSvc_70f961。它是什么,我该如何禁用它?

    • 2 个回答
  • Marko Smith

    子网掩码 /32 是什么意思?

    • 6 个回答
  • Marko Smith

    鼠标指针在 Windows 中按下的箭头键上移动?

    • 1 个回答
  • Marko Smith

    VirtualBox 无法以 VERR_NEM_VM_CREATE_FAILED 启动

    • 8 个回答
  • Marko Smith

    应用程序不会出现在 MacBook 的摄像头和麦克风隐私设置中

    • 5 个回答
  • Marko Smith

    ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败:无法获取本地颁发者证书 (_ssl.c:1056)

    • 4 个回答
  • Marko Smith

    我如何知道 Windows 安装在哪个驱动器上?

    • 6 个回答
  • Martin Hope
    Albin 支持结束后如何激活 WindowsXP? 2019-11-18 03:50:17 +0800 CST
  • Martin Hope
    fixer1234 “HTTPS Everywhere”仍然相关吗? 2019-10-27 18:06:25 +0800 CST
  • Martin Hope
    Kagaratsch Windows 10 删除大量小文件的速度非常慢。有什么办法可以加快速度吗? 2019-09-23 06:05:43 +0800 CST
  • Martin Hope
    andre_ss6 远程桌面间歇性冻结 2019-09-11 12:56:40 +0800 CST
  • Martin Hope
    Riley Carney 为什么在 URL 后面加一个点会删除登录信息? 2019-08-06 10:59:24 +0800 CST
  • Martin Hope
    zdimension 鼠标指针在 Windows 中按下的箭头键上移动? 2019-08-04 06:39:57 +0800 CST
  • Martin Hope
    Inter Sys Ctrl+C 和 Ctrl+V 是如何工作的? 2019-05-15 02:51:21 +0800 CST
  • Martin Hope
    jonsca 我所有的 Firefox 附加组件突然被禁用了,我该如何重新启用它们? 2019-05-04 17:58:52 +0800 CST
  • Martin Hope
    MCK 是否可以使用文本创建二维码? 2019-04-02 06:32:14 +0800 CST
  • Martin Hope
    SoniEx2 更改 git init 默认分支名称 2019-04-01 06:16:56 +0800 CST

热门标签

windows-10 linux windows microsoft-excel networking ubuntu worksheet-function bash command-line hard-drive

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve