我否认前台进程的方法需要花费太多精力。
zsh
假设我在前台有一个进程。我想要disown
它,这样我就可以关闭 shell,而无需向进程发送SIGHUP
.
目前,我从Ctrl+开始z进入后台并暂停该过程,然后
$ disown
disown: warning: job is suspended, use `kill -CONT -32240' to resume
$ kill -CONT -32240
$
—然后我可以关闭终端。
我怎样才能自动化呢?理想情况下,我希望能够按Ctrl+j或其他键立即否认正在运行的进程。或者第二好,我希望能够运行一个命令来否认和SIGCONT
暂停进程。
答案1
当您在终端中按Ctrl+Z时,这会导致前台进程组接收信号 SIGTSTP(假设终端处于烘焙模式并且默认键绑定已就位)。如果进程没有为SIGTSTP设置信号处理程序,这会导致进程被挂起(即使进程设置了信号处理程序,它在挂起之前通常也只进行少量处理)。当进程被终止、挂起或恢复时,其父进程会通过 SIGCHLD 信号得到通知;这就是导致 shell 显示新提示符以及类似消息的原因[1] + 1234 suspended foo
。信息流是
key→suspension→shell
而不是
key→shell→suspension
,因此您无法为Ctrl+配置不同的反应Z。
您可以为SIGCHLD设置陷阱,但当作业是当前前台作业时,陷阱不会执行。在大多数情况下,这意味着陷阱仅在后台作业终止时执行,而不是在前台作业终止时执行。但这也意味着你无法对前台作业的暂停做出反应。
precmd
您可以通过设置一个挂钩来将作业状态与上次precmd
运行保存的状态进行比较,从而间接对后台作业中的更改做出反应。但我不知道你能用它做什么:只能有一个暂停键,所以你需要一些额外的信息来知道该进程是否要暂停、后台运行或否认。
我已经设置了 zsh,以便在空提示符下按Ctrl+Z可以将当前作业背景化。这让我可以按Ctrl+Z两次将前台作业放入后台,只需短暂的暂停。
fancy-ctrl-z () {
if [[ $#BUFFER -eq 0 ]]; then
bg
zle redisplay
else
zle push-input
fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z
disown
如果你愿意的话,可以打电话。或者您可以安排第三个Ctrl+通过以下未经测试的修改Z进行调用。disown
fancy-ctrl-z () {
if [[ $#BUFFER -eq 0 ]]; then
if (($fancy_ctrl_z_already_bg)); then
disown
else
bg
fancy_ctrl_z_already_bg=1
fi
zle redisplay
else
zle push-input
fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z
fancy_ctrl_z_precmd () {
fancy_ctrl_z_already_bg=0
}
precmd_functions+=fancy_ctrl_z_precmd
答案2
使用全局键绑定来否认前台进程是不可能的:击键是由前台进程接收的,而不是由 shell 接收的。如果你想否认它,你需要先用Ctrl+暂停它。z
然而,事实证明有一个 zsh 选项可以加速否认然后继续:有了setopt AUTO_CONTINUE
,disown
也会自动发送SIGCONT
。
所以你可以把它降到C-z
disown
.
答案3
第二种方法是,按Ctrl+然后输入和 的z组合%
&|
$ %&|
将在不需要的情况下否认该过程SIGCONT
。
从zsh内置函数(1)[添加省略号]:
SHELL BUILTIN COMMANDS … disown [ job ... ] job ... &| job ... &! … If one of the latter two forms is used, the jobs will automatically be made running …
和杂项(1)[添加省略号]:
JOBS … A job can be referred to by … the following: … %string The last job whose command line begins with string.