Linux dd实用程序未准备好接收终止信号

Linux dd实用程序未准备好接收终止信号,linux,bash,shell,dd,Linux,Bash,Shell,Dd,我有一个脚本,可以解压缩.gz文件并将其复制到块设备中。我使用dd获取有关进度的信息(我不能使用其他实用程序,如pv来实现这一点)。以下是脚本的一部分: #!/bin/sh set -e trap 'true' USR1 # ... gunzip -c "${SVM_IMAGE_FILE_PATH}" | dd iflag=fullblock of="${TARGET_DEVICE_PATH}" bs=64M 2>"${DD_OUTPUT_FILE_PATH}" & DD_P

我有一个脚本,可以解压缩
.gz
文件并将其复制到块设备中。我使用
dd
获取有关进度的信息(我不能使用其他实用程序,如
pv
来实现这一点)。以下是脚本的一部分:

#!/bin/sh

set -e
trap 'true' USR1

# ...

gunzip -c "${SVM_IMAGE_FILE_PATH}" | dd iflag=fullblock of="${TARGET_DEVICE_PATH}" bs=64M 2>"${DD_OUTPUT_FILE_PATH}" &
DD_PID=$!

echo "Decompression process has started: $$ -> ${DD_PID}" >> "${DECOMPRESSION_LOG_FILE_PATH}"

# Wait for dd process to become ready to receive 'kill -s USR1' signals
sleep 1

while (ps -p "${DD_PID}") >/dev/null 2>&1
do
    set +e
        kill -s USR1 $DD_PID 2>/dev/null

        LAST_LINE=`tail -n 1 "${DD_OUTPUT_FILE_PATH}"`
        case "${LAST_LINE}" in
            *byte*)
                BYTES_COPIED=`echo ${LAST_LINE} | cut -d ' ' -f1`
                PROGRESS=$(( $(( $BYTES_COPIED * 100 )) / $DECOMPRESSED_FILE_SIZE ))
                set_status "${PROGRESS}% processed"
            ;;
        esac

        # ...
    set -e

    sleep 1

done
如您所见,在
while
循环之前有一个strage
sleep 1
。我想摆脱它,但我不知道如何摆脱。如果我删除此
sleep 1
,则
dd
进程将在第一次调用
kill-s USR1$dd_PID
后立即被终止。也许这并没有杀死dd,但它在某种程度上影响了gunzip进程,我不知道到底发生了什么

那么,有没有办法摆脱这种睡眠状态呢?

有两个问题:

  • DD\u PID
    是运行管道的shell的PID,而不是
    DD
  • SIGUSR1
    将在进程未准备好接收信号时终止进程
  • shell可以选择在与优化相同的过程中执行
    dd
    ,但这不是您可以依赖的(尤其是在使用
    /bin/sh
    时)

    您也不能依靠
    dd
    赛车来设置信号陷阱,因此最好自己设置

    <> P>既然您在Linux上,请考虑只使用GNU DD标志<代码>状态=进度< /代码>自动状态栏。

    或者,将shebang更改为
    #!/bin/bash
    ,并使用:

    trap '' USR1  # Ignore USR1 in inherited processes by default
    dd iflag=fullblock of="${TARGET_DEVICE_PATH}" bs=64M 2>"${DD_OUTPUT_FILE_PATH}" \
         < <(gunzip -c "${SVM_IMAGE_FILE_PATH}") & 
    dd_pid=$!     # Is now 'dd's pid and not a shell's.
    

    或者使用
    dash
    ,将shebang改为
    #!/bin/dash
    ,并将
    trap'true'USR1
    改为
    trap'USR1

    看看@ccarton谢谢!看来
    sleep 1
    实际上是一个合法的解决方案:)但我想,如果有人想出一个聪明的解决办法,我会把这个问题留到一边:)谢谢你的回答!1.我将$DD|u PID与
    ps aux | grep DD
    中的PID进行了比较,它们匹配。2.我必须使用的
    dd
    版本没有标记
    status=progress
    3。由于遗留问题,我不能简单地切换到
    #/在我的脚本中,bin/bash
    ,但我必须使用
    #/bin/sh
    ,例如,它恰好是Debian=)4中的
    破折号。顺便说一句,出于某种原因,我不得不编写
    trap'true'USR1
    ,而不是
    trap'USR1
    ,以使脚本正常工作。我也无法解释这种现象;)5.我两个都不能用/bin/bash
    #/箱子/破折号
    。我必须使用
    #/bin/sh
    由于遗留原因。在某些系统中
    #/bin/sh
    实际上可能是
    #/bin/bash
    ,但我不能相信这一点。无论如何,你已经为我做了很多,我不能不投票就留下你的帮助性评论。谢谢@皮克斯:当然,你更了解你的传统系统。
    fifo="/tmp/foo"
    mkfifo "$fifo"
    gunzip -c "${SVM_IMAGE_FILE_PATH}" | {
      trap '' USR1
      dd iflag=fullblock of="${TARGET_DEVICE_PATH}" bs=64M 2>"${DD_OUTPUT_FILE_PATH}" &
      echo "$!" > "$fifo"
      wait
    } &
    read dd_pid < "$fifo"
    rm "$fifo"