Nesta última seção do artigo "Brincando com pseudoterminais e redirecionamentos" far-se-á algo intuitivo perto do realizado na seção anterior, onde redirecionaram-se as saídas padrão (stdout e stderr) de uma instância do shell bash atrelada a uma janela do konsole a duas outras janelas; uma destas janelas ficando responsável pela exibição dos dados de saída dos comandos e a outra pela exibição do "prompt" e dos dados de controle e de erro atrelados à execução de programas invocados sem redirecionamentos explícitos ou mesmo oriundos da própria instância do bash. Nesta seção redirecionar-se-á a entrada padrão (stdin) do bash atrelado a uma janela de terminal a outra janela de terminal, de modo que se tenha que lhe dar o foco para a digitação de comandos ao bash.
Inicie abrindo duas janelas do konsole e exibindo seus respectivos arquivos de dispositivo com o comando "tty" e os respectivos PIDs das instâncias do bash com o comando "echo", executando em cada pseudoterminal o seguinte conjunto de comandos:
tty ; echo $BASHPID ; cd /dev/fd ; ls -la
que pode ser digitado em linha única, conforme mostrado.
FIGURA 10: uma implementação prática dos procedimentos para redirecionamento de entrada (stdin) sendo descritos. [Ref.: 37]
Se apenas as duas janelas solicitadas encontram-se abertas, seus respectivos tty serão /dev/pts/1 e /dev/pts/2. Adapte ao caso a numeração própria se distinta desta.
Desta vez iniciar-se-á o procedimento matando-se a instância do shell bash atrelada à janela pts/2. Com o foco em pts/1, execute o comando:
kill -9 {PID do bash na janela /dev/pts/2}
O "9" , número atrelado à sinalização SIGKILL, é necessário para se matar a instância do bash pois em modo interativo o bash não se mata via sinal TERM, o sinal default de "kill" caso não lhe seja informado um. Para uma lista de sinais reconhecidas pelo bash e respectiva numeração associada execute o comando "trap -l". [Ref.: 9 | 26 | 34 | 35]
Uma mensagem em vermelho deve aparecer na tela da janela pts/2 informando que o shell associado está morto (travou).
Com o foco ainda em pts/1, execute o comando:
exec </dev/pts/2
que redirecionar o descritor 0 (stdin) da instância do bash ainda em execução ao pseudoterminal pts/2. [Ref.: 20 | 23]
Doravante, digitando-se qualquer coisa com o foco na janela pts/1, ecoar-se-á o digitado na tela em virtude da função de eco estar por padrão ativa, mas nada será processado, mesmo pressionando-se Enter, pois a instância do bash ainda ativa efetivamente não tomou conhecimento de tal digitação para interpretação (ela está esperando dados de pts/2). Importante perceber contudo que a função de escrever os caracteres digitados na tela não é da instância do bash, mas de uma parte da estrutura de conexão conhecida como driver de terminal, cuja existência de uma instância atrela-se inexoravelmente à existência de uma instância do bash atrelada [Ref.: 8].
Para se processar algum outro comando doravante, deve-se mudar o foco para a janela pts/2, que assumiu a entrada padrão da instância ativa do bash. Comandos digitados nesta janela serão executados, mas suas saídas serão exibidas em pts/1 contudo. Tente, com foco em pts/2, digitar "ls -la" e veja o resultado. Importante perceber que o comando será entrado às segas. Não se verá eco do mesmo, pois junto ao terminal /pts/2 o bash (com o readline) e o driver de terminal (responsável pelo eco) associados estão mortos. Em pts/2 está ativo apenas o driver do console (ou pseudo-tty no caso), ou seja, a parte da estrutura responsável pela janela em si; por nela escrever apenas o recebido, e enviar o através dela inserido via teclado. E não há eco nesse caso.
A estrutura geral envolvendo um pseudo terminal é para fins didáticos esquematizada da seguinte forma (n representando dígitos) [Ref.: 8]:
Programa escravo (bash) <---> Driver de terminal (onde há o eco) <---> (/dev/pts/n) Driver de console ou pseudo-tty <---> Programa mestre (janela)
O driver do console opera da seguinte forma [Ref.: 8]:
Programa escravo <---> Driver de terminal <---> (/dev/pts/n) Driver do console <==> |
|----> Driver de vídeo ---> Vídeo
| <---- Driver de teclado <--- Teclado
Através da estrutura conclui-se que matando-se o programa escravo (bash) bem como o driver de terminal, o bash de outro terminal com redirecionamento ao driver pseudo-tty liberado opera sem recurso para reconhecer e auxiliar o gerenciamento do terminal a qual se conecta. Comandos oriundos do console que seriam interceptados e interpretados pelo driver de terminal (sequências de escape para configuração do terminal) são agora levados diretamente ao bash, que muitas vezes não sabe o que fazer com tais comandos (pois não são comandos do bash); o mesmo valendo no caso do fluxo inverso de dados.
A exemplo. o comando CTRL-L não funcionará imediatamente via redirecionamento de entrada acima descrito, a menos que um "Enter" seja pressionado após a combinação de teclas. "Enter" leva o pseudoterminal com foco para entrada de dados a descarregar o "buffer" de teclado (o CTRL-L) no bash, que reconhece e processa, então, a limpeza de tela (o pseudoterminal opera em modo canônico: [Ref.: 8]).
Por tal, concluindo-se, é importante manter as janelas de entrada e saídas as mais parecidas possível com aquela janela associado à instância do bash em execução e que ainda retém um driver de terminal associado (mesmo que este não atue nos redirecionamentos), evitando-se assim erros de formatação na exibição e na entrada de dados junto às janelas que receberam redirecionamentos. Igualmente devem-se evitar comandos com foco na configuração do terminal no caso de redirecionamento de entrada e saídas.
FIGURA 11: redirecionamento de entrada em sistema onde a existência do pseudoterminal atrela-se inexoravelmente à existência da instância do bash associada. Feito o redirecionamento, para se executar um comando, com foco no terminal alvo (pts/1 na figura), deve-se digitar em dobro todos os caracteres, incluindo-se o(s) espaço(s) entre comando(s) e argumento(s). As instâncias concorrentes do bash recebem, alternadamente, o que se digita; de forma que ambas executarão o mesmo comando após "Enter", também duplo. Não há eco no outro terminal (pts/0) da parte digitada que lhe cabe. [Ref.:38]
Poder-se-ia pensar agora: mas o que ocorre se redirecionarmos a entrada padrão sem contudo se matar o bash (e o driver de terminal) do pseudoterminal alvo? Deixa-se como dever de casa esta situação, mas facilmente percebe-se que haverá duas instâncias do bash concorrendo pelo dado digitado. O que se esperar?
Executar o redirecionamento de entrada (e saídas) sem se matar o bash será a situação exemplo viável em alguns sistemas mais antigos, onde, por experiência, matando-se o bash mata-se também, automaticamente, o pseudoterminal (a janela associada simplesmente fecha após o comando "kill").
Em qualquer sistema contudo, mantendo-se ambas as instâncias ativas e com entradas padrão comuns, haverá concorrência pelo dado digitado, geralmente um caractere indo a uma das instâncias, outro à outra das duas instâncias conectadas ao pseudoterminal, alternadamente (para se conseguir executar um comando com foco na janela com as entradas, cada caractere deverá ser digitado em dobro).
FIGURA 12: redirecionamento dos três descritores principais (stdout, stderr, stdin) em exemplo envolvendo quatro pseudoterminais do konsole, exemplificando todo o arcabouço abordado no artigo. Após identificação do arquivo de dispositivo e do PID da instância associada do bash em cada janela, os demais comandos foram digitados com foco na janela pts/3; até a transferência da entrada padrão ao pseudoterminal pts/4, quando comandos entrados às segas em pts/4 levaram às saídas em pts/1.
Inicialmente, a partir de pts/3, matou-se de uma só vez as instâncias do bash nas outras janelas (linhas vermelhas). Posteriormente executaram-se os redirecionamentos um a um, conforme listagem de /dev/fd/ na janela pts/1. Repare a sequência de escape produzida pela digitação dupla de "seta à esquerda", acidental, durante a digitação do comentário. [Ref.: 39]
Bem, é hora de reconhecer que não se trata de um artigo dos mais rigorosos tecnicamente - e certamente há falhas técnicas nele, pois muito se apoiou em experiência pessoal e não apenas na literatura recomendada - mas espera-se ao menos se ter ajudado a elucidar, "visualmente", o princípio de funcionamento dos redirecionamentos nos sistemas Unix-similares, e o valor prático da sensacional estrutura lógica atrelada.
Comentários e correções certamente são bem-vindos. E entre os Unix similares, "Viva o
Linux"...