【问题标题】:Trap ctrl-c, run a function, but don't exit subprocess?陷阱ctrl-c,运行一个函数,但不退出子进程?
【发布时间】:2017-10-24 23:25:13
【问题描述】:

它实际上是作为 bash 脚本的子进程启动的 Scala REPL。

我想改变 ctrl-c 的作用,但不干扰 scala REPL。

function ctrl_c_handler() {
  # do some stuff, but don't exit
}

trap ctrl_c_handler SIGINT

scala

有趣的是,忽略信号可以正常工作trap '' SIGINT。 ctrl-c 不能杀死我的 REPL,但如果我真的附加了一个函数,我无法阻止进程退出。

有哪些选择? scala REPL 需要在前台。 ctrl_c_handler 可以启动后台进程。

【问题讨论】:

  • 我认为这是不可能的,除非有一些非常聪明的“跳回到我在 ^C 之前的脚本中的位置”,您可以在 @987654323 的末尾放置这些命令集@.

标签: bash scala


【解决方案1】:

一旦子进程启动,Bash 将看不到终端输入或终端生成的信号(例如 SIGINT),因为子进程成为终端前台进程组的唯一成员。一旦子进程终止,Bash 只会再次看到终端。

在 bash 中忽略 SIGINT 有效,因为子进程继承了尚未分配信号处理程序的信号的处置。

您可以使用stty 将 SIGINT 重新分配给不同的键盘符号(或无键盘符号);子进程也将继承该设置。这将导致 ctrl-C 成为普通字符,因此不会中断子进程。不幸的是,它也不会中断 bash,所以这不是真正的解决方案。

您可以创建一个子进程,通过创建一个伪终端 (pty) 并将子进程附加到伪 tty 的从属端,您可以对其施加更多控制。然后,您可以通过将数据写入 pty 的主端,将从终端读取的输入传递到子进程,并通过从主端读取并写入终端,将子进程的输出传递回终端。在此配置中,您可以在主进程中捕获 SIGINT,而不将其传递给子进程。但是,您几乎可以肯定需要用某种语言(不一定是 C)来编写它,这样您就可以访问系统设施;这可能在 bash 中是可能的,但这将是一个相当大的技巧。阅读man pty,了解更多关于从哪里开始的信息。

【讨论】:

  • 有道理。我寻找从内部修补 REPL 的猴子方法,但它很快就变黑了。自定义 REPL 本身几乎是不可能的(它实际上是一个火花壳,因此一直是海龟)。听起来像明确放置一个选择性地将输入转发到 REPL 过程的层是最好的方法。我去看看 pty。
猜你喜欢
  • 2013-06-25
  • 1970-01-01
  • 1970-01-01
  • 2020-06-22
  • 1970-01-01
  • 2015-10-07
  • 1970-01-01
  • 2014-08-11
  • 2019-05-20
相关资源
最近更新 更多