当cURL正在下载执行秒表脚本时

时间:2017-10-22 14:02:09

标签: bash shell curl while-loop

我有一些看起来像的秒表脚本:

BEGIN=$(date +%s)

while true; do
   NOW=$(date +%s)
   DIFF=$(($NOW - $BEGIN))
   MINS=$(($DIFF / 60))
   SECS=$(($DIFF % 60))
   HOURS=$(($DIFF / 3600))

   # \r  is a "carriage return" - returns cursor to start of line
   printf "\rDownload time: %02d:%02d:%02d" $HOURS $MINS $SECS
   sleep 1
done

所以while某些条件为真,它会在每个循环中增加1秒。我希望这种情况有所不同:

function download()
{
    HOMEPAGE_RESPONSE=$(curl -w "\n%{http_code}" "https://example.com/")

    STATUS_CODE=$(echo "$HOMEPAGE_RESPONSE" | sed -n '$p')

    HTML=$(echo "$HOMEPAGE_RESPONSE" | sed '$d')
}

download

# Whenever the STATUS_CODE is 200, exit the stopwatch script
# Can be any other condition that stops the loop when cURL has finished
while (( $STATUS_CODE != 200 )); do
   NOW=$(date +%s)
   DIFF=$(($NOW - $BEGIN))
   MINS=$(($DIFF / 60))
   SECS=$(($DIFF % 60))
   HOURS=$(($DIFF / 3600))

   # \r  is a "carriage return" - returns cursor to start of line
   printf "\rDownload time: %02d:%02d:%02d" $HOURS $MINS $SECS
   sleep 1
done

想法是启动cURL下载并在下载开始的同时执行秒表脚本。这将最终开始计算秒数并打印秒表until下载完成。我也知道我在post中找到的until命令。例如:

until $(curl --output /dev/null --silent --head --fail http://myhost:myport); do
    printf '.'
    sleep 5
done

我不知道如何应用until,因为我的cURL存储在名为download()的函数中的变量中,我希望能够使用STATUS_CODE和{ {1}}内容分开。

谁能告诉我怎么做?

更新

鉴于@Inian的回答,这是我到目前为止所做的:

HTML

根据我的理解,这应该执行功能function download() { homepage_response=$(curl -s -w "\n%{http_code}" "https://example.com/") status_code=$(echo "$homepage_response" | sed -n '$p') html=$(echo "$homepage_response" | sed '$d') printf '%s' "${status_code}" } # Calling the function $(download) until [[ "$(download)" == "200" ]]; do printf '.\n' sleep 1 done echo $status_code 并在不同的行download()上打印. cURL返回until的{​​{1}}。

然而,这会启动cURL,但它既不会打印status_code也不会回显200,它应该等同于.

我无法猜到为什么。

更改回答

根据@chepner的回答,我提出了:

status_code

出于预防措施,我添加了200,只要脚本在最后执行download() { homepage_response=$(curl -s -w "\n%{http_code}" "https://example.com/") status_code=$(echo "$homepage_response" | sed -n '$p') html=$(echo "$homepage_response" | sed '$d') # printf '%s' "${status_code}" } start_stopwatch () { BEGIN=$(date +%s) while true; do NOW=$(date +%s) DIFF=$(($NOW - $BEGIN)) MINS=$(($DIFF / 60)) SECS=$(($DIFF % 60)) HOURS=$(($DIFF / 3600)) printf "\rDownload time: %02d:%02d:%02d" "$HOURS" "$MINS" "$SECS" sleep 1 & wait # Make it interruptible done } start_stopwatch & sw_pid=$! # # For testing purposes # echo "$sw_pid" # Kill background stopwatch if script EXITS beforehand set -e kill_sw() { kill "$sw_pid" } trap kill_sw EXIT # Call function download() download printf "\n" kill "$sw_pid" 之前被中断,就会调用函数set -e

2 个答案:

答案 0 :(得分:1)

您只需要将函数调用用于until条件。但是当前状态下的函数download()不会打印状态代码的输出。稍作修改如下。

download() {
    homepage_response=$(curl -w "\n%{http_code}" "https://example.com/")    
    status_code=$(echo "$HOMEPAGE_RESPONSE" | sed -n '$p')
    html=$(echo "$HOMEPAGE_RESPONSE" | sed '$d')
    printf '%s' "${status_code}"
}

现在使用打印状态代码的功能,在条件为

中使用它
until [[ "$(download)" -eq "$(curl --output /dev/null --silent --head --fail http://myhost:myport)" ]]; do
    sleep 1
    # Your rest of the script goes here
done

作为一般编码实践,

  1. 您可以在((..))构造
  2. 上使用算术运算符let
  3. 小写用户定义的变量,以避免与bash系统特定的环境变量冲突。
  4. 在考虑移植脚本而不涉及任何function - isms时,建议使用不带bash关键字的函数定义。

答案 1 :(得分:1)

我会在后台运行秒表代码,并在curl完成后将其终止。

start_stopwatch () {
   SECONDS=0
   while true; do
     now=$SECONDS
     hours=$((now / 3600))
     now=$((now % 3600))
     mins=$((now / 60))
     secs=$((now % 60))

     printf "\rDownload time: %02d:%02d:%02d" "$hours" "$mins" "$secs"
     sleep 1
   done
}

start_stopwatch & sw_pid=$! 
curl ...
kill "$sw_pid"