停止回显并消耗 Bash 中的所有用户输入
Stop echo and consume all user input in Bash
目标
直到脚本中的某些子任务完成其工作:
- 停止回显;
- 禁用光标;
- 消耗所有用户输入;
- 不阻止中断(Ctrl+C 等)。
做了什么
现在,使用 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
问题
问题是:目前的'solution'不工作。当我在长时间的 运行 作业中按下按键时,它们会出现在屏幕上,然后按下 'Enter' 会破坏所有带有光标移动的输出。此外,在 'start_interactive' 函数调用之后,所有输入都显示在终端屏幕上。
这项任务的正确解决方案是什么?
解决方案
最终的工作解决方案是:
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
根据你的问题,如果我看你的代码,有很多问题"why"。如果您不想更改 ^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
目标
直到脚本中的某些子任务完成其工作:
- 停止回显;
- 禁用光标;
- 消耗所有用户输入;
- 不阻止中断(Ctrl+C 等)。
做了什么
现在,使用 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
问题
问题是:目前的'solution'不工作。当我在长时间的 运行 作业中按下按键时,它们会出现在屏幕上,然后按下 'Enter' 会破坏所有带有光标移动的输出。此外,在 'start_interactive' 函数调用之后,所有输入都显示在终端屏幕上。
这项任务的正确解决方案是什么?
解决方案
最终的工作解决方案是:
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
根据你的问题,如果我看你的代码,有很多问题"why"。如果您不想更改 ^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