Comandos tty e stty: controlar o terminal no Linux

Imagem destacada com o comando stty sane num terminal escuro e a legenda «ler, mudar e salvar o terminal», da série Comandos Linux do blog HJFR

Escreve uma palavra-passe e não aparece nada; carrega em Backspace e surge ^?; um programa termina mal e o ecrã deixa de mostrar o que digita. Nada disto é avaria: são definições do terminal, e há dois comandos pequenos que as revelam e controlam.

Neste artigo vemos o tty, que diz a que terminal está ligado, e o stty, que mostra e altera o comportamento desse terminal: o tty -s em scripts, o stty -a, o -echo para ler segredos, a redefinição de teclas, o stty size e os modos raw e sane — este último, o comando que salva um terminal «partido».

Veja o guia em vídeo

Prefere ver antes de experimentar? No canal HJFR-IT no YouTube mostramos o tty e o stty opção a opção, com o resultado de cada comando no ecrã — narrado em português e com legendas.

tty e stty — Guia Completo: controlar o teu terminal — canal HJFR-IT no YouTube. Se o áudio não arrancar em português, abra as definições do vídeo (ícone da roda dentada) → Faixa de áudio → Português.

O que fazem o tty e o stty

A ideia central é simples: em Unix, um terminal é um ficheiro de dispositivo. Quando abre uma shell, ela fica ligada a esse dispositivo, e é por ele que entram os caracteres que escreve e sai o texto que vê. Pelo meio está a disciplina de linha do núcleo, que decide se mostra as teclas (o eco), se junta a linha até ao Enter e o que faz o Ctrl+C.

O tty responde a «qual é o meu terminal?»; o stty (de set tty) inspeciona e muda essas regras. Ambos fazem parte do GNU coreutils.

tty [-s]
stty [-a | -g]
stty [-F DISPOSITIVO] DEFINIÇÃO...
stty size

O básico do tty: em que terminal estou?

Escrito sozinho, o tty imprime o caminho do dispositivo ligado à entrada padrão. Numa janela gráfica ou por SSH vê algo como /dev/pts/0: pts significa pseudo-terminal slave, o tipo usado pelas janelas de terminal, pelo SSH e pelo tmux. Numa consola de texto real veria /dev/tty1.

$ tty
/dev/pts/0
$ ls -l $(tty)
crw--w---- 1 aluno tty 136, 0 Oct 24 10:21 /dev/pts/0

O c confirma que é um dispositivo de caracteres — e que é seu. Se descobrir o terminal de outra sessão sua (o who lista as sessões e o terminal de cada uma), pode escrever nela com um simples redirecionamento:

$ who
aluno    pts/0        2026-10-24 09:12 (192.0.2.10)
aluno    pts/1        2026-10-24 09:40 (192.0.2.10)
$ echo "backup feito" > /dev/pts/1

As permissões crw--w---- explicam porque é que isto só funciona nos seus terminais (ou como root): a escrita do grupo tty só serve a ferramentas como o write.

tty -s em scripts

A opção -s (silent) não imprime nada: apenas define o código de saída — 0 se a entrada padrão for um terminal, 1 se não for. Responde à pergunta de qualquer script: há uma pessoa à frente, ou estou num pipe, num cron, a ler de um ficheiro?

$ tty -s; echo $?
0
$ echo dados | tty -s; echo $?
1

Daí nasce o padrão dos scripts educados — interativos quando há alguém, silenciosos quando não há:

#!/bin/bash
if tty -s; then
    read -rp "Continuar? [s/N] " resp
    [ "$resp" = "s" ] || exit 1
else
    echo "$(date '+%F %T') sem terminal: a continuar" >> "$HOME/tarefa.log"
fi

Em bash, [ -t 0 ] faz o mesmo teste sem lançar um processo; sem o -s, o tty escreveria not a tty.

stty -a: ler todas as definições

Sem argumentos, o stty mostra a velocidade e só o que difere dos valores «sãos». Com -a (all) despeja tudo, formatado para a largura da janela:

