【问题标题】:Bash - Break out of loop with Ctrl-C but continue with scriptBash - 使用 Ctrl-C 跳出循环但继续执行脚本
【发布时间】:2023-03-06 12:38:01
【问题描述】:

我有一个无限循环,我只想在用户按下 Ctrl - C 时退出。

但是我的 while 循环中有 2 个计数器,当我退出 while 循环时,我想打印出它们的值。

OK_COUNT=0
NOK_COUNT=0

while :
  do
    RESULT=`curl -s http://${IP}${ENDPOINT} --max-time 1`

      if [ $RESULT == '{"status":"UP"}' ]
        then
           (( OK_COUNT+=1 ))
           echo "`date` :: ${ENDPOINT} is OK ! Total count is $OK_COUNT "
        else
           (( NOK_COUNT+=1 ))
           echo "`date` :: ${ENDPOINT} is UNREACHABLE ! Total count is $NOK_COUNT"
      fi

    sleep 0.5
  done

echo $OK_COUNT
echo $NOK_COUNT

现在,当我按下 Ctrl + C 时,我也会退出 while 循环并退出脚本。这意味着最后 2 个 echo 语句不会被打印出来。

有没有一种方法,如果我按 Ctrl + C,我只退出 while 循环,但脚本的其余部分仍然运行?

编辑/解决方案 ::

添加trap后,就可以了!

OK_COUNT=0
NOK_COUNT=0

trap printout SIGINT
printout() {
   echo $OK_COUNT
   echo $NOK_COUNT
   exit
}

while :
  do
    RESULT=`curl -s http://${IP}${ENDPOINT} --max-time 1`

      if [ $RESULT == '{"status":"UP"}' ]
        then
           (( OK_COUNT+=1 ))
           echo "`date` :: ${ENDPOINT} is OK ! Total count is $OK_COUNT "
        else
           (( NOK_COUNT+=1 ))
           echo "`date` :: ${ENDPOINT} is UNREACHABLE ! Total count is $NOK_COUNT"
      fi

    sleep 0.5
  done

使用上面的代码,当我用 Ctrl + C 退出代码时,我得到了。

Wed Oct 18 18:59:13 GMT 2017 :: /cscl_etl/health is OK ! Total count is 471 
Wed Oct 18 18:59:13 GMT 2017 :: /cscl_etl/health is OK ! Total count is 472 
^C
5
0
# 

【问题讨论】:

    标签: bash


    【解决方案1】:

    陷阱语句

    这是确保在 Ctrl+C 之后运行 echo 语句的一种方法:

    trap printout SIGINT
    printout() {
        echo ""
        echo "Finished with count=$count"
        exit
    }
    while :
    do
        ((count++))
        sleep 1
    done
    

    当运行并按下 Ctrl+C 时,此脚本的输出如下所示:

    $ bash s.sh
    ^C
    Finished with count=2
    

    工作原理

    trap 语句捕获 Ctrl+C 并执行函数printout。该函数可以包含您喜欢的任何语句。

    带陷阱的子shell

    或者,我们可以将循环和陷阱语句放在一个子shell中:

    $ cat t.sh
    (
        trap printout SIGINT
        printout() {
            echo ""
            echo "At end of loop: count=$count"
            exit
        }
        while :
        do
            ((count++))
            sleep 1
        done
    )
    echo "Finishing script"
    

    当它运行并按下 Ctrl+C 时,输出如下所示:

    $ bash t.sh
    ^C
    At end of loop: count=2
    Finishing script
    

    此方法允许我们在子shell 之后继续执行脚本。但请注意,在子shell 中设置的任何变量或其他环境更改都会在子shell 退出后丢失。

    【讨论】:

    • 感谢您的回答。我尝试了您的第一个建议,但它似乎不起作用。我已经编辑了我的问题并添加了我最新的编辑。
    • @JasonStanley 我复制并粘贴了您的脚本,添加了 IP 和 ENDPOINT 的定义,它对我来说很好。那么,您使用的是什么操作系统?如果是Linux,哪个发行版?同样非常重要的是,您执行脚本的究竟如何?
    • 感谢您特别提到“您执行脚本的具体情况如何?”。我的错。为了排除错误,我使用> out.log 2> /dev/null | tail -f out.log 运行我的脚本,所以我看不到 Ctrl + C 之后的脚本部分。现在我可以了。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-28
    • 2016-08-19
    • 2012-04-03
    • 1970-01-01
    • 2019-03-12
    相关资源
    最近更新 更多