(原标题 - bash:在后台运行命令并捕获 pid)
注意这不是另一个问题的[重复],因为它解决了 bash 的意外行为,其中子进程启动失败(例如由于“找不到命令”)可以将设置保留
$!
为调用进程的 pid,而不是失败子进程的 pid 或“”(空)。 ——文档萨尔瓦格
我正在编写 bash 4.1 脚本...
- 想要在后台运行另一个脚本(或内部函数)...
- 并在前台脚本的变量中捕获该后台作业的 pid...
- 如果作业没有启动,变量应该为空(即“”)。
如果后台作业总是启动,那么这两种方法都可以工作......
cmd &
VAR=$!
or...
( cmd & ); VAR=$!
如果cmd
运行,最后一个命令启动的 pid ($!) 将是我们想要的,并且 $VAR 将是正确的。
但是,如果cmd
没有启动,$VAR 将是最后一个命令的 pid在那之前启动的可能是前台脚本本身的 pid。由于我需要 pidcmd
以便稍后在某些条件下终止进程,因此可能获取错误的 pid 是行不通的。
我真正需要的是只有在后台作业运行时才更改 VAR。诸如语法错误之类的...
VAR=
( cmd & ); && VAR=$!
实施的解决方案
这些评论和 Joseph R 的回答非常有帮助。为了有类似问题的人的利益......
以下 bash 函数standby
在后台运行 GtkDialog 脚本。在一个本身在子进程中运行的函数内部,似乎提供了我需要的隔离,以避免standby
在失败时获取调用脚本的 PID 而不是脚本的 PID standby
...
function standbyBg () {
ifHelpShow "$1" 'standbyBg
Run standby (busy "throbber") in background and echo its pid.
Example:
standbyPID=$(standbyBg)
Revised:
20131123 docsalvager' && return
#
standby >/dev/null 2>&1 &
echo $!
}
答案1
有点黑客的解决方法:
jobs &>/dev/null
cmd &
new_job_started="$(jobs -n)"
if [ -n "$new_job_started" ];then
VAR=$!
else
VAR=
fi
感谢 @terdon 的评论将我的注意力引向help jobs
.