从 bash 中的标准输入读取时如何处理中断信号

How to handle interrupt signal when reading from stdin in bash

我正在尝试 bash 读取功能。到目前为止,我喜欢在当前 shell 之上的一个简单层。 read -e 执行 tab-complete 和之前的命令,使用 ctrl+d 发送 EOF 让我回到原来的 shell。这是我的参考:

Bash (or other shell): wrap all commands with function/script

我需要一些处理 SIGINT 的帮助,ctrl+c。在正常的 shell 中,如果您开始键入并半按 ^C,它会立即结束该行。对于这个简单的示例,在 ^C 之后,我仍然必须在注册之前点击 return。

如何保持 readline 的优点,但仍能正确处理 SIGINT?理想情况下,它会向 while read 循环发送一个 continue 语句,或者以某种方式将 \n 发送到我正在等待读取的 STDIN。

示例代码:

#!/bin/bash
# Emulate bash shell

gtg=1

function handleCtrl-C {
    # What do I do here?
    gtg=0
    return
}

trap handleCtrl-C INT

while read -e -p "> " line
do
    if [[ $gtg == 1 ]] ; then
        eval "$line"
    fi
    gtg=1
done

阅读 man 7 signal 表明某些系统调用设置了可重启标志,因此将 return 返回到命令

For some system calls, if a signal is caught while the call is executing and the call is prematurely terminated, the call is auto-matically restarted. Any handler installed with signal(3) will have the SA_RESTART flag set, meaning that any restartable system call will not return on receipt of a signal. The affected system calls include read(2), write(2), sendto(2), recvfrom(2),sendmsg(2), and recvmsg(2) on a communications channel or a low speed device and during a ioctl(2) or wait(2). However, calls that have already committed are not restarted, but instead return a partial success (for example, a short read count). These semantics could be changed with siginterrupt(3).

您可以尝试将输入的值打印到行并验证读取在 CtrlC return 后恢复,直到命中新行。输入类似 "exit" 的内容,然后按 Ctrl-C,然后输入 "exit",输出结果为 "exitexit"。对上述测试用例

进行以下更改和运行
echo ">$line<"
if [ $gtg == 1 ] ; then

您将输出为

您也可以使用 C 程序验证这一点。

我想我终于想出了一些我喜欢的东西。请参阅 SIGINT to cancel read in bash script? 以获得该答案。