我试图在 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)
}