$ stty
speed 38400 baud; line = 0;
-brkint -imaxbel iutf8
$ stty -a
speed 38400 baud; rows 24; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany -imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke -flusho -extproc

A primeira linha traz a velocidade (simbólica num pseudo-terminal) e o tamanho da janela; seguem-se duas categorias.

Caracteres de controlo

  • intr = ^C — envia o sinal de interrupção (SIGINT) ao programa em primeiro plano.
  • eof = ^D — fim de ficheiro: numa linha vazia, diz ao programa que não há mais dados.
  • erase = ^? — apaga um carácter; é o que o Backspace envia na maioria dos emuladores.
  • kill = ^U — apaga a linha inteira.

Flags de modo

O resto são flags — um - à frente significa desligada. Reconheça estas: echo (mostrar o que se escreve), icanon (modo canónico: editar a linha até ao Enter), isig (Ctrl+C e Ctrl+Z geram sinais), icrnl (o Enter, que chega como CR, passa a NL) e opost/onlcr (na saída, cada NL passa a CR+NL). É uma fotografia completa do terminal — e a base para o mudar.

Mudar o comportamento com stty

Para mudar uma definição, passe-a ao stty: o nome liga, com - à frente desliga. Vale só para o terminal atual; um terminal novo volta ao habitual.

-echo: ler palavras-passe sem as mostrar

O exemplo clássico é o -echo: o terminal deixa de mostrar o que escreve — nem a mudança de linha do Enter. As teclas chegam ao programa; só não vão para o ecrã, como num pedido de palavra-passe. Num script, a receita é desligar, ler e voltar a ligar, com um trap para repor o terminal mesmo que o script seja interrompido:

#!/bin/bash
estado=$(stty -g)              # guarda as definições atuais
trap 'stty "$estado"' EXIT     # repõe-nas ao sair, mesmo com Ctrl+C
stty -echo
read -rp "Palavra-passe: " pw
echo                           # o Enter não foi ecoado: mudar de linha
echo "Recebidos ${#pw} caracteres."

Em bash, read -s faz o mesmo só durante a leitura. E nunca passe palavras-passe como argumentos: ficam visíveis no ps e no histórico.

Redefinir teclas: erase e intr

stty erase seguido de um carácter muda a tecla que apaga; stty intr muda a que envia o sinal de interrupção, por omissão o Ctrl+C. O carácter escreve-se em notação de acento circunflexo:

$ stty erase ^H          # Ctrl+H passa a apagar; o Backspace (^?) deixa de o fazer
$ stty intr ^X           # Ctrl+X passa a interromper; Ctrl+C torna-se um carácter normal
$ stty erase '^?' intr ^C    # repor os valores habituais

O erase trocado é um clássico: se o Backspace escrever ^? ou ^H em vez de apagar, o terminal e o stty não concordam sobre o que a tecla envia.

stty size, raw e sane: três usos que valem ouro

stty size

Imprime linhas e colunas num formato simples para scripts — útil para interfaces de texto que se adaptam à janela:

$ stty size
24 80
$ read -r linhas colunas < <(stty size)

O inverso, stty rows N cols M, diz ao núcleo o tamanho da janela. Normalmente é o emulador que o faz ao redimensionar; à mão, só quando esse aviso não chega.

stty raw

Modo cru: em vez de esperar pela linha inteira e processar teclas especiais, entrega cada carácter de imediato ao programa — o que editores e jogos de terminal precisam. Mas também desliga os sinais (o Ctrl+C deixa de interromper) e o processamento de saída (-opost): numa shell, cada mudança de linha desce sem voltar ao início e a saída fica em escada. O contrário é stty -raw.

stty sane (e reset)

O mais útil de todos. Quando um terminal «enlouquece» — um programa sai mal e deixa o eco desligado ou o modo cru ligado, ou um cat a um binário enche o ecrã de lixo — o stty sane repõe as definições normais, muitas vezes escrito às cegas:

stty sane    # escreva às cegas e carregue em Enter
             # se o Enter não responder, termine com Ctrl+J
