如何从 Bash 循环检查 Curl PID 何时完成
How To Check When Curl PID is Done from Bash Loop
我无法找出 OSX 上的错误。当我尝试查看 Curl 何时完成时,进程仍处于加载状态。我从来没有看到 CURL FINISHED 消息。
#!/bin/bash
curl -S -o example.com http://example.com/downloads/example.zip &
CURL_PID=$!
echo -e "CURL PID = $CURL_PID"
while :
do
sleep 1
if [ -n $(ps -p$CURL_PID -o pid=) ]; then
echo "CURL NOT FINISHED"
else
echo "CURL FINISHED"
break
fi
done
注意 OSX 版本的 Bash 当我 运行 这个:
#!/bin/bash
PIDX=1
if [ -n $(ps -p$PIDX -o pid=) ]; then
echo "PROCESS 1 IS THERE"
else
echo "PROCESS 1 IS NOT THERE"
fi
...它说进程 1 在那里。 (每个人都有一个 PID 1,所以这只是一个例子。)所以,我知道我的 if
语句是正确的。 if
行不需要双引号。
请注意,我不能在 $CURL_PID
上使用等待,因为您在这里看不到的是我也在使用 OSX 的 osascript
命令来显示显示 "Downloading..." 的对话框,上面还有一个取消按钮和它自己的 $DLG_PID
,所以我一直循环直到他们取消对话框(意思是 $DLG_PID
点消失了)或者 $CURL_PID
不见了(意味着下载终于完成了,所以我现在可以 运行 kill $DLG_PID
)。
在 OSX 上,请注意我也在 curl
声明之前这样做。
osascript -e 'tell app "System Events" to display dialog "Downloading..." with title "My App Installer" buttons {"Cancel"}' &
因此,如果有人取消对话,我会通过 PID 终止 curl 并退出无限循环(并退出 bash 脚本)。如果他们不取消该对话框,并且 curl 完成,那么我将通过 PID 终止该对话框并退出 bash 脚本。
通常您会为此使用 wait
:
curl http://... &
do_something
wait
echo "CURL has finished"
轮询后台作业的可移植方法是使用 kill
内置函数,并发送信号 0
以查看它是否可交付。如果子进程仍然是 运行,kill -0 $pid
(其中 $pid
是子进程的 PID)将 return 为零,如果它已经死亡,则为非零。请注意,对于子进程(而不是从别处启动的某个随机进程,将 PID 写入 PID 文件),这是安全的 仅 安全(来自 PID 回收),原因概述 here:
Each UNIX process also has a parent process. This parent process is the process that started it, but can change to the init process if the parent process ends before the new process does. (That is, init
will pick up orphaned processes.) Understanding this parent/child relationship is vital because it is the key to reliable process management in UNIX. A process's PID will NEVER be freed up for use after the process dies UNTIL the parent process waits for the PID to see whether it ended and retrieve its exit code. If the parent ends, the process is returned to init
, which does this for you.
This is important for one major reason: if the parent process manages its child process, it can be absolutely certain that, even if the child process dies, no other new process can accidentally recycle the child process's PID until the parent process has waited for that PID and noticed the child died. This gives the parent process the guarantee that the PID it has for the child process will ALWAYS point to that child process, whether it is alive or a "zombie". Nobody else has that guarantee.
当然,较新版本的OSX不使用init
(取而代之的是launchd
),但原理是一样的。
顺便说一下,整个页面都值得一读:http://mywiki.wooledge.org/ProcessManagement。
鉴于此,这里有一个示例脚本可以执行您想要的操作(它需要一个 URL 参数——下载 URL)。如果有什么不清楚的地方请打扰我。
#!/usr/bin/env bash
osascript -e 'tell app "System Events" to display dialog "Downloading..." with title "Downloader" buttons {"Cancel"}' &>/dev/null &
dialog_pid=$!
curl -sSLO "" &
curl_pid=$!
timer=0
while kill -0 "$curl_pid" &>/dev/null; do
kill -0 "$dialog_pid" &>/dev/null || { echo "User cancelled download from dialog."; kill "$curl_pid" &>/dev/null; exit 1; }
sleep 1
(( timer++ ))
echo "Been downloading for $timer seconds..."
done
echo "Finished."
kill "$dialog_pid" &>/dev/null
wait &>/dev/null
运行它:
> ./download https://github.com/torvalds/linux/archive/v4.4-rc2.tar.gz
Been downloading for 1 seconds...
Been downloading for 2 seconds...
<omitted>
Been downloading for 38 seconds...
Finished.
中途取消:
> ./download https://github.com/torvalds/linux/archive/v4.4-rc2.tar.gz
Been downloading for 1 seconds...
Been downloading for 2 seconds...
Been downloading for 3 seconds...
User cancelled download from dialog.
丑陋的是,杀死 osascript
作业的 PID 并没有关闭对话框...我无法解决这个问题,因为我绝对害怕 AppleScript。
我无法找出 OSX 上的错误。当我尝试查看 Curl 何时完成时,进程仍处于加载状态。我从来没有看到 CURL FINISHED 消息。
#!/bin/bash
curl -S -o example.com http://example.com/downloads/example.zip &
CURL_PID=$!
echo -e "CURL PID = $CURL_PID"
while :
do
sleep 1
if [ -n $(ps -p$CURL_PID -o pid=) ]; then
echo "CURL NOT FINISHED"
else
echo "CURL FINISHED"
break
fi
done
注意 OSX 版本的 Bash 当我 运行 这个:
#!/bin/bash
PIDX=1
if [ -n $(ps -p$PIDX -o pid=) ]; then
echo "PROCESS 1 IS THERE"
else
echo "PROCESS 1 IS NOT THERE"
fi
...它说进程 1 在那里。 (每个人都有一个 PID 1,所以这只是一个例子。)所以,我知道我的 if
语句是正确的。 if
行不需要双引号。
请注意,我不能在 $CURL_PID
上使用等待,因为您在这里看不到的是我也在使用 OSX 的 osascript
命令来显示显示 "Downloading..." 的对话框,上面还有一个取消按钮和它自己的 $DLG_PID
,所以我一直循环直到他们取消对话框(意思是 $DLG_PID
点消失了)或者 $CURL_PID
不见了(意味着下载终于完成了,所以我现在可以 运行 kill $DLG_PID
)。
在 OSX 上,请注意我也在 curl
声明之前这样做。
osascript -e 'tell app "System Events" to display dialog "Downloading..." with title "My App Installer" buttons {"Cancel"}' &
因此,如果有人取消对话,我会通过 PID 终止 curl 并退出无限循环(并退出 bash 脚本)。如果他们不取消该对话框,并且 curl 完成,那么我将通过 PID 终止该对话框并退出 bash 脚本。
通常您会为此使用 wait
:
curl http://... &
do_something
wait
echo "CURL has finished"
轮询后台作业的可移植方法是使用 kill
内置函数,并发送信号 0
以查看它是否可交付。如果子进程仍然是 运行,kill -0 $pid
(其中 $pid
是子进程的 PID)将 return 为零,如果它已经死亡,则为非零。请注意,对于子进程(而不是从别处启动的某个随机进程,将 PID 写入 PID 文件),这是安全的 仅 安全(来自 PID 回收),原因概述 here:
Each UNIX process also has a parent process. This parent process is the process that started it, but can change to the init process if the parent process ends before the new process does. (That is,
init
will pick up orphaned processes.) Understanding this parent/child relationship is vital because it is the key to reliable process management in UNIX. A process's PID will NEVER be freed up for use after the process dies UNTIL the parent process waits for the PID to see whether it ended and retrieve its exit code. If the parent ends, the process is returned toinit
, which does this for you.This is important for one major reason: if the parent process manages its child process, it can be absolutely certain that, even if the child process dies, no other new process can accidentally recycle the child process's PID until the parent process has waited for that PID and noticed the child died. This gives the parent process the guarantee that the PID it has for the child process will ALWAYS point to that child process, whether it is alive or a "zombie". Nobody else has that guarantee.
当然,较新版本的OSX不使用init
(取而代之的是launchd
),但原理是一样的。
顺便说一下,整个页面都值得一读:http://mywiki.wooledge.org/ProcessManagement。
鉴于此,这里有一个示例脚本可以执行您想要的操作(它需要一个 URL 参数——下载 URL)。如果有什么不清楚的地方请打扰我。
#!/usr/bin/env bash
osascript -e 'tell app "System Events" to display dialog "Downloading..." with title "Downloader" buttons {"Cancel"}' &>/dev/null &
dialog_pid=$!
curl -sSLO "" &
curl_pid=$!
timer=0
while kill -0 "$curl_pid" &>/dev/null; do
kill -0 "$dialog_pid" &>/dev/null || { echo "User cancelled download from dialog."; kill "$curl_pid" &>/dev/null; exit 1; }
sleep 1
(( timer++ ))
echo "Been downloading for $timer seconds..."
done
echo "Finished."
kill "$dialog_pid" &>/dev/null
wait &>/dev/null
运行它:
> ./download https://github.com/torvalds/linux/archive/v4.4-rc2.tar.gz
Been downloading for 1 seconds...
Been downloading for 2 seconds...
<omitted>
Been downloading for 38 seconds...
Finished.
中途取消:
> ./download https://github.com/torvalds/linux/archive/v4.4-rc2.tar.gz
Been downloading for 1 seconds...
Been downloading for 2 seconds...
Been downloading for 3 seconds...
User cancelled download from dialog.
丑陋的是,杀死 osascript
作业的 PID 并没有关闭对话框...我无法解决这个问题,因为我绝对害怕 AppleScript。