Вопрос команда сценария, имеющая нечетные эффекты при изменении размера окна терминала


Некоторое время назад я решил зарегистрировать все свои действия в терминале, добавив

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

в файл .bash_profile. Это работало, как и ожидалось, но я обнаружил проблему с изменением размера окон.

Поэтому я запускаю свое окно терминала так:

enter image description here

Все отлично ... если я затем изменю размер окна и открою файл с помощью vim, я получу:

enter image description here

(вы заметите, что окно vim меньше окна терминала)

Если я нахожу «exit» для выхода из журнала и изменяю размер, я получаю терминал vim, которого я ожидал.

enter image description here

Поэтому я немного смущен, и было бы здорово, если бы люди могли либо объяснить, что происходит, или если они могут предложить мод, или если у людей есть лучшие идеи о том, как я должен регистрировать команды. :(


2
2018-03-02 12:04


происхождения


Было бы интересно, если бы у вас было такое же поведение с использованием другого терминального приложения, такого как iTerm2. Вы пробовали это? - cyphorious


ответы:


Когда вы изменяете размер окна эмулятора терминала, он настраивает его псевдотерминал («Pty»), сделав системный вызов ioctl TIOCSWINSZ (Terminal IO Control Set WINdow SiZe). В свою очередь, ядро ​​отправляет сигнал SIGWINCH (WINdow CHange) в группу процессов переднего плана (например, исполняемый экземпляр напор) этого pty. Наконец, программа (ы), которая получила SIGWINCH, может использовать TIOCGWINSZ (G для Get) ioctl для извлечения новых измерений pty и, по мере необходимости, перерисовать.

Из-за скрипт программа работает, программы, запущенные «внутри» скрипт сеанс фактически выполняется на другом pty из pty, созданного эмулятором терминала.

Рассмотрим этот журнал:

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

Script done, output file is typescript

Первоначально оболочка работает ttys003, но оболочка, которая запускается «внутри» скрипт сеанс работает ttys004,

Если я изменил размер окна эмулятора терминала перед выходом из скрипт сессии, эмулятор терминала установил новый размер для ttys003, и ядро ​​отправит SIGWINCH в скрипт программы (процесс переднего плана ttys003). В идеале скрипт программа будет считывать новые измерения «внешнего» pty и устанавливать «внутренний» pty одинакового размера. Это, в свою очередь, вызовет группу процессов переднего плана ttys004 (т. е. напор экземпляр) для получения SIGWINCH.

К сожалению, версия скрипт ты используешь (Версия от Apple от Lion?), как представляется, не проходит по изменению размера окна (и необработанный SIGWINCH фактически игнорируется). Другие версии (от util-linux-ng), похоже, лучше справляются с работой SIGWINCH, но они могут быть легко компилируемы в вашей системе.


Если вы можете стоять, чтобы вручную активировать адаптацию к новому размеру, вы можете просто запустить изменить размер команда (/usr/X11/bin/resize) внутри «внутреннего» pty. Он запросит эмулятор терминала для соответствующего размера с помощью управляющих последовательностей, а затем установит pty в правильные размеры. В вашем заявленном сценарии вы можете сделать :!resize изнутри напор экземпляр, чтобы изменить размер «внутреннего» pty (который Vim заметит, когда :! команда завершена).

Если вы хотите, чтобы автоматическое изменение размера работало, вам нужно будет найти версию скрипт который правильно распространяет изменения размера pty (путем обработки SIGWINCH и создания правильных ioctls). Кроме того, вы можете заменить script вызов с вызовом следующей программы 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"

Дайте ему имя файла в качестве единственного аргумента:

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

4
2018-03-03 10:58



вау ... это вполне ответ ... :) - Joe


У меня нет окончательного ответа, но ...

  • Согласно его странице руководства ($ man script), script не похоже на интерактивные программы:

Некоторые интерактивные команды, такие как vi (1), создают мусор в   машинописный файл. Утилита script лучше всего работает с командами, которые   не манипулируйте экраном. Результаты предназначены для подражания   печатный терминал, а не адресный.

  • Размер «по умолчанию» совпадает с размером вашего окна при запуске script,

  • Возможно, что script принудительно сбрасывает или отключает кучу функций (например, возможность изменения размера окна). На странице руководства не говорится об этой теме, но я думаю, что было бы целесообразно предотвратить изменение размера.


0
2018-03-02 13:30