É possível salvar o conteúdo e a rolagem do console virtual do Linux em um arquivo?

21

Eu tenho um script em execução a longo prazo e esqueci de redirecionar sua saída para um arquivo. Eu posso vê-lo em um terminal, mas posso salvá-lo em um arquivo?

Eu não estou pedindo tee, redirecionamento de saída (por exemplo >, >>) etc - o comando foi iniciado e não posso executá-lo novamente. Eu preciso salvar a saída já gerada. Se eu conseguir vê-lo no meu monitor, ele está em algum lugar armazenado / armazenado em cache / em buffer. Onde?

screendump, /dev/vcsXe assim por diante permitem salvar apenas a última tela na saída do terminal (não o atual! - o terminal de rolagem não ajuda).

Este é um console virtual Linux, não um emulador de terminal X11, como o gnome-terminalmouse e outras guloseimas.

Júri
fonte
1
Sim, como você pode vê-lo, está em algum lugar. Infelizmente, esse local é o buffer do quadro de hardware da tela. Provavelmente seria mais fácil transcrevê-lo manualmente do que arrancá-lo do hardware da tela.
RSU
Interessante! Mas ... Está faltando em algum lugar, como em /dev/, certo? Caso contrário, você escreveu como alcançá-lo.
Júri

Respostas:

19

/dev/vcs[a]<n>você receberá a última tela cheia, mesmo se você tiver rolado a tela para cima, mas as seleções ioctl()usadas por gpmele permitirão que você despeje a tela exibida no momento, mesmo quando você rolou a tela para cima.

Então você pode fazer:

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

Ajuste o 80 e o 25 para a largura e altura reais da tela.

A sleep 3dá-lhe tempo para rolar para cima (com Shift+PageUP) para a tela real que você deseja despejar. cat > fileredireciona a pasta para file. Terminar com Ctrl+D.

Veja console_ioctl(4)para detalhes.

Se você gpminstalou e está executando, pode fazer essa seleção com o mouse.

A rolagem e seleção do console virtual do Linux são muito limitadas e bastante irritantes (quando você alterna o console, você perde a rolagem inteira). No futuro, sugiro que você use coisas como o GNU screenou tmuxdentro dele (eu pessoalmente as uso em terminais ainda mais capazes). Com eles, é possível obter retornos de rolagem pesquisáveis ​​maiores e despejá-los facilmente em arquivos (e até registrar toda a saída do terminal, além de todos os outros itens fornecidos com esses multiplexadores de terminal).


Quanto à automação do processo para despejar todo o buffer de rolagem, deve ser possível em algumas condições, mas bastante difícil, pois a API é muito limitada. Há um documento não documentado ioctl(TIOCLINUX, subcódigo = 13) para rolar o console virtual atual em algum deslocamento (negativo para rolar para cima, positivo para rolar para baixo).

No entanto, não há como (que eu saiba) saber o tamanho atual do buffer de rolagem. Portanto, é difícil saber quando você alcançou o topo desse buffer. Se você tentar rolar além, a tela não será alterada tanto e não há uma maneira confiável de saber quanto a tela realmente rolou.

Também acho o comportamento da rolagem ioctl irregular (pelo menos com o console VGA), em que a rolagem em menos de 4 linhas funciona apenas ocasionalmente.

O script abaixo parece funcionar para mim nos consoles de buffer de quadro (e ocasionalmente nos de VGA), desde que o buffer de rolagem não contenha sequências de linhas idênticas com mais de uma tela e mais uma linha.

É muito lento porque rola uma linha de cada vez e precisa aguardar 10 ms pelo eof ao ler cada despejo de tela.

Para ser usado a that-script > filepartir do console virtual.

#! /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
fonte
0

https://github.com/jerome-pouiller/reredirect/ pode ser uma opção?

Descrição:

O reredirect é um utilitário para pegar um programa em execução existente e anexar suas saídas (saída padrão e saída de erro) a arquivos ou outro processo.

A sintaxe é a seguinte:

reredirect -m FILE PID
Adionditsak
fonte
7
Isso não salva a saída já gerada, conforme solicitado pelo OP, apenas uma nova saída será redirecionada para algum lugar.
jimmij
1
Isso é verdade ...
Adionditsak
Então, se meu programa já terminou, só posso tirar uma foto da minha tela?
Júri