重新获得使用 ^C 关闭后台然后(有效)前台进程的能力

重新获得使用 ^C 关闭后台然后(有效)前台进程的能力

在交互式控制台中,按^C关闭zenity --info & fgZenity 窗口。只能zenity --info & wait在脚本中使用。但^C在这种情况下不会关闭 Zenity 窗口。有没有什么办法可以让wait行为变得更像fg工作^C

答案1

您可以做的最简单的事情就是捕获SIGINT(^C) 并从处理程序中终止后台进程:

#! /bin/sh
trap 'kill "$!"; exit 1' INT QUIT
zenity --info &
wait

以及其他类似的答案对此行为的解释。

当从某些 shell 调用脚本时,例如bash实现所谓的《等待并配合退出》(看这里供讨论),程序在收到信号后干净退出的预期方法是重置处理程序,然后用相同的信号杀死自身:

#! /bin/sh
termsig(){ trap - "$1"; kill "$!"; kill -s "$1" "$$"; }
trap 'termsig INT' INT
trap 'termsig QUIT' QUIT 
zenity --info &
wait

当然,所有这些都是相当粗俗的,并且无法对zenity本身可能产生的子进程做任何事情,并且必须针对多个后台进程进行调整。更明显的解决方案(trap - INT; zenity --info) &不是/bin/sh与任何 Debian 衍生发行版(Ubuntu 等)或任何基于 busybox 的系统一起使用。

另一个解决方案是通过包装器运行您的程序,该包装器允许您将SIGINT配置重置为默认值,例如。和perl

#! /bin/sh
perl -e '$SIG{INT} = $SIG{QUIT} = "DEFAULT"; exec @ARGV' zenity --info &
wait

perl但如果你这样做,你也可以用or重写整个脚本python;-)

答案2

在非交互式中sh,命令异步运行,并&忽略其 SIGINT 和 SIGQUIT 信号。

tcsetpgrp()这是 POSIX 的要求,可以追溯到终端作业控制 ( ...) 不存在的时代。如今,它通常会成为障碍。

另一个来自同一来源的 POSIX 要求是,当 shell 启动时忽略信号时,不能使用 来取消忽略该信号trap。再说一遍,如今,这是不受欢迎且令人讨厌的行为。

zsh仅部分实现了后一个要求。恢复trap - SIGNAL默认配置的忽略SIGNAL被忽略,但trap handler SIGNAL安装handlerfor SIGNAL 即使该信号在启动时被忽略,因此如果他们确实想要使用 .a 仍然可以恢复默认配置trap : SIGNAL; trap - SIGNAL

只要脚本中不忽略 SIGINT(例如当脚本在后台运行时),您就可以执行以下操作:

#! /bin/sh -
(trap - INT QUIT; exec zenity) & wait

恢复 SIGINT 和 SIGQUIT 的默认配置。

然而,尽管 POSIX 明确表示它应该可以工作,它不需要一些sh实现。特别是,不适用于dash和大多数其他ash导数,ksh93boshyash。因此,您可能需要将 she-bang 更改为#! /bin/bash -or #! /bin/zsh -or#! /bin/mksh -以确保在本例中您有一个符合 POSIX 标准的 shell。

如果 SIGINT 在 shell 启动时被忽略,您需要使用以下命令zsh来恢复它们的配置:

#! /bin/zsh -
trap : INT QUIT # noop handler to unignore
trap - INT QUIT # restore default disposition for the shell
(trap - INT QUIT; zenity) & wait

示例(此处在 Linux 上,信号配置在 中以位图形式公开/proc/<pid>/status):

$ sh -c 'grep SigIgn /proc/self/status'
SigIgn: 0000000000000000
$ sh -c 'grep SigIgn /proc/self/status & wait'
SigIgn: 0000000000000006 # (1<<(SIGINT-1) | 1<<(SIGQUIT-1))

$ zsh -c '(trap - INT QUIT; exec grep SigIgn /proc/self/status) & wait'
SigIgn: 0000000000000000
$ bash -c '(trap - INT QUIT; exec grep SigIgn /proc/self/status) & wait'
SigIgn: 0000000000000000
$ mksh -c '(trap - INT QUIT; exec grep SigIgn /proc/self/status) & wait'
SigIgn: 0000000000000000

$ dash -c '(trap - INT QUIT; exec grep SigIgn /proc/self/status) & wait'
SigIgn: 0000000000000006
$ ksh93 -c '(trap - INT QUIT; exec grep SigIgn /proc/self/status) & wait'
SigIgn: 0000000000000006
$ yash -c '(trap - INT QUIT; exec grep SigIgn /proc/self/status) & wait'
SigIgn: 0000000000000006
$ bosh -c '(trap - INT QUIT; exec grep SigIgn /proc/self/status) & wait'
SigIgn: 0000000000100006  # also SIGTTIN

$ (bash -c 'grep SigIgn /proc/self/status' & wait)
SigIgn: 0000000000000006
$ (bash -c 'trap - INT QUIT; grep SigIgn /proc/self/status' & wait)
SigIgn: 0000000000000006

$ (zsh -c 'grep SigIgn /proc/self/status' & wait)
SigIgn: 0000000000000002 # not sure why the SIGQUIT was unignored
$ (zsh -c 'trap - INT QUIT; grep SigIgn /proc/self/status' & wait)
SigIgn: 0000000000000002
$ (zsh -c 'trap : INT QUIT; trap - INT QUIT; grep SigIgn /proc/self/status' & wait)
SigIgn: 0000000000000000

相关内容