【发布时间】:2018-04-03 03:35:00
【问题描述】:
我有一些类似的秒表脚本:
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 和 HTML 内容。
谁能告诉我该怎么做?
更新
鉴于@Inian 的回答,这就是我目前所拥有的:
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()并在不同的行上打印.每个until cURL返回status_code的200。
然而,这会启动 cURL,但它既不打印 .,也不回显应该等同于 200 的 status_code。
我猜不出为什么。
改变的答案
根据@chepner 的回答,我想出了:
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,它在脚本在kill "$sw_pid"最后执行之前被中断时调用函数kill_sw()。
【问题讨论】:
-
如果您使用(首选)
$((...))语法,则不需要let。 -
您可能想考虑使用
curl已经提供的进度表。 -
你是对的@chepner 我从我的代码中删除了
let -
我想避免使用进度表,因为有时我发现它并不完全准确。我只是想实现一个我自己的秒表,它与下载并行执行,最后显示它所花费的时间。 @chepner 我更新了我的问题,你能猜到为什么我的最后一个脚本不起作用吗?
标签: bash shell curl while-loop