AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 513466
Accepted
Marko Todoric
Marko Todoric
Asked: 2019-04-20 12:41:46 +0800 CST2019-04-20 12:41:46 +0800 CST 2019-04-20 12:41:46 +0800 CST

当“选择”循环运行时,Bash 忽略 SIGINT 陷阱

  • 772

当我将“陷阱”与选择循环结合使用时,即当我尝试在显示选项时按 CTRL+C 来突破时,它只会在终端中打印 ^C。如果我从脚本中删除“陷阱”,它通常会退出,也就是说它会接受 CTRL+C。

我已经在两种不同版本的 bash 上对此进行了测试(一种随 CentOS 提供,另一种随 Fedora 提供),我对来自 Fedora(4.4.23(1)-release)的那个有问题。CentOS 附带的 Bash 版本 4.2.46(2)-release 似乎工作正常。我还在本地终端和远程(通过 ssh)上对此进行了测试。问题总是在 Fedora 方面。

我将发布代码以查看我在说什么

这个不行:

#!/bin/bash

trap exit SIGINT

select opt in One Two Three; do
        break
done

如果我要删除整个 'trap exit SIGINT' 行,它将正常工作并接受 CTRL+C 没有问题。

任何想法如何解决或绕过这个?

bash signals
  • 2 2 个回答
  • 1438 Views

2 个回答

  • Voted
  1. Best Answer
    mosvy
    2019-04-20T17:17:23+08:002019-04-20T17:17:23+08:00

    任何想法如何解决或绕过这个?

    您可以通过打开posix模式来绕过它,或者使用 --posix选项,或者暂时使用set -o posix:

    set -o posix
    select opt in foo bar baz; do
        echo "opt=$opt"
    done
    set +o posix
    

    有关此行为的解释,您可以查看内置zread()函数使用的函数read(也由 bash in 内部调用select):

      while ((r = read (fd, buf, len)) < 0 && errno == EINTR)
        /* XXX - bash-5.0 */
        /* We check executing_builtin and run traps here for backwards compatibility */
        if (executing_builtin)
          check_signals_and_traps ();   /* XXX - should it be check_signals()? */
        else
          check_signals ();
    

    由于某些特殊原因,executing_builtin仅在read显式调用内置函数时设置,而不是在由 调用时设置select。这看起来很像一个错误,而不是故意的。

    在posix模式下运行时,信号将取消read内置。在这种情况下,zreadintr()被调用,与 不同的是,在运行陷阱后zread()不会重新调用中断的系统调用。read(2)见builtins/read.def:

          if (unbuffered_read == 2)
            retval = posixly_correct ? zreadintr (fd, &c, 1) : zreadn (fd, &c, nchars - nr);
          else if (unbuffered_read)
            retval = posixly_correct ? zreadintr (fd, &c, 1) : zread (fd, &c, 1);
          else
            retval = posixly_correct ? zreadcintr (fd, &c) : zreadc (fd, &c);
    

    read有关 bash内置的“重新启动”的更多详细信息,请点击此处。

    • 6
  2. Kusalananda
    2019-04-20T13:06:14+08:002019-04-20T13:06:14+08:00

    手册中的相关部分bash是(我相信;至少它的行为是这样的):

    如果bash正在等待命令完成并接收到已设置陷阱的信号,则在命令完成之前不会执行陷阱。

    select所以你的陷阱处理程序在循环体执行之前不会被调用,因为bash它正在等待命令完成。一旦接收到输入select,陷阱处理程序将执行。

    以下修改后的脚本更好地说明了这一点:

    #!/bin/bash
    
    trap 'echo INT;exit' SIGINT
    
    select opt in One Two Three; do
        printf 'Got %s (%s)\n' "$REPLY" "$opt"
    done
    

    运行它(使用bash5.0.3),选择,然后1按,然后选择。 Ctrl+CEnter3

    $ bash script.sh
    1) One
    2) Two
    3) Three
    #? 1
    Got 1 (One)
    #? ^C
    1) One
    2) Two
    3) Three
    #? 3
    INT
    

    陷阱处理程序在当前输入 ( 3) 已被接受且select循环体之前执行时执行。

    当我按下after时,不会执行陷阱处理程序,因为在提示符处按下只会重新显示菜单。EnterCtrl+CEnterselect

    • 2

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve