ddは、出力をパイピングしながら「生」の進行状況を表示します。

ddは、出力をパイピングしながら「生」の進行状況を表示します。

特定のdd操作を実行し、トランスポートの「生」データを他のインターフェース(たとえばターミナルではない)からのトランスポートのリアルタイムビューを提供するために、他のものによってポーリングされるログファイルに追加しようとしています。

dd操作は次のとおりです。

dd if=/some/lvm bs=512K | gzip -c > /tmp/whatever

私が見る最も簡単な方法は、コマンドをファイルに出力し、同時に-SIGUSR1 pidで終了して出力を表示することです。しかし、プロセスのpidを変数に保存し、終了コマンドで使用する方法を見つけることはできません。 。

私はこれのための1つか2つのライナーを見ました。

dd if=/some/lvm of=/some/fat/image/which/I/cant/use bs=512K& pid=$!; \
sleep 1; while [[ -d /proc/$pid ]]; do kill -USR1 $pid && sleep 1; done

pidを変数にインポートする方法を理解していないので、パイプ出力を使用するように変更することはできません。

ddの代替案を見てうれしいですが、ほとんどはdcflddと同じ行を更新するのと同じくらい複雑ですが、私の考えでは呪いのようなアプローチです。これにより、毎秒その出力のスナップショットを撮り、必要なデータを抽出することが困難になります。これを処理する簡単な方法がある場合、または「生」出力を取得できる場合は、PVにパイプすることもできます。

私を啓発してください。 ;-)

挨拶

編集:だから「解決策」を見つけました。まだきれいじゃないけど

pgrepを使用してプロセスIDを見つけることができるので、ddコマンドが実行されてファイルに出力されると、毎秒出力転送の進行watch -n1 'sudo kill -USR1 $(pgrep ^dd)'状況を実行し、ポーラーがその進行状況を解釈できます。

これはまだエレガントな解決策ではなく、ジレンマのように感じます。より良い方法がある場合は、まだ提案に開いています。 :-)

答え1

最良の答えは、pvパイピングできるすべてのプロセスの進行状況を見ることができるということです。

dd if=/some/lvm bs=512K | pv | gzip -c > /tmp/whatever

以下を使用して、ddディスクイメージを作成または書き込みする一般的な目的にも使用できます。ddpv

dd if=/dev/cdrom | pv | dd of=/path/to/some.iso

答え2

トリックを実行するスクリプトは次のとおりです。

(
        dd if=/some/lvm bs=512K &
        pid_dd=$!

        while :; do
                sleep 1
                kill -USR1 $pid_dd
        done &
        pid_monitor=$!

        wait $pid_dd
        kill $pid_monitor
) |
        gzip -c > /tmp/whatever

答え3

まだこの問題を発見できる人のために:

ddの進行状況をgrepまたは処理するには、これを括弧で囲むことができます。 killによってトリガーされた出力はstderrに送信されるため、2>&1をリダイレクトしてgrepableにすることができます。

# ( DP=$(
 dd if=/proc/kcore of=/dev/null bs=1M count=50000 &
 echo $!);  while kill -USR1 $DP 2>/dev/null; do sleep 1; done ) 2>&1 |grep copied
0 bytes copied, 1.73e-05 s, 0.0 kB/s
21043871744 bytes (21 GB, 20 GiB) copied, 1.01827 s, 20.7 GB/s
42920312832 bytes (43 GB, 40 GiB) copied, 2.02764 s, 21.2 GB/s
52428800000 bytes (52 GB, 49 GiB) copied, 2.49048 s, 21.1 GB/s
#

楽しくするには、ジッパーを追加してください。ブラケットがもっと必要になるでしょう! gzipのために>&1を予約するには>&3をバイパスする必要があるからです。

    # ZIPFILE=/path/to/zipfile..
    # ( DP=$(
((dd if=/proc/kcore bs=1M count=500 & echo $! >&3 ) | gzip > $ZIPFILE & ) 3>&1|head -1); 
    sleep 1 # wait for dd startup; 
    while kill -USR1 $DP 2>/dev/null ; do sleep 1; done) 2>&1|grep copied
    241172480 bytes (241 MB, 230 MiB) copied, 1.00001 s, 241 MB/s
    486539264 bytes (487 MB, 464 MiB) copied, 2.00568 s, 243 MB/s
    524288000 bytes (524 MB, 500 MiB) copied, 2.16047 s, 243 MB/s

目的に合わせてddを編集してください。
PS。これは、スクリプトをラップしてから |grep またはスクリプトの外に移動する操作の一部です。またはその逆を実行し、1行でうまく動作します:-)

答え4

それがあなたにうまくいかないならpv、あなたは正しい道を行っていますkill -USR1。元のコマンドが与えられたら、一対のスクリプトdd if=/some/lvm bs=512K | gzip -c > /tmp/whateverコンテキストで次のことを行います。

dd if=/some/lvm bs=512K | gzip -c > /tmp/whatever &
PID=$! # $! is set to the PID of the last backgrounded process
echo $PID > /var/run/dd_pid.txt  # So that other scripts can read it
fg
rm /var/run/dd_pid.txt

一方、他のスクリプトは次のことを行います。

PID=$(cat /var/run/dd_pid.txt)
if [[ 0 -ne $? ]]; then
    echo 'PID file not found'
    exit 1
fi
while kill -0 $PID; do
    sleep 1
    kill -USR1 $PID
done

関連情報