提问人:Gigi Bayte 2 提问时间:2/27/2023 更新时间:2/28/2023 访问量:98
阻止具有后台进程的子 shell 接收 SIGINT,尽管在前台捕获信号
Stop subshell with background process from receiving SIGINT despite trapping signals in the foreground
问:
假设我有一个在前台运行的函数。此函数捕获 SIGINT 并忽略 EOF(用于防止 Control + C 和 Control + D)。此函数创建一个在后台运行命令的子 shell。
我认为 SIGINT 会被主功能捕获。但是,在运行 main 函数时使用 Control + C 仍会导致子 shell 接收 SIGINT 并在预期之前被杀死。
我还尝试为 SIGINT 添加陷阱并忽略子 shell 本身中的 EOF,但这似乎也不起作用。
下面是一个相对最小的示例,它使用 mpv 命令封装了问题:
function play_video_until_yes {
trap '' 2
set -o ignoreeof
videourl="$1"
read -r mpv_pid < <(mpv --loop "$videourl" --no-video &>/dev/null & echo $!)
while true; do
read -rp "Input y for yes: " answer
if [[ "$answer" = "y" ]]; then
break
fi
printf "\nIncorrect. Try again.\n"
done
kill "$mpv_pid" >/dev/null
trap 2
set +o ignoreeof
}
可以使用任何 YouTube 视频的命令行参数(例如)运行此函数,并在主进程要求用户输入时按 Control + C。这会导致子 shell 退出,可能是由于 SIGINT。play_video_until_yes "https://www.youtube.com/watch?v=usNsCeOV4GM"
答:
0赞
Gigi Bayte 2
2/28/2023
#1
我对此做了相当多的研究,并能够找到一个答案。它有效,但不太理想。
我必须在我的 Mac 上安装一个名为 via Homebrew 的单独软件包才能获得该命令。然后,我可以使用该命令在单独的进程组中运行该命令,以防止将 SIGINT 转发到它。util-linux
setsid
mpv
所以,这是我的解决方案之后的样子:
function play_video_until_yes {
trap '' 2
set -o ignoreeof
videourl="$1"
read -r mpv_pid < <( /opt/homebrew/opt/util-linux/bin/setsid mpv --loop "$videourl" --no-video &>/dev/null & echo $!)
while true; do
read -rp "Input y for yes: " answer
if [[ "$answer" = "y" ]]; then
break
fi
printf "\nIncorrect. Try again.\n"
done
kill "$mpv_pid" >/dev/null
trap 2
set +o ignoreeof
}
我仍然更喜欢使用macOS上已经存在的命令的解决方案,但这个解决方案目前仍然站稳脚跟。
评论