Est-il possible d'enregistrer le contenu de la console virtuelle Linux et de faire défiler dans un fichier?

21

J'ai un script en cours d'exécution à long terme et j'ai oublié de rediriger sa sortie vers un fichier. Je peux le voir dans un terminal, mais puis-je l'enregistrer dans un fichier?

Je ne demande pas tee, la redirection de sortie (par exemple >, >>) etc - la commande a commencé, et je ne peux pas courir à nouveau. J'ai besoin de sauvegarder la sortie déjà générée. Si je peux le voir sur mon écran, c'est quelque part stocké / mis en cache / tamponné. Où?

screendump, /dev/vcsXet ainsi de suite me permet d'enregistrer uniquement le dernier écran sur la sortie du terminal (pas le courant! - le terminal de défilement n'aide pas).

C'est sur une console virtuelle Linux, pas un émulateur de terminal X11 comme gnome-terminalavec la souris et autres goodies.

Jury
la source
1
Oui, puisque vous pouvez le voir, c'est quelque part. Malheureusement, c'est quelque part le tampon de trame matérielle pour l'affichage. Il serait probablement plus facile de le transcrire à la main que de l'extraire du matériel d'affichage.
msw
Intéressant! Mais ... Il manque quelque part, comme à l'intérieur /dev/, non? Sinon, vous avez écrit comment l'atteindre.
Jury

Réponses:

19

/dev/vcs[a]<n>vous n'obtiendrez que le dernier écran plein même si vous avez fait défiler vers le haut, mais la sélection ioctl()telle qu'utilisée par gpmvous permettra de vider l'écran actuellement affiché même lorsque vous avez fait défiler vers le haut.

Vous pouvez donc faire:

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

Ajustez le 80 et le 25 à votre largeur et hauteur d'écran réelles.

Le sleep 3vous donne le temps de faire défiler vers le haut (avec Shift+PageUP) jusqu'à l'écran que vous souhaitez vider. cat > fileredirige la pâte vers file. Terminez avec Ctrl+D.

Voir console_ioctl(4)pour plus de détails.

Si vous avez gpminstallé et exécuté, vous pouvez faire cette sélection avec la souris.

Le défilement et la sélection de la console virtuelle Linux sont très limités et assez ennuyeux (en ce que lorsque vous changez de console, vous perdez tout le défilement). À l'avenir, je vous suggère d'utiliser des choses comme GNU screenou tmuxen son sein (je les utilise personnellement dans des terminaux encore plus performants). Avec eux, vous pouvez avoir des défilements de recherche plus importants et les vider facilement dans des fichiers (et même enregistrer toutes les sorties du terminal, ainsi que tous les autres goodies fournis avec ces multiplexeurs de terminaux).


Quant à l'automatisation du processus de vidage de la totalité du tampon de défilement, cela devrait être possible dans certaines conditions, mais assez difficile car l'API est très limitée. Il existe un document non documenté ioctl(TIOCLINUX, sous-code = 13) pour faire défiler la console virtuelle actuelle d'un certain décalage (négatif pour le défilement vers le haut, positif pour le défilement vers le bas).

Il n'y a cependant aucun moyen (que je sache) de connaître la taille actuelle du tampon de défilement. Il est donc difficile de savoir quand vous avez atteint le sommet de ce tampon. Si vous essayez de le faire défiler, l'écran ne sera pas déplacé d'autant et il n'y a aucun moyen fiable de savoir à quel point l'écran a réellement défilé.

Je trouve également le comportement de l'ioctl de défilement erratique (au moins avec la console VGA), où le défilement de moins de 4 lignes ne fonctionne qu'occasionnellement.

Le script ci-dessous semble fonctionner pour moi sur les consoles de tampon de trames (et parfois sur les consoles VGA) à condition que le tampon de défilement ne contienne pas de séquences de lignes identiques plus longues qu'un écran plus une ligne.

C'est assez lent car il fait défiler une ligne à la fois et doit attendre 10 ms pour eof lors de la lecture de chaque vidage d'écran.

À utiliser à that-script > filepartir de la console virtuelle.

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

https://github.com/jerome-pouiller/reredirect/ pourrait être une option?

La description:

reredirect est un utilitaire pour prendre un programme en cours d'exécution et attacher ses sorties (sortie standard et sortie d'erreur) à des fichiers ou à un autre processus.

La syntaxe est la suivante:

reredirect -m FILE PID
Adionditsak
la source
7
Cela ne sauvegarde pas la sortie déjà générée comme l'OP l'a demandé, seule la nouvelle sortie sera redirigée quelque part.
jimmij
1
C'est vrai ...
Adionditsak
Donc, si mon programme est déjà terminé, je peux seulement prendre une photo de mon écran?
Jury