Is it possible to save Linux virtual console content and scrollback in a file?

/dev/vcs[a]<n> will only get you the last screen-full even if you've scrolled up, but the selection ioctl()s as used by gpm will allow you to dump the currently displayed screen even when you've scrolled up.

So you can can do:

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

Adjust the 80 and 25 to your actual screen width and height.

The sleep 3 gives you time to scroll up (with Shift+PageUP) to the actual screen you want to dump. cat > file redirects the paste to file. Finish it with Ctrl+D.

See console_ioctl(4) for details.

If you have gpm installed and running, you can do that selection with the mouse.

The Linux virtual console scrollback and selection are very limited and quite annoying (in that when you switch console, you lose the whole scrollback). Going forward, I'd suggest you use things like GNU screen or tmux within it (I personally use them in even more capable terminals). With them, you can have larger searchable scrollbacks and easily dump them to files (and even log all the terminal output, plus all the other goodies that come with those terminal multiplexers).


As to automating the process to dump the whole scrollback buffer, it should be possible under some conditions, but quite difficult as the API is very limited. There is an undocumented ioctl (TIOCLINUX, subcode=13) to scroll the current virtual console by some offset (negative for scrolling up, positive for scrolling down).

There is however no way (that I know) to know the current size of the scrollback buffer. So it's hard to know when you've reached the top of that buffer. If you attempt to scroll past it, the screen will not be shifted by as much and there's no reliable way to know by how much the screen has actually scrolled.

I also find the behaviour of the scrolling ioctl erratic (at least with the VGA console), where scrolling by less than 4 lines works only occasionally.

The script below seems to work for me on frame buffer consoles (and occasionally on VGA ones) provided the scrollback buffer doesn't contain sequences of identical lines longer than one screen plus one line.

It's quite slow because it scrolls one line at a time, and needs to wait 10ms for eof when reading each screen dump.

To be used as that-script > file from within the virtual console.

#! /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);

Tags:

Linux

Console