bash:如果子进程失败,避免获取父进程的PID

bash:如果子进程失败,避免获取父进程的PID

(原标题 - 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.

相关内容