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

Doc*_*ger 21 bash process background-process

(以前的标题 - bash:在后台运行命令并捕获 pid)

注意这不是另一个问题的 [DUPLICATE],因为它解决了 bash 的意外行为,其中子$!进程启动失败,比如由于“找不到命令”,可以将设置保留为调用进程的 pid 而不是失败子进程的 pid 或 "" (null)。-- 文档打捞者

我正在编写 bash 4.1 脚本...

  • 想在后台运行另一个脚本(或内部函数)...
  • 并在前台脚本的变量中捕获该后台作业的 pid ...
  • 如果作业未启动,则变量应为空值(即“”)。

如果后台工作总是开始,那么这些工作中的任何一个都可以工作......

cmd &
VAR=$!

or...

( cmd & ); VAR=$!
Run Code Online (Sandbox Code Playgroud)

如果cmd运行,最后启动的命令的 pid ($!) 将是我们想要的,而 $VAR 将是正确的。

但是,如果cmd没有启动,$VAR 将是启动之前的最后一个命令的 pid,这可能是前台脚本本身的 pid。由于我需要 pidcmd以便稍后在某些条件下终止进程,因此可能无法获得错误的 pid。

我真正需要的是只有在后台作业运行时才更改 VAR。像语法不正确的东西......

VAR=
( cmd & );  && VAR=$!
Run Code Online (Sandbox Code Playgroud)

实施方案

评论和 Joseph R 的回答非常有帮助。为了任何有类似问题的人的利益......

以下 bash 函数standby在后台运行 GtkDialog脚本。在一个本身在子进程中运行的函数内部,似乎提供了隔离我需要避免获取调用脚本的 PID 而不是脚本的 PIDstandby如果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 $!
}
Run Code Online (Sandbox Code Playgroud)

Jos*_* R. 8

有点hackish的解决方法:

jobs &>/dev/null
cmd &
new_job_started="$(jobs -n)"
if [ -n "$new_job_started" ];then
    VAR=$!
else
    VAR=
fi
Run Code Online (Sandbox Code Playgroud)

感谢@terdon 的评论将我的注意力引向help jobs.

  • 不错的黑客,+1。如果你只是运行`jobs -p | wc -l` 在启动 `cmd` 之前执行一次,然后再执行一次并比较数字,即使有其他后台作业也可以执行。 (2认同)