comando de script com efeitos ímpares ao redimensionar a janela do terminal

2

Há pouco tempo, decidi registrar todas as minhas atividades de terminal adicionando

script -t 0 "/Users/XXXXXXX/terminalLogs/log0$(date '+%y-%m-%d-%H:%M').txt"

ao meu arquivo .bash_profile. Isso funcionou geralmente como esperado, mas encontrei um problema com o redimensionamento de janelas.

Por isso, inicio a janela do meu terminal da seguinte forma:

Tudobem...seeu,emseguida,redimensionarajanelaeabrirumarquivousandovimeurecebo:

(você notará que a janela vim é menor que a janela do terminal)

Se eu digitar 'exit' para sair do registro, e redimensionar, eu recebo o terminal vim que eu esperava.

Então estou um pouco confuso e seria ótimo se as pessoas pudessem explicar o que está acontecendo, ou se pudessem sugerir um mod, ou se as pessoas tivessem ideias melhores de como eu deveria estar registrando comandos. :(

    
por Joe 02.03.2012 / 13:04

2 respostas

4

Quando você redimensiona a janela de um emulador de terminal, ele ajusta seu pseudo-terminal (“pty”) fazendo um TIOCSWINSZ ( Terminal IO Controle Set WINdow SiZe) chamada do sistema ioctl. Por sua vez, o kernel envia um sinal SIGWINCH (WINdow CHange) para o grupo de processos em primeiro plano (por exemplo, a instância em execução de Vim ) desse arquivo. Finalmente, o (s) programa (s) que receberam o SIGWINCH podem usar um ioctl TIOCGWINSZ (G for Get) para recuperar as novas dimensões da pty e se redesenhar apropriadamente.

Devido à forma como o programa script funciona, os programas que executam “dentro” da sessão script estão sendo executados em uma pty diferente da pty criada pelo emulador de terminal .

Considere este log:

% tty
/dev/ttys003
% script
Script started, output file is typescript
% tty
/dev/ttys004
% exit

Script done, output file is typescript

Inicialmente, o shell está sendo executado em ttys003 , mas o shell que é iniciado “dentro” da sessão script está sendo executado em ttys004 .

Se eu redimensionasse a janela do emulador de terminal antes de sair da sessão script , o emulador de terminal definiria o novo tamanho para ttys003 e o kernel enviaria um SIGWINCH para o script programa (o processo em primeiro plano de ttys003 ). O ideal é que o programa script leia as novas dimensões da "externa" e defina a "interna" para ter o mesmo tamanho. Isso, por sua vez, faria com que o grupo de processos em primeiro plano de ttys004 (isto é, sua instância Vim ) recebesse um SIGWINCH.

Infelizmente, a versão do script que você está usando ( versão da Apple do Lion ?) não parece transmitir a mudança no tamanho da janela (e o SIGWINCH não tratado é efetivamente ignorado). Outras versões ( do util-linux-ng ) parecem fazer um trabalho melhor no SIGWINCH, mas podem não ser facilmente compiláveis em seu sistema.

Se você puder aguentar manualmente a adaptação para o novo tamanho, você pode simplesmente executar o comando resize ( /usr/X11/bin/resize ) dentro do arquivo "inner". Ele consultará o emulador de terminal para o tamanho apropriado usando seqüências de escape e, em seguida, definirá o pty com as dimensões corretas. Em seu cenário declarado, você poderia fazer :!resize de dentro da sua instância Vim para redimensionar a pty “interna” (que o Vim notará quando o comando :! terminar).

Se você quiser que o redimensionamento automático funcione, então você terá que encontrar uma versão do script que propague corretamente alterações de dimensão pty (manipulando SIGWINCH e fazendo as próprias ioctls). Como alternativa, você pode substituir sua invocação script por uma chamada do seguinte programa Expect:

#!/usr/bin/expect
proc date {fmt} {
    clock format [clock seconds] -format $fmt
}
set file [if {$argc > 0} {lindex $argv 0} {list typescript}]

send_user "Script started, output file is $file\n"
log_file "$file"
send_log "Script started on [date %+]\n"

# WINCH code from http://ubuntuforums.org/showthread.php?t=865420
trap {
 set rows [stty rows]
 set cols [stty columns]
 stty rows $rows columns $cols < $spawn_out(slave,name)
} WINCH

spawn -noecho $env(SHELL)
interact

send_log "\nScript done on [date %+]\n"
log_file
send_user "Script done, output file is $file\n"

Dê um nome ao arquivo como seu único argumento:

 /path/to/script.expect "$HOME/terminalLogs/log0$(date '+%y-%m-%d-%H:%M').txt"
    
por 03.03.2012 / 11:58
0

Eu não tenho uma resposta definitiva, mas…

  • De acordo com sua página man ( $ man script ), script não parece gostar de programas interativos:

Certain interactive commands, such as vi(1), create garbage in the typescript file. The script utility works best with commands that do not manipulate the screen. The results are meant to emulate a hardcopy terminal, not an addressable one.

  • O tamanho "padrão" é igual ao tamanho da sua janela quando você inicia script .

  • É possível que script redefina ou desative forçosamente várias funções (como a capacidade de redimensionar a janela). A man page é omissa sobre esse assunto, mas acho que faria sentido evitar o redimensionamento.

por 02.03.2012 / 14:30