redimensionável janela do console serial?

25

Ao usar o console serial do meu sistema, sempre acabo com $COLUMNS=80e $LINES=24.

Embora eu possa alterar essas variáveis ​​manualmente, é um pouco chato fazer isso a qualquer momento quando a janela do terminal do lado do cliente foi redimensionada.

Normalmente, estou me conectando ao console usando screen /dev/mytty baudrate.

Alterar a $TERMvariável de ambiente para "tela" ou "xterm" não ajuda.

Preciso ligar gettycom alguns deles em vez do vt100?

Escusado será dizer que tudo isso funciona bem, quando eu me conecto à mesma máquina usando ssh.

Sven Geggus
fonte

Respostas:

26

Como os comentaristas antes de mim mencionaram, não há alternativa para chamar resizeapós cada comando, se você não possui esse comando e não deseja instalar um pacote em que ele está ( xterm), aqui estão dois scripts de shell POSIX que fazem o mesmo usando códigos de escape do terminal ANSI:

res() {

  old=$(stty -g)
  stty raw -echo min 0 time 5

  printf '\0337\033[r\033[999;999H\033[6n\0338' > /dev/tty
  IFS='[;R' read -r _ rows cols _ < /dev/tty

  stty "$old"

  # echo "cols:$cols"
  # echo "rows:$rows"
  stty cols "$cols" rows "$rows"
}

res2() {

  old=$(stty -g)
  stty raw -echo min 0 time 5

  printf '\033[18t' > /dev/tty
  IFS=';t' read -r _ rows cols _ < /dev/tty

  stty "$old"

  # echo "cols:$cols"
  # echo "rows:$rows"
  stty cols "$cols" rows "$rows"
}

BTW, no meu .profilearquivo você encontrará o seguinte: [ $(tty) = /dev/ttyS0 ] && res para que o tamanho do terminal seja determinado em cada login na linha serial (a que eu uso para gerenciamento), por exemplo, após a reinicialização do dispositivo.
Veja também a idéia de rsaw nos comentários de ter a linha [ $(tty) = /dev/ttyS0 ] && trap res2 DEBUGlá, para que o redimensionamento seja executado após cada comando (observe que o AFAIK nem sempre é possível ou não é possível busybox).

phk
fonte
3
PS: Para tornar mais permanente, adicione [[ $(tty) == /dev/ttyS0 ]] && trap res2 DEBUGa uma das configurações em seu perfil shell (por exemplo, /etc/profile, ~/.bash_profile). Isso fará com que seja executado após cada comando (o que seria bom se você estiver redimensionando janelas / painéis com screen / tmux / emulador de terminal).
rsaw
2
Depois de usá-lo por alguns minutos, rapidamente percebi que ambos rese res2são muito lentos para qualquer coisa, exceto para o primeiro login. Nas minhas máquinas, ambos estão demorando 0,5 segundo para terminar ... fazendo com que todos os meus comandos pareçam lentos (quando usados ​​com a armadilha DEBUG). Ops! Não pode ter isso. Acho que vou instalar xterm.
rsaw
3
O @phk xterm's resizeé muito mais rápido - geralmente 0,002seg.
rsaw
11
@rsaw Oh OK, bom saber, eu pensei que iria se comportar semelhante e, portanto, ser igualmente lento. Lembro-me que o de algumas busyboxes parecia ser tão lento para mim.
Php
11
Obrigado por esta solução autônoma. Estou usando uma distro somente para console que não possui o x11 ou o xterm instalado, portanto resizenão é uma opção.
thom_nic
16

Apenas para constar, aqui está a resposta para este problema (Usenet venceu):

Os aplicativos de console em execução dentro dos aplicativos de terminal virtual ( xterm, rxvte amigos) serão recebidos SIGWINCHapós a operação de redimensionamento. Assim, o aplicativo poderá redesenhar a janela etc. no manipulador de sinal correspondente.

Infelizmente, ao usar um console serial, não existe esse mecanismo.

No entanto, é possível que o aplicativo solicite ativamente o tamanho atual da janela do console. Portanto, a segunda melhor coisa é fazer isso toda vez que um prompt de comando é impresso pelo shell.

Isso pode ser conseguido primeiro compilando um executável de redimensionamento especial e, em seguida, usando o seguinte em bashrc:

if [ $(tty) == '/dev/ttyS0' ]; then
  trap resize DEBUG
fi

Obviamente, isso não alterará as configurações de tamanho do console em um aplicativo de console durante o tempo de execução.

