我有一个 bash 脚本,除其他外,它还启动后台进程。我使用一个函数为进程设置一些配置,启动它,检查它是否正确启动,然后返回它的 PID,稍后用它来终止子进程。下面的示例代码具有相同的结构,但简化了逻辑:
function launcher(){
sleep 30 &
echo $!
}
PID=$(launcher)
echo $PID
kill $PID
我面临的问题是,执行
launcher
函数的子 shell 在 sleep
命令结束之前不会返回。因此,直到子 shell 结束时才会执行 echo $PID
语句。
令我惊讶的是,如果我检查
sleep
命令,它没有脚本作为父 ID:
UID PID PPID C STIME TTY STAT TIME CMD
user 20135 1 0 18:39 pts/8 S+ 0:00 sleep 30
如何在后台启动
sleep &
,让子shell在结束之前结束?
注意:请注意,在我的例子中,后台进程永远不会结束,直到我杀死它,所以我需要子shell来结束获取PID。另请注意,在我的实际代码中,
launcher
函数的逻辑非常复杂,我将其作为子shell运行以将主进程与其隔离。
提前致谢
问题恰好与
stdin
有关,因为主 shell 正在从子 shell 的 stdout
读取内容,而该子 shell 是由后台进程继承的。只需在调用后台进程时重定向 stdout
即可使其按预期工作。
sleep 100 > /dev/null &
我不确定这是否能完成但是
function launcher(){
echo "start launching"
sleep 100 &
echo "end launching"
}
launcher
PID=$!
# Here $PID is the process id of `sleep`
echo $PID
kill $PID
如果没有
kill
,这将运行分叉的 sleep
命令,并且 shell 脚本结束,留下 sleep
命令以 PID
中设置的 pid 运行,这意味着您可以稍后杀死它。
这是您需要的吗? 如果没有,你能澄清一下你的期望吗?
我还注意到,如果父脚本保持活动状态,则睡眠进程的 PPID 是正确的并且保持不变。
# sleeper_test.sh
#!/bin/bash
function launcher(){
echo "start launching"
sleep 100 &
echo "end launching"
}
launcher
PID=$!
# Here $PID is the process id of `sleep`
echo $PID
sleep 10
#kill $PID
$ ps -ef | grep sleep
501 13748 5471 0 1:54PM ttys000 0:00.00 /bin/bash ./sleeper_test.sh
501 13749 13748 0 1:54PM ttys000 0:00.00 sleep 100 <- child correctly tied to the parent sh script
501 13750 13748 0 1:54PM ttys000 0:00.00 sleep 10
$ ps -ef | grep sleep
501 13749 1 0 1:54PM ttys000 0:00.00 sleep 100 <- since the parent ended - it's parent becomes the root process parent
``