在bash中从stdin读取时如何处理中断信号

时间:2016-11-19 01:27:01

标签: bash readline interactive sigint bash-trap

我正在玩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之后,我仍然需要在它注册之前点击返回。

如何保留readline所做的好事,但仍能正确处理SIGINT?理想情况下,它会向while循环发送一个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

2 个答案:

答案 0 :(得分:0)

读取man 7信号告诉某些系统调用设置了可重启标志,结果将返回命令

  

对于某些系统调用,如果在调用时捕获了信号   执行并且呼叫提前终止,呼叫是   自动重启。任何安装有signal(3)的处理程序都将   设置SA_RESTART标志,表示任何可重新启动的系统调用   收到信号后不会返回。受影响的系统调用   包括read(2),write(2),sendto(2),recvfrom(2),sendmsg(2)和   recvmsg(2)在通信信道或低速设备上   在ioctl(2)或等待(2)期间。但是,已经有的电话   已提交但未重新启动,而是返回部分成功(for   例如,短读数)。这些语义可以改变   siginterrupt(3)。

您可以尝试将值输入打印到line并验证在CtrlC返回后恢复读取,直到命中新行。输入类似“退出”的内容,然后输入Ctrl-C,然后“退出”,输出结果为“exitexit”。进行以下更改并运行上述测试用例

echo ">$line<"
if [ $gtg == 1 ] ; then

您的输出为

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

答案 1 :(得分:0)

我想我终于想出了一些我喜欢的东西。有关答案,请参见SIGINT to cancel read in bash script?