【问题标题】:BASH - trap CTRL+C - Are you sure prompt doesn't always workBASH - 陷阱 CTRL+C - 你确定提示并不总是有效吗
【发布时间】:2019-07-08 16:17:17
【问题描述】:

我在 bash 脚本的顶部添加了以下内容:

quit() {

echo "Do you want to quit ? (y/n)"
  read n
  if [ "$n" = 'y' ]; then
    exit
  fi

}

trap quit INT
trap quit SIGINT
trap quit SIGTERM

脚本会询问用户一系列问题,然后根据结果执行操作。有时按 CTRL+C 似乎可以工作。

但其他时候我只收到Do you want to quit ? (y/n) 并且脚本锁定了。这可能在 IF 语句或 WHILE / DONE 中发生。

但是如果你在回声发生时计时 CTRL+C 我可以使问题发生.. 即:同时 CTRL+C作为回声。

有没有办法总是捕获 CTRL+C 并提示用户?然后让他们决定是否要退出?

此代码显示正在发生的问题..

quit() {

echo "Do you want to quit ? (y/n)"
  read n
  if [ "$n" = 'y' ]; then
    exit
  fi

}

trap quit INT
trap quit SIGINT
trap quit SIGTERM

for i in `seq 1 50`; do
    sleep 1
    echo -e "........"
    read -i "0000" -e site
done

尝试将 CTRL+C 计时,就像屏幕上显示 '........' 和 0000 时出现问题。

这似乎有很大的不同。

quit() {

    while read -e -t 0.1; do : ; done
    read  -p "Do you want to quit ? (y/n) " n
    if [ "$n" = 'y' ]; then
        exit
    fi

}

我现在正在努力实现它。

谢谢

【问题讨论】:

  • 我的猜测是您在标准输入中有一些内容被读入$n,并且由于它与y 不同,您的脚本只是在执行陷阱函数后继续执行。这听起来可能吗?如果是这样,我建议在提示输入 y/n 之前检查 this Unix&Linux SE question 以丢弃 stdin 的内容
  • 与您的问题无关,但最好避免使用 echo-e 参数;它不是由 POSIX sh 标准指定的,即使在 bash 中,它的行为也会根据活动的编译时和运行时标志而变化很大。请参阅 Stephane 在 unix.stackexchange.com/questions/65803/… 中的出色回答,其中描述了 echo 的行为不可靠和不可移植的方面,尤其是在依赖反斜杠转义翻译时。
  • 我不熟悉read-i 标志,但鉴于它的描述,我认为这是违规者:“如果使用 readline 读取行,则将文本放入编辑缓冲区在编辑开始之前。” ;它必须将0000 放入stdin,您的quit() 函数会读取它而不是您想要的y/n
  • 我认为是read -i - 是否有这个问题?我已经关注了@Aaron 提供的链接,但我不确定如何添加它。谢谢
  • @Aaron 我不认为它会继续......当这种情况发生时它似乎很有趣。

标签: bash ctrl bash-trap


【解决方案1】:

陷阱名称不能以SIG 为前缀,因为它是未定义的。

您想要在陷阱处理程序中做的另一件事是: 中和陷阱 所以它们不会在处理程序处理时触发。

#!/usr/bin/env sh

quit() {
  trap false ABRT INT # Neutralize traps in the quit handler by assigning the false function
  printf '\nDo you want to quit ? (y/N)\n' # Uppercase N show the default choice
  read -r n
  case "${n}" in
    [yY]) # Match y or Y
      exit
    ;;
  esac
  trap quit ABRT INT # Re-enable traps on self
}

trap quit ABRT INT # Attach the SIGABRT and SIGINT traps to the quit function
i=1
while true; do
  echo "$i"
  i=$((i+1))
  sleep 1
done

示例运行:

1
2
^C
Do you want to quit ? (y/n)
n
3
4
^C
Do you want to quit ? (y/n)
^C5
6
7
8
^C
Do you want to quit ? (y/n)
y

【讨论】:

  • 我又添加了几个 cmets
  • 这也有同样的问题。如果您在“右侧”按 CTRL+C,则脚本似乎挂起并且不接受任何输入。我的问题的更新似乎效果更好。
【解决方案2】:

试试下面的。

quit() {

  echo "Do you want to quit ? (y/n)"
  read n
  if [ "$n" = 'y' ]; then
    exit
  fi

}

trap quit INT
trap quit SIGINT
trap quit SIGTERM

for i in `seq 1 50`; do
    sleep 1
    echo -e "........"
    site=$(read -p "0000" -e site; echo "$site")
done

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    • 2014-08-11
    • 1970-01-01
    • 2016-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多