<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Shell on Tuan's Blog</title><link>https://blog.cloudorz.com/tags/shell/</link><description>Recent content in Shell on Tuan's Blog</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><copyright>mt</copyright><lastBuildDate>Sun, 01 Nov 2026 10:00:00 +0800</lastBuildDate><atom:link href="https://blog.cloudorz.com/tags/shell/index.xml" rel="self" type="application/rss+xml"/><item><title>Linux dd 命令在运行时显示进度</title><link>https://blog.cloudorz.com/p/linux-dd-show-progress-while-running/</link><pubDate>Sun, 05 May 2024 08:55:59 +0800</pubDate><guid>https://blog.cloudorz.com/p/linux-dd-show-progress-while-running/</guid><description>&lt;img src="https://blog.cloudorz.com/p/linux-dd-show-progress-while-running/cover.svg" alt="Featured image of post Linux dd 命令在运行时显示进度" /&gt;&lt;h2 id="问题"&gt;问题&#10;&lt;/h2&gt;&lt;p&gt;在 Linux/Unix 类系统中，&lt;code&gt;dd&lt;/code&gt; 命令是一个非常实用的工具，可以用来复制文件、磁盘、分区等。但是 &lt;code&gt;dd&lt;/code&gt; 默认在运行时不会显示任何进度信息，这可能会让你感到焦虑和困惑：到底 dd 了多少啊啊啊啊啊。那么，有没有办法让 &lt;code&gt;dd&lt;/code&gt; 命令在运行时显示进度呢？&lt;/p&gt;&#10;&lt;h2 id="解决方案"&gt;解决方案&#10;&lt;/h2&gt;&lt;h3 id="dd-命令加上-statusprogress-参数"&gt;dd 命令加上 status=progress 参数&#10;&lt;/h3&gt;&lt;p&gt;GNU Coreutils 8.24 版本之后，&lt;code&gt;dd&lt;/code&gt; 命令增加了一个 &lt;code&gt;status=progress&lt;/code&gt; 参数，可以用来显示进度信息。你可以像下面这样使用它：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/zero &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/null &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1M &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt; &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;code&gt;status=progress&lt;/code&gt; 参数会让 &lt;code&gt;dd&lt;/code&gt; 命令实时刷新已复制的字节数、耗时和速度，如图：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="dd status=progress 的输出" class="gallery-image" data-flex-basis="2270px" data-flex-grow="945" height="174" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.cloudorz.com/p/linux-dd-show-progress-while-running/dd-progress.png" srcset="https://blog.cloudorz.com/p/linux-dd-show-progress-while-running/dd-progress_hu_8d5cffc4c14ef3d5.png 800w, https://blog.cloudorz.com/p/linux-dd-show-progress-while-running/dd-progress_hu_b508569dcd386907.png 1600w, https://blog.cloudorz.com/p/linux-dd-show-progress-while-running/dd-progress.png 1646w" width="1646"&gt;&lt;/p&gt;&#10;&lt;h3 id="使用-kill-命令"&gt;使用 kill 命令&#10;&lt;/h3&gt;&lt;p&gt;如果是已经在跑的 &lt;code&gt;dd&lt;/code&gt;，也可以用 &lt;code&gt;kill&lt;/code&gt; 命令给它发送 &lt;code&gt;USR1&lt;/code&gt; 信号。GNU &lt;code&gt;dd&lt;/code&gt; 收到这个信号后，会把当前的统计信息打印到标准错误，然后&lt;strong&gt;继续运行&lt;/strong&gt;，不会被终止。我们做一个小实验：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 启动 dd 命令，放到后台执行&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/zero &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/null &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10M &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;100000&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 获取 dd 命令的进程 ID&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 每隔 1 秒输出一次进度信息&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;while&lt;/span&gt; ps -p &lt;span class="nv"&gt;$PID&lt;/span&gt; &amp;gt; /dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nb"&gt;kill&lt;/span&gt; -USR1 &lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; sleep 1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;在这个示例中，我们用 &lt;code&gt;dd&lt;/code&gt; 从 &lt;code&gt;/dev/zero&lt;/code&gt; 设备读取数据并写入 &lt;code&gt;/dev/null&lt;/code&gt; 设备，然后用 &lt;code&gt;kill&lt;/code&gt; 每隔 1 秒让 &lt;code&gt;dd&lt;/code&gt; 输出一次进度信息：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="kill -USR1 的工作方式" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.cloudorz.com/p/linux-dd-show-progress-while-running/usr1-terminal.svg"&gt;&lt;/p&gt;&#10;&lt;p&gt;这种方法不需要安装额外的软件，毕竟 &lt;code&gt;kill&lt;/code&gt; 是 Linux 系统自带的工具。它也适用于一开始执行 &lt;code&gt;dd&lt;/code&gt; 时忘了加 &lt;code&gt;status=progress&lt;/code&gt; 参数的情况，可以用这种方法补救：在另一个终端里找到 &lt;code&gt;dd&lt;/code&gt; 的进程号再发信号即可。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo &lt;span class="nb"&gt;kill&lt;/span&gt; -USR1 &lt;span class="k"&gt;$(&lt;/span&gt;pgrep -x dd&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;注意：&lt;code&gt;USR1&lt;/code&gt; 打印进度是 &lt;strong&gt;GNU&lt;/strong&gt; &lt;code&gt;dd&lt;/code&gt; 的行为。macOS/BSD 上的 &lt;code&gt;dd&lt;/code&gt; 不一定支持 &lt;code&gt;USR1&lt;/code&gt;，发错了可能直接把 &lt;code&gt;dd&lt;/code&gt; 结束掉。那边一般用 &lt;code&gt;INFO&lt;/code&gt; 信号：在运行 &lt;code&gt;dd&lt;/code&gt; 的终端里按 &lt;code&gt;Ctrl+T&lt;/code&gt; 即可。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;h3 id="进度到-100-了为什么还没结束"&gt;进度到 100% 了，为什么还没结束？&#10;&lt;/h3&gt;&lt;p&gt;往 U 盘、SD 卡这类慢速设备写镜像时，经常会看到进度早早就到了总大小，命令却迟迟不退出。这是因为数据先写进了内存里的页缓存，&lt;code&gt;dd&lt;/code&gt; 统计的是“写进缓存”的量，真正落盘还需要时间。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="进度统计的是写进缓存的量" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.cloudorz.com/p/linux-dd-show-progress-while-running/page-cache.svg"&gt;&lt;/p&gt;&#10;&lt;p&gt;可以加上 &lt;code&gt;conv=fsync&lt;/code&gt;，让 &lt;code&gt;dd&lt;/code&gt; 在退出前等数据真正写入设备；或者加上 &lt;code&gt;oflag=direct&lt;/code&gt; 绕过页缓存，让进度更贴近实际写入速度：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;debian.iso &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sdX &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4M &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress &lt;span class="nv"&gt;conv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;fsync&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&lt;code&gt;/dev/sdX&lt;/code&gt; 请换成实际的设备名，写错设备会直接覆盖上面的数据，执行前用 &lt;code&gt;lsblk&lt;/code&gt; 再三确认。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;h2 id="总结"&gt;总结&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;场景&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;方法&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;新执行的 &lt;code&gt;dd&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;加上 &lt;code&gt;status=progress&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;已经在跑、忘了加参数&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;另开终端 &lt;code&gt;kill -USR1 &amp;lt;PID&amp;gt;&lt;/code&gt;（GNU &lt;code&gt;dd&lt;/code&gt;）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macOS/BSD 上的 &lt;code&gt;dd&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;按 &lt;code&gt;Ctrl+T&lt;/code&gt; 发送 &lt;code&gt;INFO&lt;/code&gt; 信号&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;写慢速设备&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;再加 &lt;code&gt;conv=fsync&lt;/code&gt;，结束时确保数据已落盘&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;以上就是在 Linux/Unix 系统中让 &lt;code&gt;dd&lt;/code&gt; 命令显示进度的几种常用方法，你可以根据自己的需求选择合适的方法。&lt;/p&gt;&#10;&lt;h2 id="参考"&gt;参考&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://www.gnu.org/software/coreutils/manual/html_node/dd-invocation.html" target="_blank" rel="noopener"&#10; &gt;GNU Coreutils: dd invocation&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item></channel></rss>