停止回显并消耗Bash中的所有用户输入

问题描述 投票:0回答:1

TARGET

直到脚本中的某个子任务完成其工作:

  • 停止回声;
  • 禁用游标;
  • 消耗所有用户输入;
  • 不要阻止中断(Ctrl + C等)。

WHAT HAVE DONE

现在,使用this answer,我为此创建了一些函数,它们是:

function hide_input()
{
  if [ -t 0 ]; then
    stty -echo -icanon time 0 min 0
  fi
}

function reset_input()
{
  if [ -t 0 ]; then
    stty sane
  fi
}

function stop_interactive()
{
  trap reset_input EXIT
  trap hide_input CONT
  hide_input
  tput civis
}

function start_interactive()
{
  tput cnorm
  reset_input
}

function consume_input()
{
  local line
  while read line; do line=''; done
}

以下是它们的使用方式:

echo "Warn the user: the job will be started."
read -p "Continue? [yes/no] > "
if [ "$REPLY" == "yes" ]; then
  stop_interactive  # <== from here all input should be rejected
  echo "Notify the user: job starting..."

  # << ------ here goes some long job with output to terminal ------>

  echo "Notify the user: job done!"
  consume_input # <== here I trying to get all user input and put nowhere
  start_interactive # <== from here restore normal operation
else
  echo "Aborted!"
  exit 0
fi

THE PROBLEM

问题是:当前的“解决方案”不起作用。当我在长时间运行的工作期间按键时,它们会出现在屏幕上,然后按“Enter”将光标移动所有输出。此外,在'start_interactive'函数调用之后,所有输入都出现在终端屏幕上。

这项任务的正确解决方案是什么?

SOLUTION

最终的工作方案是:

function hide_input()
{
  if [ -t 0 ]; then
    stty -echo -icanon time 0 min 0
  fi
}

function reset_input()
{
  if [ -t 0 ]; then
    stty sane
  fi
}

function consume_input()
{
  local line
  while read line; do line=''; done
}

function stop_interactive()
{
  trap reset_input EXIT
  trap hide_input CONT
  hide_input
  tput civis
}

function start_interactive()
{
  consume_input
  trap - EXIT
  trap - CONT
  tput cnorm
  reset_input
}

echo "Warn the user: the job will be started."
read -p "Continue? [yes/no] > "
if [ "$REPLY" == "yes" ]; then
  stop_interactive
  echo "Notify the user: job starting..."
  do_the_job &
  pid=$!
  while ps $pid > /dev/null ; do
    consume_input
  done
  echo "Notify the user: job done!"
  start_interactive
else
  echo "Aborted!"
  exit 0
fi
bash echo stty tput
1个回答
1
投票

根据您的问题,如果我查看您的代码,有很多问题“为什么”。如果您不想更改^ C等的行为,则不要使用陷阱。您的所有函数都会测试文件描述符0是否为终端。你打算在管道中使用脚本吗?此外,您的用户输入将继续消耗,直到文件结束,因此脚本可能永远不会结束。

根据你的问题,我会写这样的东西:

echo "Warn the user: the job will be started."
read -p "Continue? [yes/no] > "
if [ "$REPLY" == "yes" ]; then
    stty -echo
    echo "Notify the user: job starting..."
    program_to_execute &
    pid=$!
    while ps $pid > /dev/null ; do
        read -t 1 line
    done
    echo "Notify the user: job done!"
else
    echo "Aborted!"
fi
stty sane
© www.soinside.com 2019 - 2024. All rights reserved.