Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何检查何时从Bash循环执行Curl PID_Bash_Curl_Background Process - Fatal编程技术网

如何检查何时从Bash循环执行Curl PID

如何检查何时从Bash循环执行Curl PID,bash,curl,background-process,Bash,Curl,Background Process,我想不出我在OSX上的错误。当我尝试查看Curl何时完成时,进程仍然处于加载状态。我从来没有看到这个消息 #!/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

我想不出我在OSX上的错误。当我尝试查看Curl何时完成时,进程仍然处于加载状态。我从来没有看到这个消息

#!/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\u PID
上使用wait,因为您在这里看不到的是,我还使用OSX的
osascript
命令来显示一个对话框,上面写着“下载…”,该对话框上还有一个取消按钮和它自己的
$DLG\u PID
,因此我一直循环,直到他们取消该对话框为止(意思是
$DLG\u PID
点不见了)或
$CURL\u PID
不见了(意思是下载终于完成了,我现在可以运行
kill$DLG\u 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脚本。

通常您将使用
等待

curl http://... &
do_something
wait
echo "CURL has finished"

通常您会使用
wait

curl http://... &
do_something
wait
echo "CURL has finished"

轮询后台作业的可移植方法是使用
kill
内置,并发送信号
0
,以查看它是否可交付。
kill-0$pid
(其中
$pid
是子进程的pid)如果子进程仍在运行,则返回零;如果子进程已死亡,则返回非零。请注意,对于子进程(而不是其他地方启动的随机进程,将PID写入PID文件),这是安全的且仅安全的(从PID回收),原因如下:

每个UNIX进程也有一个父进程。此父进程是启动它的进程,但如果父进程在新进程结束之前结束,则可以更改为init进程。(即,
init
将拾取孤立进程。)理解此父/子关系至关重要,因为它是UNIX中可靠进程管理的关键。在父进程等待PID查看其是否结束并检索其退出代码之前,进程的PID将永远不会释放出来供使用。如果父进程结束,进程将返回到
init
,w这是他为你做的

这一点很重要,因为有一个主要原因:如果父进程管理其子进程,则可以绝对确定,即使子进程死亡,在父进程等待该PID并注意到子进程死亡之前,其他新进程也不会意外地回收子进程的PID。这为父进程提供了保证子进程的PID始终指向该子进程,无论它是活动的还是“僵尸”。没有其他人有这种保证

当然,较新版本的OS X不使用
init
(取而代之的是
launchd
),但原理是一样的

顺便说一下,整个页面值得一读:

有鉴于此,下面是一个示例脚本,它实现了您想要的功能(只需要一个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 "$1" &
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.

丑陋的是,杀死
osascript
作业的PID并不会关闭对话框……我无法解决这个问题,因为我非常害怕AppleScript。

轮询后台作业的可移植方法是使用
kill
内置程序,并发送信号
0
,查看它是否可交付。
kill-0$pid
(其中,
$pid
是子进程的pid)将在子进程仍在运行时返回零,如果子进程已经死亡,则返回非零。请注意,对于子进程(而不是在别处启动的、pid写入pid文件的随机进程),这是安全的,并且是唯一安全的(pid回收),原因如下:

每个UNIX进程也有一个父进程。此父进程是启动它的进程,但如果父进程在新进程结束之前结束,则可以更改为init进程。(即,
init
将拾取孤立进程。)理解此父/子关系至关重要,因为它是UNIX中可靠进程管理的关键。在父进程等待PID查看其是否结束并检索其退出代码之前,进程的PID将永远不会释放出来供使用。如果父进程结束,进程将返回到
init
,w这是他为你做的

这一点很重要,因为有一个主要原因:如果父进程管理其子进程,则可以绝对确定,即使子进程死亡,在父进程等待该PID并注意到子进程死亡之前,其他新进程也不会意外地回收子进程的PID。这为父进程提供了保证子进程的PID始终指向该子进程,无论它是活动的还是“僵尸”。没有其他人有这种保证

当然,较新版本的OS X不使用
init
(取而代之的是
launchd
),但原理是一样的

顺便说一下,整个页面值得一读:

有鉴于此,下面是一个示例脚本,它实现了您想要的功能(只需要一个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 "$1" &
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.
丑陋的是,杀死
osascript
作业的PID并不会关闭对话框……我无法解决这个问题,因为我非常害怕AppleScript。

首先,“Bash bug”这个短语并不是你想要的意思……其次,那是什么意思?
#!
拜托。第三,
$(附言)
需要引用。一旦