用于调用函数的递归bash陷阱

时间:2015-02-26 14:02:50

标签: bash ctrl bash-trap

我创建了一个bash陷阱来捕获 CTRL + C 并调用函数ctrl_c。此函数只显示一条消息并启动计数器然后返回主函数。

第一次运行时陷阱工作正常但如果第二次尝试它会显示C ^虽然它确实禁用CTRL + C但它不会再次调用该函数。

有没有办法将陷阱重置为像第一个实例一样运行。

提前致谢。

代码;

function ctrl_c() {
    clear
    echo "** Trapped CTRL-C"
    echo -n "Press [ Enter ] to continue."
    read
    for i in $(seq 1 5);
    do
            let timer="5 - $i + 1"
            clear
            echo "Returning to main menu in.. $timer"
            sleep 1
    done
    main
}

trap ctrl_c INT

3 个答案:

答案 0 :(得分:1)

中断处理程序运行时始终阻止信号。在此代码中,您的处理程序永远不会返回,因此信号仍然被阻止。

不返回的信号处理程序通常是个坏主意。如果您只想在信号之后重新启动函数,那么您可以在循环中的子shell中运行它并让处理程序退出,这将仅从子shell退出。

编辑:更新了Adrian的建议。

    #!/bin/bash

    function ctrl_c() {
            clear
            echo "Trapped CTRL-C"
            echo
            for ((timer=5; timer>0; timer--)); do
                    printf "\rRetunring to main menu in $timer seconds"
                    sleep 1
            done
            exit 10
    }

    function main() {
            trap ctrl_c INT
            # Doing main stuff
            echo "Exiting normally"
            exit 0;
    }

    while ( main ); (($? == 10)); do :; done

答案 1 :(得分:1)

将程序的控制权传递给信号处理程序并不是一个好主意。信号处理程序应尽可能快地完成并返回。因此,您可以在处理程序中启用标志变量,如下所示:

function ctrl_c() {
    flag=1
}

function trap_menu() {
    clear
    for i in $(seq 1 5);
    do
        let timer="5 - $i + 1"
        clear
        echo "Returning to main menu in.. $timer"
        sleep 1
    done
    flag=0
}

trap "ctrl_c" INT

flag=0
while ! [ $age ]; do
    echo -n "Enter your age> "
    while [ $flag -eq 0 ] && ! [ $age ]; do
        # Wait for one second
        read -t 1 age
    done
    if [ $flag -eq 1 ]; then trap_menu; fi
done

答案 2 :(得分:0)

你没有回归'到主函数,而是重新调用它,所以你仍然在技术上在你的陷阱处理程序。如果您排除' main'在处理程序结束时调用,bash将在执行流程中断之后返回NEXT命令,您可以继续捕获进一步的中断。见Catch SIGINT in bash, handle AND ignore

function main() {
    echo sleeping...
    sleep 60
    main
}

function ctrl_c() {
    echo "** Trapped CTRL-C"
}

trap ctrl_c INT

main

在你的情况下,如果它只是一个读取操作(从用户那里获得菜单选择)失败,那么只需检查输入是否为空并循环回来以获得更多输入。