reset        # se os caracteres continuarem trocados, reinicializa também o emulador

O stty sane trata das definições no núcleo (eco, modo canónico, sinais, teclas por omissão); o reset, do ncurses, reinicializa também o emulador (conjunto de caracteres, cores) e limpa o ecrã, mas mantém as teclas redefinidas. Depois de um cat a um binário, é muitas vezes ele que resolve.

tty e stty em cibersegurança

Segredos sem eco — e sem rasto. Ler palavras-passe com -echo (ou read -s) evita que fiquem à vista de quem está ao lado ou em gravações de ecrã. O trap que repõe o terminal não é cosmético: um script que morre com o eco desligado deixa o comando seguinte a ser digitado às cegas. E o tty -s permite recusar pedir credenciais quando não há terminal.

Saber onde está numa sessão remota. Em resposta a incidentes, o tty com o who ou o w diz qual das sessões abertas é a sua — e, por exclusão, quais não são. Uma pts vinda de um IP que não reconhece é para investigar antes de agir: registe origem e hora, veja o que corre nesse terminal (ps -t pts/2) e só depois contenha, por exemplo com pkill -t pts/2. Não avise o intruso escrevendo no terminal dele.

Shells sem TTY numa auditoria autorizada. Num teste de intrusão autorizado é comum obter uma shell remota sem terminal: o tty responde not a tty, os editores não funcionam e um Ctrl+C mata a ligação inteira. Estabilizá-la passa por alocar um pseudo-terminal no alvo, pôr o terminal local em modo cru e sem eco e acertar linhas e colunas com o stty. Do lado defensivo: uma bash filha do servidor web — sem TTY no ps, ou com um pts que nenhuma sessão SSH justifica — é um forte indicador de comprometimento.

Experimente no simulador interativo

O simulador abaixo abre uma sessão SSH na máquina hjfr. No painel esquerdo vê as definições do terminal, o percurso de cada tecla até ao programa e as sessões abertas; à direita, o terminal a obedecer-lhes. Desligue o eco, troque o erase e o intr, ponha o terminal em raw e salve-o com stty sane. O que for escrito sem eco aparece numa caixa tracejada — num terminal real, não apareceria nada. Use Demonstrar tudo para a sequência guiada, Anterior e Seguinte para avançar ao seu ritmo e Repor estado para recomeçar.

Erros comuns e boas práticas

  • Fechar o terminal «partido»: antes de desistir, escreva stty sane às cegas e carregue em Enter (ou Ctrl+J); se os caracteres continuarem estranhos, reset.
  • Desligar o eco sem garantia de o repor: guarde o estado com stty -g e reponha-o num trap … EXIT, ou use read -s. E faça echo depois da leitura: o Enter também não foi ecoado.
  • Correr stty num script sem terminal: no cron ou num pipe falha com Inappropriate ioctl for device. Teste primeiro com tty -s (ou [ -t 0 ]).
  • Redefinir teclas «para experimentar» em produção: um intr trocado faz o Ctrl+C falhar no pior momento. Se mudar, reponha logo.
  • Acertar o stty cols à mão sem necessidade: se não coincidir com a janela real, as linhas partem-se; redimensionar a janela repõe o valor certo.

Conclusão

O tty e o stty revelam como o Unix trata o terminal por dentro: um ficheiro de dispositivo com regras que pode ler e mudar — e o stty sane salva-o quando tudo corre mal. Se trabalha sobretudo em máquinas remotas, veja também o nosso artigo sobre o ssh e o scp; e, para perceber o que o Ctrl+C envia de facto, o artigo sobre o kill e o systemctl explica os sinais em detalhe.

Workshop — Linha de Comandos Linux

Quer passar da leitura à prática, com exercícios reais e acompanhamento? No workshop Linha de Comandos Linux da HJFR trabalha estes e outros comandos da série — da administração do dia a dia à resposta a incidentes.

Este artigo faz parte da série «Comandos Linux, um a um» do blog HJFR — fique atento aos próximos comandos.