Nas páginas anteriores desse artigo apresentaram-se os fundamentos do que vêm a ser os assim chamados terminais burros (videotextos ou teletipos), os arquivos de dispositivo, os descritores de arquivos e os arquivos descritores. A continuidade da leitura pressupõe compreensão destes conceitos conforme relatados, visto que nesta seção apresentar-se-ão os exemplos práticos associados à parte teórica descrita.
Atualmente os antigos teletipos (terminais de vídeo) são simulados no próprio console da máquina rodando o sistema operacional a fim de prover um canal de comunicação entre o usuário e o sistema em si, visto não serem mais usuais os teletipos físicos. A comunicação com esses pseudoterminais se dá através de arquivos de dispositivo, assim como o outrora feito com os teletipos reais.
Inciando-se a parte prática com o auxílio de pseudoterminais, solicita-se que se sigam as instruções abaixo a fim de se executar, na máquina do leitor, o mesmo relatado dentro do possível através das capturas de tela apresentadas nessa seção. Solicita-se de início a abertura de (apenas) três pseudoterminais do konsole (ou de outro pseudoterminal como o gnome-terminal). Executando-se o comando "tty" em cada um deles, ter-se-ão exibido os respectivos arquivos de dispositivo atrelados a cada janela; e executando-se o comando " ls -la " a partir do diretório /dev/fd/ , a situação atual dos descritores de arquivo padrão para cada um dos pseudoterminais será exibida. O número de processo da instância do BASH atrelado a cada terminal também será necessário, podendo-se obtê-lo com "echo $BASHPID". [Ref.: 6 | 9 | 14 | 16 | 18 | 19]
Uma vez abertos, execute pois em cada terminal a linha de comando:
tty ; echo $BASHPID ; cd /dev/fd ; ls -la ; cd ~
FIGURA 06: preparativos para a parte prática. Um exemplo avulso das saídas esperadas para a linha de comandos acima, executada em pseudoterminais konsole em ambiente KDE - SUSE
Linux 13.2 (Harlequin). Os valores dos números de processos (PIDs) são "aleatórios" e particulares a cada execução do programa. [Ref.: 24]
Posicione as três janelas de forma a se localizá-las facilmente em função da numeração dos respectivos arquivos de dispositivos reportados na primeira linha da saída dos comandos acima; e de forma que se possa vê-las todas em íntegra, dê destaque à tela com pts de valor mais baixo; nos exemplos que se seguem /dev/pts/1. Nessa última janela se fará doravante todo o processamento que se segue.
Uma vez identificadas as informações necessárias, a partir da tela de dispositivo /dev/pts/1, execute o seguinte comando:
exec 1>/dev/pts/3
Podem-se ter de adaptar os valores à situação, em particular os PIDs, mas se apenas três pseudoterminais foram abertos, o comando acima não se altera. Com este comando se transfere a saída de dados (stdout) do bash atrelado ao pts/1 para o pts/3 (ver Carta de Redirecionamentos à página 4 deste artigo [Ref.: 23]). Doravante as saídas de comandos executados no terminal pts/1 vão à tela do pts/3. O comando "exec" faz com que o redirecionamento tenha efeito na instância corrente do shell, e não apenas nos subshell ou comandos invocados a partir dela como visto em página anterior desse artigo [Ref.: 9 | 25]. Para certificar-se do redirecionamento, como exemplo execute os seguintes comandos no terminal pts/1:
echo
$ cd /dev/fd
$ ls
$ ls -la
$ echo
O comando echo pula a linha de forma a não se embolarem os dados e dar uma estética melhor. Todas as saídas desse comando não seguem as respectivas linhas de instrução na tela /dev/pts/1. Elas são exibidas na tela do dispositivo /dev/pts/3. Observe descritor 1 e seu apontamento para visualizar e compreender o que se fez.
O passo seguinte é perceber que, na tela /dev/pts/3 há também uma instância do bash rodando, e se esta janela ganhar foco (não o faça, mas se o fizer, volte o foco à janela pts/1), ela também poderá executar seus próprios comandos. Dois programas escrevendo na mesma tela assincronamente podem fazer uma verdadeira bagunça na tela. Assim, a fim de configurar a tela pts/3 como apenas uma tela de saída de dados, deve-se matar o bash associado a ela. Execute, com o foco em pts/1, o comando:
kill -9 {PID do bash na janela pts/3}
ajustando o número do PID do bash à situação particular. Na figura seguinte o {PID ...} era 5458. Uma linha vermelha na janela pts/3 informará que o bash associado está devidamente morto. [Ref.: 9 | 26]
Uma observação aqui: em sistemas mais antigos, por experiência, não é viável se matar o bash pois tal procedimento mata também o pseudoterminal associado (a janela simplesmente fecha). Caso seja este o caso, não execute tal procedimento, deixando ambos os shells concorrentes. Para fins desse artigo não haverá maiores problemas.
FIGURA 07: uma execução, com comentários no próprio terminal (linhas iniciadas por #), dos procedimentos sendo indicados acima. O terminal com foco é aquele em janela própria, à direita. À esquerda, a janela de erros e comandos (situação final), no centro, a janela de saída de dados (stdout). [Ref.: 27]
Dando sequência aos procedimentos, faremos agora a mesma peripécia com a saída de erro (stderr) do bash iniciado junto ao terminal pts/1. A saída de erro é redirecionada agora ao outro terminal, /dev/pts/2, com o comando:
exec 2>/dev/pts/2
Doravante, tudo o que se escreve com o foco na janela pts/1 aparece na tela pts/2, incluindo-se o prompt de comandos do bash, que é veiculado através do canal de erro (stderr) e não de saída (stdout) da instância do shell. O passo seguinte é matar o bash na janela pts/2:
kill -9 {PID do bash na janela pts/2}
devendo-se aqui aplicar o PID particular à situação. Na implementação desse procedimento conforme ilustrada (figura acima), o PID era 5429. Repare que as instruções para se matar o bash à janela pts/2 são vistas agora nesta própria janela, embora o foco esteja com pts/1.
Repare na saída do comando "la -la" realizado a partir do diretório /dev/fd (execute antes "cd /dev/fd" caso necessário). O descritor zero, a entrada padrão (stdin) do bash em pts/1, aponta para /dev/pts/1 , implicando que a entrada de dados via teclado se dá com foco em pts/1; o descritor 1, a saída padrão, agora aponta para /dev/pts/3, indicando que os dados de saídas dos comandos serão exibidos em pts/3; e o descritor 2, a saída de erro padrão (stderr), aponta para /dev/pts/2, indicando que os alarmes de processamento bem como o prompt de comandos e as entradas de teclado ecoadas serão vistos em /dev/pts/2.
Para finalizar, uma observação sobre como se limpam as telas. No Linux há duas formas de se limparem as telas quando se executa o bash: a primeira se dá via combinação de teclas CTRL-L (ou seja, as teclas Control mais L); a segunda através do comando "clear" [Ref.: 28]. A combinação de teclas gera em verdade uma sequência de escape conhecida como "form feed", carregamento de folha, referenciando-se aqui o comportamento do papel perfurado nas antigas impressoras matriciais.
A tela é limpa por deslocamento para cima (o que se pode ver rodando-se a barra de rolagem à lateral da janela do terminal após um CTRL-L). A sequência contudo é "despachada" à saída de erro, de forma que, na configuração realizada, CTRL-L limpa a janela pts/2. Já "clear" é um comando, e sua saída limpa pois a janela conectada à sua saída de dados conforme herdada do bash que o invoca (ou conforme redirecionamento explícito), no caso, a janela pts/3. [Ref.: 29 | 30]
FIGURA 08: Control-L limpa a saída de erro, a janela pts/2. Já o comando "clear" limpa a saída padrão, pts/3 no exemplo. [Ref.: 31]
Vale ressaltar que o procedimento acima descrito tem finalidade meramente didática. Uma implementação prática e útil do descrito por certo dispensa o redirecionamento da saída de erro, e apenas duas janelas de terminal se fazem necessárias. A figura abaixo ilustra uma implementação efetivamente prática: janela de comandos e erros em um pseudoterminal, saída limpa de comandos na tela de outro pseudoterminal. Pouco usual, contudo.
FIGURA 09: uma implementação útil dos pseudoterminais mediante redirecionamentos. [Ref.: 32]
Por razões técnicas a serem vistas, recomenda-se que as janelas de saídas de dado e de erro sejam feitas do mesmo tamanho preferencialmente, ou maiores, que a janela com a instância do bash, observados tanto comprimentos como larguras. Tal procedimento evita distorções de exibição dos textos de saída nas janelas de destino (ver próxima seção).