Можно ли сохранить содержимое виртуальной консоли Linux и прокрутку в файл?

21

У меня есть долгосрочный сценарий, и я забыл перенаправить его вывод в файл. Я вижу это в терминале, но могу ли я сохранить его в файл?

Я не спрашиваю tee, перенаправление вывода (например >, >>) и т. Д. - команда запущена, и я не могу запустить ее снова. Мне нужно сохранить уже сгенерированный вывод. Если я вижу его на моем дисплее, он где-то хранится / кэшируется / буферизируется. Где?

screendump, /dev/vcsXИ так далее позволяет мне сохранить только последний экран на выходе терминала ( а не текущий - терминал прокрутки не поможет).

Это на виртуальной консоли Linux, а не на эмуляторе терминала X11, как gnome-terminalс мышью и другими вкусностями.

Жюри
источник
1
Да, так как вы можете видеть это, это где-то. К сожалению, это где-то аппаратный буфер кадров для дисплея. Вероятно, было бы легче переписать его вручную, чем вырвать его из оборудования дисплея.
MSW
Интересный! Но ... Это не хватает где-то, как в /dev/, верно? В противном случае вы написали, как этого достичь.
Жюри

Ответы:

19

/dev/vcs[a]<n>Вы получите только последний заполненный экран, даже если вы прокрутили его вверх, но выбор, ioctl()как используется, gpmпозволит вам сбросить отображаемый в данный момент экран, даже если вы прокрутили вверх.

Так что вы можете сделать:

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 мсек при чтении каждого снимка экрана.

Используется как 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);
Стефан Шазелас
источник
0

https://github.com/jerome-pouiller/reredirect/ может быть вариант?

Описание:

reredirect - это утилита, которая берет существующую работающую программу и присоединяет ее выходы (стандартный вывод и вывод ошибок) к файлам или другому процессу.

Синтаксис выглядит следующим образом:

reredirect -m FILE PID
Adionditsak
источник
7
Это не сохраняет уже сгенерированный вывод как запрос OP, только новый вывод будет перенаправлен куда-то.
Джимми
1
Это правда ...
Adionditsak
Итак, если моя программа уже закончена, я могу только сфотографировать мой дисплей?
Жюри