Остановите эхо и используйте весь пользовательский ввод в Bash
TARGET
Пока некоторая подзадача в скрипте не завершит свою работу:
- остановить эхо;
- отключить курсор;
- потреблять весь пользовательский ввод;
- не блокируйте прерывания (Ctrl+C и т. д.).
ЧТО СДЕЛАНО
Сейчас, используя этот ответ, я создаю несколько функций для этого, вот они:
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
ЭТА ПРОБЛЕМА
Проблема в том, что текущее "решение" не работает. Когда я нажимаю клавиши во время длительного выполнения задания, они появляются на экране, а нажатие клавиши "Ввод" уничтожает весь вывод движениями курсора. Кроме того, после вызова функции "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
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