dd 实用程序在 sh 和 bash 的同一命令下输出不同的行,如何强制输出 docker 容器内的最后一行?

dd utility outputs different lines under the same command for sh and bash, how to force output of the last line inside the docker container?

在 docker 容器中我测试了

dd if=/dev/zero of=/tmp/test2.img bs=512 count=1000 2> >( grep copied )

行执行。我使用两种方式钻入容器。

1)经典的是docker exec -it 2b65c84ddce2 /bin/sh

内含的执行行继承自阿尔卑斯山 I'm greeting /bin/sh: syntax error: unexpected redirection 因为 >(

附近的东西

2) 当我将容器输入到 bash 执行器时,如 docker exec -it 2b65c84ddce2 /bin/bash

dd if=/dev/zero of=/tmp/test2.img bs=512 count=1000 2> >( grep copied ) returns无输出 dd if=/dev/zero of=/tmp/test2.img bs=512 count=1000 returns 只输出2行,而期望是3行:

1+0 records in
1+0 records out

在主机级别,相同的 dd 命令返回 3 行,如下所示:

dd if=/dev/zero of=/tmp/test2.img bs=512 count=1000
1000+0 records in
1000+0 records out
512000 bytes (512 kB, 500 KiB) copied, 0.0109968 s, 46.6 MB/s

并且使用重定向后输出是最后一行:

dd if=/dev/zero of=/tmp/test2.img bs=512 count=1000 2> >( grep copied )
512000 bytes (512 kB, 500 KiB) copied, 0.0076261 s, 67.1 MB/s

那么如何从 docker 容器内部获取最后一行 dd 输出?

PS.

将 stderr 重定向到 stdout 通常没有帮助:

/ # dd if=/dev/zero of=/tmp/test2.img bs=512 count=1000 2>&1 | grep copied
/ # dd if=/dev/zero of=/tmp/test2.img bs=512 count=1000 2>&1
1000+0 records in
1000+0 records out

在主机系统上它可以工作

$ dd if=/dev/zero of=/tmp/test2.img bs=512 count=1000 2>&1 | grep copied
512000 bytes (512 kB, 500 KiB) copied, 0.00896706 s, 57.1 MB/s

主持人:

dd --v
dd (coreutils) 8.30
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

作者:Paul Rubin、David MacKenzie 和 Stuart Kemp。

容器:

/ #dd --v

BusyBox v1.31.1 () multi-call binary.

Usage: dd [if=FILE] [of=FILE] [ibs=N obs=N/bs=N] [count=N] [skip=N] [seek=N]
        [conv=notrunc|noerror|sync|fsync]
        [iflag=skip_bytes|fullblock] [oflag=seek_bytes|append]

Copy a file with converting and formatting

        if=FILE         Read from FILE instead of stdin
        of=FILE         Write to FILE instead of stdout
        bs=N            Read and write N bytes at a time
        ibs=N           Read N bytes at a time
        obs=N           Write N bytes at a time
        count=N         Copy only N input blocks
        skip=N          Skip N input blocks
        seek=N          Skip N output blocks
        conv=notrunc    Don't truncate output file
        conv=noerror    Continue after read errors
        conv=sync       Pad blocks with zeros
        conv=fsync      Physically write data out before finishing
        conv=swab       Swap every pair of bytes
        iflag=skip_bytes        skip=N is in bytes
        iflag=fullblock Read full blocks
        oflag=seek_bytes        seek=N is in bytes
        oflag=append    Open output file in append mode
        status=noxfer   Suppress rate output
        status=none     Suppress all output

N may be suffixed by c (1), w (2), b (512), kB (1000), k (1024), MB, M, GB, G

它们实际上是不同的

对于搜索此问题的任何人:

使用的 DD 正在与 BusyBox 一起使用。第三行是一个可选的输出,它是在从源代码编译 BusyBox 时定义的。预编译版本禁用此功能

ENABLE_FEATURE_DD_THIRD_STATUS_LINE必须定义。

参见 https://git.busybox.net/busybox/tree/coreutils/dd.c 第 166 行。

#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
# if ENABLE_FEATURE_DD_STATUS
    if (G.flags & FLAG_STATUS_NOXFER) /* status=noxfer active? */
        return;
    //TODO: should status=none make dd stop reacting to USR1 entirely?
    //So far we react to it (we print the stats),
    //status=none only suppresses final, non-USR1 generated status message.
# endif
    fprintf(stderr, "%llu bytes (%sB) copied, ",
            G.total_bytes,
            /* show fractional digit, use suffixes */
            make_human_readable_str(G.total_bytes, 1, 0)
    );
    /* Corner cases:
     * ./busybox dd </dev/null >/dev/null
     * ./busybox dd bs=1M count=2000 </dev/zero >/dev/null
     * (echo DONE) | ./busybox dd >/dev/null
     * (sleep 1; echo DONE) | ./busybox dd >/dev/null
     */
    seconds = (now_us - G.begin_time_us) / 1000000.0;
    bytes_sec = G.total_bytes / seconds;
    fprintf(stderr, "%f seconds, %sB/s\n",
            seconds,
            /* show fractional digit, use suffixes */
            make_human_readable_str(bytes_sec, 1, 0)
    );
#endif
}