Estou escrevendo um script bash para ler alguma entrada do usuário (como uma solicitação de senha), e gostaria de capturar o resultado e passá-lo por sua stdout. (Estou trabalhando em um ambiente GNU / Linux, com software recente).
Aqui está uma versão simplificada do script que reproduz os problemas
....
# read_input.sh
#
# Issue B : redirection of "3>&1" here causes stty error when
# this script is executed via a command subsitution context subshell
exec 3>&1 </dev/tty >/dev/tty
tty_settings='stty -g'
# Issue A : uncommented version doesn't restore tty properly.
#trap 'stty "$tty_settings";' EXIT
#trap 'echo "...interrupting"; exit 1' INT ABRT HUP QUIT TERM
trap 'echo "...interrupting"; stty "$tty_settings"; exit 1' INT ABRT HUP QUIT TERM
stty -echo
echo "Enter input: "
input=""
while IFS= read -r -n1 char; do
# nb: stripped out proper char handling code here,
# (except return), for simplicity
if [[ $char = "" ]]; then
break
fi
input+=$char
echo -n "*"
done
echo ""
stty "$tty_settings"
#trap - EXIT INT ABRT HUP QUIT TERM
trap - INT ABRT HUP QUIT TERM
echo "$input" >&3
A intenção é escrever para o fd 3 a entrada do resultado (se o stdout do script em invocação estiver conectado em um canal) - enquanto ainda estiver tendo tty durante a interação. Eu então modifico o tty com o stty para controlar o eco, etc, restaurando quaisquer modificações através do manuseio com o trap.
Eu encontrei dois problemas com isso.
Problema A
Na restauração do terminal de controle, o eco foi suprimido. Eu tive que usar o caso de manipulação de armadilha de duas linhas (comentado), em vez do caso do manipulador de uma linha ativa não comentada.
No caso de uma linha - digamos, no INT: o tty é restaurado, e a saída é chamada pelo manipulador. Eu não estou prendendo EXIT em si - por que isso seria necessário?
Problema B
Isso está relacionado ao redirecionamento "3 > & 1" do executivo em um contexto de subshell.
Por alguma razão, digamos que eu execute este script ("read_input.sh") em um subshell - e queira capturar sua saída de outro script por meio da substituição de comando:
....
# read_input_caller.sh
input=$(sh read_input.sh)
echo "$input"
Eu encontrei a invocação stty no manipulador de armadilha queixou-se do seguinte ao interromper o script de chamada (digamos com ^ C):
stty: 'standard input': Input/output error
Essa mensagem de erro só acontece por causa do redirecionamento "3 > & 1" na linha exec - chamando a linha exec sem "3 > & 1", não há nenhum erro stty (mas não muito útil para passar a entrada para stdout). Eu não posso pensar por que isso seria o caso?
No script de chamada, outra invocação de subshell como
....
sh read_input.sh | cat
Não produz este erro.
Curiosamente, quando o problema B ocorria, o terminal de controle parecia ser restaurado corretamente, mesmo sob a armadilha / restauração problemática do problema A.