Bash:用后台作业替换命令

Bash:用后台作业替换命令

我试图在 bash 函数中触发并忘记一个进程。我想让这个函数返回一个与进程确实已被触发的事实相对应的状态,并检索函数的输出以获取子进程的 PID。所以我写道:

my_ping() {
    # ... param check which potentially return 1

    ping "$1" &
    local pid
    pid="$!"
    echo "$pid"
    return 0
}

当使用命令替换调用它时,该函数会阻塞并且永远不会返回(它不会在命令替换之外阻塞)

main() {
  
  # my_ping www.google.com # does not block and print PID

  # Blocks waiting for ping to terminate
  local mp_pid
  mp_pid=$(my_ping www.google.com)
}

main "$@"

我不明白为什么在这种情况下功能会阻塞,我尝试了各种方法(setsid、disown 等...)但没有成功,但我只是不太明白发生了什么。有什么指示可以了解这种情况吗?

答案1

您应该将输出重定向到ping默认位置(由命令替换创建的管道)之外的其他位置。只要任何进程仍然持有对该管道写入端的引用,主 shell 就不会获得 EOF,并且仍会等待以获取命令替换的所有输出。

例如将其重定向到脚本的原始标准输出:

my_ping() {
    ...
    ping "$1" >&"$out" &
    ...
}
main() {
    exec {out}>&1
    ...
    mp_pid=$(my_ping www.google.com)
}

相关内容