2

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

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

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

Итак, я запускаю окно терминала так:

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

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

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

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

2 ответа2

4

Когда вы изменяете размер окна эмулятора терминала, он настраивает свой псевдотерминал («pty»), выполняя системный вызов ioctl TIOCSWINSZ (терминал ввода-вывода Idct SiZe). В свою очередь, ядро отправляет сигнал SIGWINCH (WINdow CHange) в группу процессов переднего плана (например, запущенный экземпляр Vim) этого pty. Наконец, программы, которые получили SIGWINCH, могут использовать ioctl TIOCGWINSZ (G для Get), чтобы получить новые измерения 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 (т. Е. Ваш экземпляр Vim) получит сигнал SIGWINCH.

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


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

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

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

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

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

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .