调整终端窗口大小时脚本命令会产生奇怪的效果

调整终端窗口大小时脚本命令会产生奇怪的效果

不久前,我决定通过添加以下方法记录我的所有终端活动:

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

到我的 .bash_profile 文件。这通常按预期工作,但我发现调整窗口大小时存在问题。

因此我按如下方式启动终端窗口:

在此处输入图片描述

一切都很好...如果我调整窗口大小并使用 vim 打开文件,我会得到:

在此处输入图片描述

(您会注意到 vim 窗口比终端窗口小)

如果我输入“exit”退出日志记录并调整大小,我就会得到我期望的 vim 终端。

在此处输入图片描述

所以我有点困惑,如果有人可以解释发生了什么,或者他们可以建议一个模型,或者人们对我应该如何记录命令有更好的想法,那就太好了。:(

答案1

当你调整终端仿真器窗口的大小时,它会调整其伪终端(“pty”)通过进行 TIOCSWINSZ(终端 IO 控制集 WINdow SiZe)ioctl 系统调用。反过来,内核向前台进程组(例如正在运行的Vim) 的 pty。最后,收到 SIGWINCH 的程序可以使用 TIOCGWINSZ(G 代表获取)ioctl 来检索新的 pty 尺寸并根据需要重新绘制自身。

由于脚本程序工作时,在“内部”运行的程序脚本会话实际上在与终端仿真器创建的 pty 不同的 pty 上运行。

考虑这个日志:

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

Script done, output file is typescript

最初,shell 在 上运行ttys003,但在 内部启动的 shell脚本会话正在运行ttys004

如果我在退出之前调整了终端仿真器窗口的大小脚本会话中,终端仿真器将设置新的大小ttys003,内核将向脚本程序(的前台进程ttys003)。理想情况下,脚本程序将读取“外部” pty 的新尺寸,并将“内部” pty 设置为相同的尺寸。这反过来会导致前台进程组ttys004(即您的Vim例如,接收 SIGWINCH。

不幸的是,脚本您正在使用 (Apple 版本的 Lion?) 似乎不会传递窗口大小的变化(并且未处理的 SIGWINCH 会被有效忽略)。其他版本(来自 util-linux-ng) 似乎在处理 SIGWINCH 方面做得更好,但它们可能不易在您的系统上编译。


如果你可以手动触发适应新尺寸,那么你可以简单地运行调整大小命令(/usr/X11/bin/resize)。它将使用转义序列向终端仿真器查询适当的大小,然后将 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"

答案2

我没有明确的答案但是...

  • 根据它的手册页($ man script),script似乎不喜欢交互式程序:

某些交互式命令(如 vi(1))会在 typescript 文件中产生垃圾。脚本实用程序最适合处理不操作屏幕的命令。结果旨在模拟硬拷贝终端,而不是可寻址终端。

  • “默认”大小与启动时的窗口大小相同script

  • 这可能会script强制重置或禁用一系列功能(例如调整窗口大小的功能)。手册页没有提到这个主题,但我认为阻止调整大小是有意义的。

相关内容