假设我想将某个命令的输出通过管道传输到一个文件中。简单地……好吧,将它传送到一个文件,例如
some-command > file
Run Code Online (Sandbox Code Playgroud)
和管道它通过dd像
some-command | dd $MAYBE_SOME_OPTIONS_LIKE_BS of=file
Run Code Online (Sandbox Code Playgroud)
这个问题主要是为了满足我的好奇心,除非后一种形式有一些不可忽视的好处或用例,否则在实践中我会省去练习并选择前者。
fileRun Code Online (Sandbox Code Playgroud)some-command > file some-command | dd $MAYBE_SOME_OPTIONS_LIKE_BS of=file
在第一种情况下,它some-command知道它写入file,因此它可以出于任何原因检索元数据(如 mtime 或 size)。此类元数据对于常规文件具有有用的意义,但对于未命名的管道则毫无意义。
some-command 甚至可能有兴趣打开其标准输出指向的内容进行阅读,这对于常规文件来说相当安全,显然在第二种情况下不是正确的做法。
但我认为这些场景非常罕见。
的行为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
Run Code Online (Sandbox Code Playgroud)
第一个命令将起作用,它将在其中留下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
}
Run Code Online (Sandbox Code Playgroud)
尝试这些并在每个之后检查文件:
is-seekable > file
is-seekable | dd of=file
Run Code Online (Sandbox Code Playgroud)
了解以上所有内容,有一种情况我会考虑您的第二个命令:如果some-command在两种情况下确实表现不同(如我们的is-seekable函数)并且我希望它“认为”它正在写入管道,但我希望输出在一个文件中. 好的。虽然我宁愿使用cat而不是dd(这可能无关紧要)。例如,我可能想non-seekable从is-seekable文件中获取并将其写入文件:
is-seekable | cat > file
Run Code Online (Sandbox Code Playgroud)
但前提是它有什么不同。否则,这将是(臭名昭著的)“无用使用cat”。或者在你的情况下“无用的使用dd”;如果您处理退出状态不佳,甚至是“有害使用”。
现在试试这两个例子:
false > file
false | dd of=file
Run Code Online (Sandbox Code Playgroud)
如果您$?在第二个之后检查,您会发现它0(除非dd失败)。您的第二种情况丢弃了some-command(通常;例如在 Bash 调查中set -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
Run Code Online (Sandbox Code Playgroud)
我认为这非常接近于“不可忽视的好处或用例”。
显然$MAYBE_SOME_OPTIONS_LIKE_BS可以改变dd行为。我知道像这样的选项conv=swab超出了范围,因为您希望file在两种情况下都接收相同的数据。
仍然有几个选项可以有所作为。例子:
status=progress 在处理每个输入块时,将在 stderr 上打印传输速率和容量统计信息;
oflag=noatime 不会更新文件的访问时间戳;
oflag=nolinks 如果文件有多个硬链接,则会失败;
还有更多。
上面的例子是 GNU 扩展,不可移植。便携dd的特点在这里。
最后是KISS 原则:保持简单的愚蠢。你的第一个案例是愚蠢的简单。
| 归档时间: |
|
| 查看次数: |
326 次 |
| 最近记录: |