你如何停止当前的前台进程并重新执行它?

时间:2014-01-23 11:06:39

标签: zsh sigint

我经常需要重新启动服务器以查看我的更改是否正常。我将此服务器保存在shell中,因此我可以快速访问当前日志。所以这就是我在shell中输入的内容:^C!!⏎。那是send SIGINT,然后是relaunch last event in history

所以我想要输入,说^R,并得到相同的结果。

(注意:我使用zsh)

我尝试了以下内容:

relaunch-function() {
        kill -INT %% && !!
}
zle -N relaunch-widget relaunch-function
bindkey "^R" relaunch-widget

但似乎在运行我的服务器时,^ R不会传递给shell,而是传递给不注意shell的服务器。所以我看不到通用的解决方案,而测试返回值和进程名称应该是可行的。

1 个答案:

答案 0 :(得分:1)

只要作业在前台运行,键就不会传递给shell。因此,设置用​​于终止前台进程并重新启动它的键绑定将不起作用。

但是,您可以在无限循环中启动服务器,以便自动重启。假设命令的名称是run_server,您可以在shell上启动它:

(TRAPINT(){};while sleep .5; do run_server; done)

周围的括号启动一个子shell,TRAPINT(){}禁用此shell的SIGINT。 while循环将继续重新启动run_server,直到sleep退出且退出状态不为零。这可以通过sleep中断^C来实现。 (不设置TRAPINT,中断run_server也可能会中断循环)

因此,如果您想重新启动服务器,只需按^C并等待0.5秒。如果要在不重新启动的情况下停止服务器,请在0.5秒内按^C两次。

要保存一些输入,您可以为其创建一个功能:

doloop() {(
    TRAPINT(){}
    while sleep .5
    do
        echo running \"$@\"
        eval $@
    done   
)}

然后使用doloop run_server调用它。注意:您仍然需要额外的周围(),因为函数本身不会打开子shell。

eval允许使用shell结构。例如doloop LANG=C locale。在某些情况下,您可能需要使用(单个):

$ doloop echo $RANDOM
running "echo 242"
242
running "echo 242"
242
running "echo 242"
242
^C
$ doloop 'echo $RANDOM'
running "echo $RANDOM"
10988
running "echo $RANDOM"
27551
running "echo $RANDOM"
8910
^C