Sven Geggus
fonte
11
Não deveria ser possível executar um protocolo sobre a linha de série, que não oferecem todas as funcionalidades? Quero dizer, temos um cliente e um servidor. Eles poderiam usar seqüências de escape na banda para fazer quase tudo e ainda trabalhar com um console serial de texto sem formatação!
Evi1M4chine
11
Na verdade, o comentário no código deixa claro que não é a versão resizeinstalada no seu sistema.
Thomas Dickey
9

Os terminais "redimensionáveis", como tais, são o resultado do NAWS ( Negotiate About Window Sizeda opção de tamanho de janela Telnet RFC 1073 ).

Se você estiver conectado diretamente ao computador usando uma porta serial, não há negociação envolvida e o computador não tem conhecimento direto do tamanho da tela do seu terminal.

Se um terminal puder negociar o tamanho, o computador enviará SIGWINCHpara aplicativos em execução no terminal, solicitando que eles atualizem sua noção do tamanho da tela.

Quando o computador não conhece o tamanho da tela, normalmente define o tamanho mostrado por stty -a(linhas e colunas) como zero. Para uso interativo, isso é um pouco hostil, e alguns sistemas usam variáveis ​​de ambiente LINESe COLUMNSpara ajudar. Os valores atribuídos podem ser derivados da descrição do terminal; mais frequentemente, eles são simplesmente codificados. A convenção para essas variáveis ​​exige que elas entrem em vigor, a menos que sejam explicitamente suprimidas, por exemplo, na use_envfunção de aplicações malditas . No lado positivo, essas variáveis ​​podem ser úteis quando nenhuma informação confiável estiver disponível. No lado negativo, não existe um método conveniente para alterar essas variáveis.

O resizeprograma (um utilitário fornecido com xterm) pode usar a sequência de escape do relatório de posição do cursor no estilo VT100 para determinar o tamanho da tela. Isso pode ser executado na linha de comando; não há (novamente) nenhuma maneira conveniente de fazer isso automaticamente. Como efeito colateral, resizeatualiza as informações nas linhas / colunas vistas por stty. Seu uso para fornecer variáveis ​​de ambiente atualizadas é útil principalmente para casos como este, onde LINESe COLUMNS são definidos, e deve ser atualizado.

Thomas Dickey
fonte
3

Aqui está outra solução que funcionou muito bem para mim no meu sistema Linux incorporado (Overo executando o Angstrom). Acabei de executá-lo no meu arquivo .bashrc. Eu não queria usar o redimensionamento porque isso requer a instalação de alguns pacotes X e não queria isso.

Dizendo ao seu Raspberry Pi que seu terminal é maior que 24 linhas | Blog de pensamentos superficiais

Austin Beer
fonte
3
Por favor, não basta postar um link: incluem os detalhes relevantes para que a informação está disponível aqui também ...
jasonwryan
11
Pena que precisa de Python.
Craig McQueen
1

Caso você possa usar o FreeBSD, existe o comando resizewin (1) , que faz exatamente o que você deseja.

Edward Tomasz Napierala
fonte
1

Ao executar uma sessão shell através de uma linha serial, basta chamar o resizecomando dentro dessa sessão - após estabelecer a conexão e após a alteração geométrica de cada terminal.

O resizecomando faz parte do xterm, mas não depende do X11. Por exemplo, no Fedora, ele é empacotado separadamente como xterm-resize.

Como funciona: o comando redimensionar mede a altura / largura através de alguns movimentos do cursor e envia esses valores ao terminal através de seqüências de escape.

Com um shell como o zsh, isso também atualiza automaticamente as variáveis LINESe COLUMNS(como alternativa, é possível avaliar as instruções de exportação que os comandos imprimem no stdout).

Por que isso é necessário: com uma sessão local ou ssh, o terminal pode sinalizar a sessão sobre alterações na geometria (consulte SIGWINCH). Esse mecanismo não funciona em uma conexão serial.

maxschlepzig
fonte
0

Aqui está uma função de redimensionamento simples e rápida que funciona apenas para o bash. Ele é modificado a partir do res2 do phk, usando o bash's read -d delimpara evitar que o tempo limite termine a leitura.

resize() {
  old=$(stty -g)
  stty -echo
  printf '\033[18t'
  IFS=';' read -d t _ rows cols _
  stty "$old"
  stty cols "$cols" rows "$rows"
}
Gary Guo
fonte