コマンドが完了する前にいくつかの文字列を印刷するには?

コマンドが完了する前にいくつかの文字列を印刷するには?

私はbashスクリプトを使用してクライアントデバイスからWebサーバーに大容量ファイルをダウンロードしています。

しかし、時間がかかるため、nginxはゲートウェイタイムアウトを返します。私がやる計画は、bashスクリプトの標準出力をPythonサブプロセスにリンクして応答として送信することです。 scpは標準出力として出力を生成しないため、scpコマンドが完了するまで毎分応答を送信する必要があります。

bashスクリプトを使用してこれを達成する方法はありますか?

また、通常20分以上かかるため、Nginxタイムアウトを増やすことはできません。

答え1

バックグラウンドでいくつかの出力を実行するプロセスを作成し、scp完了したら終了できます。

(while sleep 60; do echo downloading; done) &
PID=$!
scp "$1" "$2"
kill $PID

答え2

ダウンロードと待機を処理するより一般的な機能は次のとおりです。

#! /bin/bash

# Wait for process end and show seconds count down
# Arg1: PID
# Arg2: Expected seconds
# Arg3: (optional): dump file
# Arg4: (optional): expected file size in bytes
function waitpid() {
[ -n "$3" ] && touch "$3"
local COUNT=$(( $2*10 ))
while [ -e /proc/$1 ]; do 
    if [ $(( COUNT%10 )) -eq 0 ]; then
        echo -en "\r$(( COUNT/10 )) sec"
        if [ -n "$3" ]; then
            bytes=$( stat --format=%s $3 )
            echo -n " $bytes bytes "
            if [ -n "$4" ]; then
                echo -n "$(( $bytes*100/$4 ))% "
            fi
        fi
    fi
    echo -en ".\e[K"
    sleep 0.1
    [ $COUNT -gt 0 ] && COUNT=$(( COUNT-1 ))
done
echo
}

echo "Example 1: Wait for process to be finished"
sleep 10 &
waitpid $! 10

echo "Example 2: Wait and show file size"
for N in {1..5} ; do echo "BAR $N" >> /tmp/foo ; sleep 2 ; done &
waitpid $! 10 /tmp/foo

出力例:

Example 1: Wait for process to be finished
3 sec........
Example 2: Wait and show file size
7 sec 160 bytes .......

編集:複雑すぎる場合、短いバージョンは次のようになります。

sleep 10 &
while [ -e /proc/$! ]; do echo -n . ; sleep 1 ; done

スクリーンショット:

$ sleep 10 &
[1] 5432
$ while [ -e /proc/$! ]; do echo -n . ; sleep 1 ; done
..........[1]+  Done sleep 10

答え3

さて、いよいよやりました。パラメータを渡し$1$2ここscpでコマンドのプロセスIDを取得しscp、完了するまで毎分ダウンロードした応答をエコーし​​ました。このために私はSECONDSbashで使用します。

t=$SECONDS
scp $1 $2 &
PROC_ID=$!
while kill -0 "$PROC_ID" >/dev/null 2>&1; do
    n=$(( SECONDS-t))
    if (( n > 60 )); then
        echo downloading
        t=$SECONDS
    fi
done

関連情報