Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a long-term running script and I forgot to redirect its output to a file. I can see it in a terminal, but can I save it to a file?

I'm not asking for tee, output redirection (e.g. >, >>) etc - the command has started, and I can't run it again. I need to save already generated output. If I can see it on my display, it is somewhere stored/cached/buffered. Where?

screendump, /dev/vcsX and so on allows me to save only last screen on terminal output (not the current! - scrolling terminal doesn't help).

This is on a Linux virtual console, not a X11 terminal emulator like gnome-terminal with mouse and other goodies.

share|improve this question
1  
Yes, since you can see it, it is somewhere. Unfortunately, that somewhere is the hardware frame buffer for the display. It would probably be easier to transcribe it by hand than rip it out of the display hardware. – msw Feb 1 at 11:26
    
Interesting! But... It is missing somwhere, like in /dev/, right? Otherwise, you've wrote how to reach it. – Jury Feb 1 at 12:06
up vote 19 down vote accepted

/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);
share|improve this answer
1  
Magic!!! Thanks a lot! – Jury Feb 1 at 13:16

https://github.com/jerome-pouiller/reredirect/ might be an option?

Description:

reredirect is a utility for taking an existing running program and attaching its outputs (standard output and error output) to files or another process.

The syntax is as follows:

reredirect -m FILE PID
share|improve this answer
6  
This does not save already generated output as OP asked, only new output will be redirected somewhere. – jimmij Feb 1 at 10:59
    
That is true... – Adionditsak Feb 1 at 11:52
    
So, if my program already finished, I can only take a photo of my display? – Jury Feb 1 at 12:03

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.