强制wget超时


6

如何在X秒后强制wget停止?

我有一个下载图像的脚本,并且不时会卡住并拒绝“超时”。

我尝试过的:

--tries=3 --connect-timeout=30

来自ps aux

root     26543  0.0  0.0  38636  1656 ?        S    20:40   0:00 wget -nc --tries=3 --connect-timeout=30 --restrict-file-names=nocontrol -O 18112012/image.jpg http://site/image.jpg

你试过--timeout(或-T)选项吗?
gniourf_gniourf

是的......一切都来自wget man

你确定你试过wget -nc --tries=3 -T30 --restrict-file-names=nocontrol -O 18112012/image.jpg http://site/image.jpg吗?我从来没有遇到像你描述的问题。
gniourf_gniourf

Answers:


2

您可以将wget命令作为后台进程运行,并在睡眠一段时间后发送SIGKILL强制终止它。

wget ... &
wget_pid=$!
counter=0
timeout=60
while [[ -n $(ps -e) | grep "$wget_pid") && "$counter" -lt "$timeout" ]]
do
    sleep 1
    counter=$(($counter+1))
done
if [[ -n $(ps -e) | grep "$wget_pid") ]]; then
    kill -s SIGKILL "$wget_pid"
fi

说明:

  • wget ... &- 最后的&符号在后台运行命令而不是前景
  • wget_pid=$!- $!是一个特殊的shell变量,它包含最近执行的命令的进程ID。这里我们将它保存到一个名为的变量中wget_pid
  • while [[ -n $(ps -e) | grep "$wget_pid") && "$counter" -lt "$timeout" ]] - 每隔一秒查找一次进程,如果仍然存在,请等待超时限制。
  • kill -s SIGKILL "$wget_pid"- 我们用它kill来强制杀死在后台运行的wget进程,发送一个SIGKILL信号

1
如果wget成功怎么办?你会随机扔一个SIGKILL
gniourf_gniourf

如果文件已经下载,我怎么能跳过“睡眠”?

1
重写了脚本,使其更加健壮,并解决了跳过睡眠时间问题
sampson-chen

@gniourf_gniourf有证据表明将SIGKILL发送给任何人都是有害的吗?
kojiro

@kojiro取决于实施,技术上的pids可以重复使用; 所以理论上它可能会触及另一个过程。
sampson-chen

12

最简单的方法是使用timeout(1)命令,GNU coreutils的一部分,因此几乎可以在任何安装bash的地方使用:

timeout 60 wget ..various wget args..

或者,如果你想要wget,如果它运行太久了:

timeout -s KILL 60 wget ..various wget args..

你知道每台Mac上都安装了bash,没有GNU用户地,对吧?
kojiro

1
@kojiro:标记的问题ubuntu包括GNU coreutils,如果你需要它可以很容易地安装在mac上。

嗯,也许它应该被迁移到askubuntu.com。>;)
kojiro

1
这绝对是最简单,最安全的方式。man timeout将显示其他选项。我个人不会-s KILL直接使用该选项,但可能会使用该-k选项,例如timeout -k 5 60 wget ..various wget args..wgetKILL编辑之前给予额外5秒的机会)。这个答案值得+1
gniourf_gniourf

0

社区wiki,因为这主要是sampson-chen的答案副本,但我想指出一些事情:

wget ... &
# Strictly speaking you can just use the job number,
# which is probably %1, but saving the pid is also fine.
wget_pid=$! 
counter=0
timeout=60
# use kill -0 to check if a pid is still running
while kill -0 "$wget_pid" && (( counter < timeout )); do
    sleep 1
    (( counter++ ))
done
# if killing nothing is distasteful, use kill -0 one more time.
# also think a SIGKILL is overkill since the question doesn't imply wget needs it.
kill -0 "$wget_pid" && kill "$wget_pid"

0

我最近注意到wget 1.14默默地忽略了--timeout选项,当我将其更新为1.19时它工作正常

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.