对上面的答案补充几点:
- 根据@cuonglm的建议,使用'&'在后台启动进程并等待其pid,可以使处理程序在子进程运行时执行,但子进程将失去捕获任何输入的能力,因为stdin会在子进程分离后关闭。为了强制stdin保持打开状态,您可以添加一个无限循环,并将其管道传输给子进程。请参见this post。
然后,在当前shell中读取输入并将其写入子进程的proc文件,以便将其发送到其stdin:
(while true; do sleep 10000; done) | /bin/start/main/server --nodaemon &
child_pid=$!
while :
do
result=$(kill -0 $mypid > /dev/null 2>&1)
if [ $? -ne 0 ] ; then
# process is gone
break
else
# read input in the current shell and store it in a variable. The timeout only works with Bash, not with Bourne-Shell. You will need to find a way to read stdin instead and sleep 1 sec between each loop
read -t 1 input
# echo the input to the proc file of the runuser process so it goes to its stdin
echo $input > /proc/$child_pid/fd/0 2>/dev/null
fi
done
wait $child_pid
注意:这在Linux上运行得很好,但可能需要一些调整才能在其他Unix平台上使用。
编辑:一个更简单的方法是将stdin复制到一个文件描述符中,然后可以将其作为后台进程的stdin使用。
exec 3<&0
/bin/start/main/server --nodaemon <&3 &
exec是第二个解决方案,如@Stuart P. Bentley所建议的,但有时您需要使用新的进程ID创建进程,或者所使用的命令可能不让您选择并创建带有新PID甚至新PGID的进程(例如,对于带有-l选项的runuser)。
除了针对特定PID进行定位外,另一种方法是向进程组发送信号。
可以通过在子进程的PID之前使用减号(-)来实现:
kill -TERM -$child_pid
Bash确实可以让您捕获针对进程组的信号,而无需将进程放在后台运行。此方法不会丧失子进程读取stdin的能力。如果子进程在不同的进程组中运行,这也是一个很好的解决方案,因为处理程序将允许您将信号转发给子进程。限制是组中的其他成员也将接收到该信号,这可能是一个问题,也可能不是,具体取决于场景。
wait
调用? - iruvar等待
是我们脚本的需要...等待子进程完成。我们希望确保在子进程终止后,脚本才会退出。 - cuonglmexec /bin/start/main/server --nodaemon
(在这种情况下,shell进程被服务器进程替换,你不需要传播任何信号),要么你使用/bin/start/main/server --nodaemon &
,但是exec
实际上没有什么意义。 - Andreas Veithenexec
,所以 Bash 进程将保留在服务器进程周围,以便在信号处理时进行清理。 - Stuart P. Bentleyexec command &
会在子shell中启动命令,并且在新的shell中,exec
将用主程序替换当前的shell。我不记得最后一次编辑时删除了exec
部分,导致我的解释不正确。 - cuonglm_term()
函数中,你应该再次使用wait "$child"
。这可能是必要的,如果你有其他监控进程在等待shell脚本死亡之前重新启动它,或者如果你也捕获了EXIT
来进行一些清理工作,并且需要它在子进程完成后才运行。 - LeoRochaelman
和我的本地测试,我认为bash
只在交互模式
下忽略SIGTERM信号。其他方面答案很好。 - akostadinovset -o forwardsignals
,或者其他任何方式。 - Alexander Millsexec
命令(https://unix.stackexchange.com/a/196053/7733),或者你想要设置陷阱(https://unix.stackexchange.com/a/444676/7733)。 - Stuart P. Bentleychild=$!
之前发送,子进程将无法设置并且kill命令会报错。为了修复这个问题,陷阱处理程序应该直接使用$!
。 - Igor Bukanov