Czy można zapisać zawartość wirtualnej konsoli Linux i przewijać plik?

21

Mam długo działający skrypt i zapomniałem przekierować jego dane wyjściowe do pliku. Widzę to w terminalu, ale czy mogę zapisać go do pliku?

Nie pytam o teeprzekierowanie wyjścia (np >, >>) etc - komenda zaczęła, a ja nie mogę go uruchomić ponownie. Muszę zapisać już wygenerowane dane wyjściowe. Jeśli widzę to na moim wyświetlaczu, jest ono gdzieś przechowywane / buforowane / buforowane. Gdzie?

screendump, /dev/vcsXi tak dalej pozwala mi zapisać tylko ostatni ekran na wyjściu terminala (nie bieżący! - przewijanie terminala nie pomaga).

To jest na wirtualnej konsoli Linuksa, a nie na emulatorze terminali X11, takim jak gnome-terminalmysz i inne gadżety.

Jury
źródło
1
Tak, skoro możesz to zobaczyć, to gdzieś. Niestety, gdzieś jest sprzętowy bufor ramki dla wyświetlacza. Prawdopodobnie łatwiej byłoby go ręcznie przepisać niż wyjąć ze sprzętu wyświetlającego.
msw
Ciekawy! Ale ... brakuje jej gdzieś, na przykład /dev/, prawda? W przeciwnym razie napisałeś, jak to osiągnąć.
Jury

Odpowiedzi:

19

/dev/vcs[a]<n>sprawi, że ostatni ekran będzie pełny, nawet jeśli przewinąłeś w górę, ale wybrana opcja ioctl()s gpmpozwoli ci zrzucić aktualnie wyświetlany ekran nawet po przewinięciu w górę.

Możesz więc zrobić:

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

Dostosuj 80 i 25 do rzeczywistej szerokości i wysokości ekranu.

sleep 3Daje czas do przewijania w górę (z Shift+PageUP) do rzeczywistego ekranu chcesz zrzucić. cat > fileprzekierowuje wklej do file. Zakończ to za pomocą Ctrl+D.

Zobacz console_ioctl(4)szczegóły.

Jeśli masz gpmzainstalowany i uruchomiony, możesz dokonać wyboru za pomocą myszy.

Przewijanie i wybór wirtualnej konsoli Linuxa jest bardzo ograniczony i dość irytujący (w tym momencie, gdy zmieniasz konsolę, tracisz całe przewijanie). Idąc dalej, sugeruję, abyś używał takich rzeczy jak GNU screenlub tmuxw nim (osobiście używam ich w jeszcze bardziej wydajnych terminalach). Dzięki nim możesz mieć większe przewijane strony do przeszukiwania i łatwo zrzucić je do plików (a nawet zalogować wszystkie dane wyjściowe terminala oraz wszystkie inne gadżety, które są dostarczane z tymi terminalowymi multiplekserami).


Jeśli chodzi o automatyzację procesu zrzucania całego bufora przewijania, powinno to być możliwe w pewnych warunkach, ale dość trudne, ponieważ interfejs API jest bardzo ograniczony. Istnieje nieudokumentowane ioctl(TIOCLINUX, subkod = 13) przewijanie bieżącej konsoli wirtualnej o pewne przesunięcie (ujemne przy przewijaniu w górę, dodatnie przy przewijaniu w dół).

Nie ma jednak sposobu (o którym wiem), aby poznać aktualny rozmiar bufora przewijania. Trudno więc wiedzieć, kiedy osiągnąłeś szczyt tego bufora. Jeśli spróbujesz przewinąć obok, ekran nie zostanie przesunięty o tyle i nie ma wiarygodnego sposobu, aby dowiedzieć się, o ile ekran faktycznie przewinął.

Uważam też, że zachowanie przewijanego ioctl jest nieprawidłowe (przynajmniej z konsolą VGA), gdzie przewijanie o mniej niż 4 linie działa tylko sporadycznie.

Poniższy skrypt wydaje mi się działać na konsolach bufora ramki (i czasami na VGA), pod warunkiem, że bufor przewijania nie zawiera sekwencji identycznych linii dłuższych niż jeden ekran plus jedna linia.

Jest dość powolny, ponieważ przewija jedną linię na raz i musi czekać 10 ms na eof podczas czytania każdego zrzutu ekranu.

Do użycia that-script > filez poziomu wirtualnej konsoli.

#! /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);
Stéphane Chazelas
źródło
0

https://github.com/jerome-pouiller/reredirect/ może być opcją?

Opis:

reredirect to narzędzie do pobierania istniejącego programu i dołączania jego wyników (standardowe wyjście i wyjście błędów) do plików lub innego procesu.

Składnia jest następująca:

reredirect -m FILE PID
Adionditsak
źródło
7
Nie zapisuje to już wygenerowanych danych wyjściowych zgodnie z zapytaniem OP, tylko nowe dane wyjściowe zostaną przekierowane gdzieś.
jimmij
1
To prawda ...
Adionditsak
Więc jeśli mój program już się zakończył, mogę zrobić tylko zdjęcie mojego wyświetlacza?
Jury