2

对于某些信号,例如 SIGINT,我可以很容易地设置一个陷阱来处理信号并继续执行我认为合适的。我想将 ^q 和 ^s 的典型行为添加到我正在摆弄的 ruby​​ 命令行应用程序中。有没有办法做到这一点 - 特别是便携的,所以我可以在 Windows、iOS、Linux 和 Solaris 中使用它?

编辑:

事实证明,信号永远不会传递给进程。事实上,在进程及其父进程(一个 bash 实例)上运行 strace 表明,进程和父进程都没有得到任何关于正在发生的事情的迹象。他们只是被暂停。

我可能会尝试让一个每秒触发一次的 SIGALARM 处理程序,检查自上次警报以来是否已经过去了超过一秒,如果得出结论该进程已暂停,则进行适当的调用。在负载较重的系统上会出现误报。

4

2 回答 2

1

在 irb 中输入Signal.list。它将列出您应该能够捕获的所有信号。

在 ruby​​ 中捕获信号:

Signal.trap("STOP") do
  # handle the signal
end

在终端输入$ stty -a. 它应该列出信号及其相关的组合键(如果有的话)。

我相信 ^s 通常是stop^q 是start.

虽然根据这个答案,那些键组合实际上并没有向正在运行的进程发送信号,而是向终端驱动程序发送信号。在这种情况下,kill -STOP <process>可以将该信号发送到您的进程。

于 2012-09-11T21:05:39.200 回答
1

TL;DR 不,您不能捕获它们,因为它们不会产生信号,并且终端下的进程看不到它们,只能启发式地检测它们。但是,如果要能够在终端程序中使用这些键绑定,那么可以,您可以通过禁用终端对它们的特殊处理来做到这一点。

^q并且^s不会产生信号。这^z不是^s导致终端信令SIGSTOP(编辑:实际上是SIGTSTP)。

什么^s是告诉终端不要读取正在写入它的进程的输出。这会导致进程在写入终端时阻塞(它们仍然可以写入其他地方并从标准输入读取,以及执行其他操作)[1]。^q告诉终端继续读取和显示进程输出。将终端作为标准输入的进程看不到这些。终端看到键绑定,对其进行操作,并且不会将它们传递给从其终端设备读取的进程。

您可以使用 禁用此特殊行为stty -ixon,然后使用 重新启用它stty ixon。当我禁用它时,我键入时读取的进程说^s是 byte 0x13,并且^q是 byte 0x11

[1] 作为展示这一点的实验,您可以打开 2 个终端窗口。tty在第二个上执行以找到它的终端设备。然后,在第一个终端上,您可以作为第二个终端tee $TTY > $OTHER_TTY$OTHER_TTY终端设备运行。完成此操作后,您可以点击^s以阻止对终端的写入,并通过键入一些行来检查这一点。该行将显示在第二个终端中,但不会显示在第一个终端中,此后您输入的任何内容都不会显示在任何一个终端上,直到您点击^q。这里发生的情况是,在您点击^s并键入一行之后,tee仍然可以读取它,并将其输出到我们重定向到第二个终端的 stdout。然后,当它尝试将其写入作为参数传递的第一个文件时,它被阻止,因为它是您阻止的终端^s. 它呆在那里等待write()返回,直到你击中它才会返回^q

于 2018-09-18T21:05:25.110 回答