![是否可以将 Linux 虚拟控制台内容和回滚保存在文件中?](https://linux22.com/image/82525/%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E5%B0%86%20Linux%20%E8%99%9A%E6%8B%9F%E6%8E%A7%E5%88%B6%E5%8F%B0%E5%86%85%E5%AE%B9%E5%92%8C%E5%9B%9E%E6%BB%9A%E4%BF%9D%E5%AD%98%E5%9C%A8%E6%96%87%E4%BB%B6%E4%B8%AD%EF%BC%9F.png)
我有一个长期运行的脚本,但我忘记将其输出重定向到文件。我可以在终端中看到它,但是我可以将其保存到文件中吗?
我不是要求tee
输出重定向(例如>
,>>
)等 - 命令已启动,我无法再次运行它。我需要保存已经生成的输出。如果我可以在显示器上看到它,则它位于存储/缓存/缓冲的某个位置。在哪里?
screendump
等/dev/vcsX
允许我仅保存终端输出上的最后一个屏幕(而不是当前屏幕! - 滚动终端没有帮助)。
这是在 Linux 虚拟控制台上,而不是像gnome-terminal
鼠标和其他东西那样的 X11 终端模拟器。
答案1
/dev/vcs[a]<n>
即使您向上滚动,也只会让您看到最后一个全屏,但是即使您向上滚动,ioctl()
使用的选择 sgpm
也将允许您转储当前显示的屏幕。
所以你可以这样做:
sleep 3; perl -e '
require "sys/ioctl.ph";
# copy:
ioctl(STDIN, &TIOCLINUX, $arg = pack("CS5", 2, 1, 1, 80, 25, 2));
# paste:
ioctl(STDIN, &TIOCLINUX, $arg = "\3")'; cat > file
将 80 和 25 调整为您的实际屏幕宽度和高度。
这sleep 3
让您有时间向上滚动(使用Shift+PageUP)到您想要转储的实际屏幕。cat > file
将粘贴重定向到file
.用 完成它Ctrl+D。
console_ioctl(4)
详情请参阅。
如果您已gpm
安装并运行,则可以使用鼠标进行选择。
Linux 虚拟控制台回滚和选择非常有限且非常烦人(因为当您切换控制台时,您会丢失整个回滚)。展望未来,我建议您使用 GNU 之类的东西screen
或tmux
其中的东西(我个人在功能更强大的终端中使用它们)。有了它们,您可以拥有更大的可搜索回滚并轻松将它们转储到文件中(甚至记录所有终端输出,以及这些终端多路复用器附带的所有其他好东西)。
至于自动转储整个回滚缓冲区的过程,在某些条件下应该是可能的,但由于 API 非常有限,所以相当困难。有一个未记录的ioctl
(TIOCLINUX,子代码=13)可以将当前虚拟控制台滚动一定的偏移量(向上滚动为负值,向下滚动为正值)。
但是(据我所知)无法知道回滚缓冲区的当前大小。因此很难知道何时到达缓冲区的顶部。如果您尝试滚动过去,屏幕将不会移动那么多,并且没有可靠的方法可以知道屏幕实际滚动了多少。
我还发现滚动 ioctl 的行为不稳定(至少对于 VGA 控制台),滚动少于 4 行只是偶尔有效。
下面的脚本似乎适用于帧缓冲区控制台(有时在 VGA 控制台上),前提是回滚缓冲区不包含长于一个屏幕加一行的相同行序列。
它非常慢,因为它一次滚动一行,并且在读取每个屏幕转储时需要等待 10 毫秒的 eof。
that-script > file
在虚拟控制台中使用。
#! /usr/bin/perl
require "sys/ioctl.ph";
($rows,$cols) = split " ", `stty size`;
$stty = `stty -g`; chomp $stty;
system(qw(stty raw -echo icrnl min 0 time 1));
sub scroll {
ioctl(STDIN, &TIOCLINUX, $arg = pack("Cx3l", 13, $_[0])) or die "scroll: $!";
}
sub grab {
ioctl(STDIN, &TIOCLINUX, $arg = pack("CS5", 2, 1, 1, $cols, $rows, 2)) or die "copy: $!";
ioctl(STDIN, &TIOCLINUX, $arg = "\3") or die "paste: $!";
return <STDIN>;
}
for ($s = 0;;$s--) {
scroll $s if $s;
@lines = grab;
if ($s) {
last if "@lines" eq "@lastlines";
unshift @output, $lines[0];
} else {
@output = @lines;
}
@lastlines = @lines;
}
print @output;
exec("stty", $stty);
答案2
https://github.com/jerome-pouiller/reredirect/可能是一个选择?
描述:
reredirect 是一个实用程序,用于获取现有正在运行的程序并将其输出(标准输出和错误输出)附加到文件或其他进程。
语法如下:
reredirect -m FILE PID