【问题标题】:SIGINT to cancel read in bash script?SIGINT 取消在 bash 脚本中读取?
【发布时间】:2012-10-14 23:57:20
【问题描述】:

我正在编写一个 bash 包装器来学习一些脚本概念。这个想法是在 bash 中编写一个脚本,并在登录时将其设置为用户的 shell。

我在reads 和evals 用户的输入中创建了一个while 循环,然后注意到,每当用户输入CTRL + C 时,脚本都会中止,因此用户会话结束。

为了避免这种情况,我困住了SIGINT,在圈内什么都不做。

现在的问题是,当您在命令的一半处键入 CTRL + C 时,它不会像在 bash 上那样被取消 - 它只是忽略了 CTRL + C

所以,如果我输入ping stockoverf^Cping stackoverflow.com,我会得到ping stockoverfping stackoverflow.com,而不是我想要的ping stackoverflow.com

有什么办法吗?

#!/bin/bash

# let's trap SIGINT (CTRL + C)
trap "" SIGINT

while true
do
    read -e -p "$USER - SHIELD: `pwd`> " command
    history -s $command
    eval $command
done

【问题讨论】:

    标签: bash sigint


    【解决方案1】:

    我知道这已经很老了,但我一直在努力做这样的事情并想出了这个解决方案。希望它可以帮助其他人!

    #/usr/bin/env bash
    # Works ok when it is invoked as a bash script, but not when sourced!
    function reset_cursor(){
        echo
    }
    trap reset_cursor INT
    while true; do
        command=$( if read -e -p "> " line ; then echo "$line"; else echo "quit"; fi )
        if [[ "$command" == "quit" ]] ; then
            exit
        else
            history -s $command
            eval "$command"
        fi
    done
    trap SIGINT
    

    通过将 read 放入子 shell 中,您可以确保它会被 sigint 信号杀死。如果您在该信号渗透到父级时捕获该信号,则可以在那里忽略它并移至下一个 while 循环。您不必将 reset_cursor 作为自己的函数,但如果您想做更复杂的事情,我觉得它很好。

    我必须在子 shell 中添加 if 语句,否则它会忽略 ctrl+d - 但我们希望它能够“注销”而不强制用户手动键入 exit 或退出。

    【讨论】:

    • 这很好用。我已按如下方式实现它以获取用户输入作为单词列表:trap echo INT; while true; do mapfile -t -d '' input < <(IFS=' ' read -r -e -p '> ' -a input; printf '%s\0' "${input[@]}"); [[ ${input[0]} == quit ]] && break; history -s "${input[*]}"; declare -p input; done; trap SIGINT
    【解决方案2】:

    您可以使用 xdotool 之类的工具来发送 Ctrl-A(行首)Ctrl-K(删除到行尾)返回(清理行)

    #!/bin/bash
    trap "xdotool key Ctrl+A Ctrl+k Return" SIGINT;
    unset command
    while [ "$command" != "quit" ] ;do
        eval $command
        read -e -p "$USER - SHIELD: `pwd`> " command
      done
    trap SIGINT
    

    但是我强烈邀请你去rtfm...在搜索``debug''关键字...

    man -Pless\ +/debug bash
    

    【讨论】:

    • xdotool 可以做到这一点,因为它是 100% 的黑客。你会得到一个 ^C^A^K 和一个不会在纯 bash 中显示的空行(只是 ^C),但总比没有好。无论如何,不​​依赖xdotool 并避免那些额外的标记会很棒——比如说,让它就像 bash 一样工作。无论如何,我没有收到 rtfm 邀请... debug 应该告诉我什么?
    • 是的,这是一个巨大的 hack。但在状态下,这可以完成工作。遵循原意的正确方式需要通过ioctl访问文件描述符。
    • @mgarciaisaia 关于debug 可以做什么以及如何使用它。看看profiling bash in nanoseconds
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-26
    • 1970-01-01
    • 2019-05-06
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 2017-12-22
    相关资源
    最近更新 更多