Invite de coup en dessous de la sortie - queue du journal d'arrière-plan


15

J'avais l'habitude de travailler pour une entreprise qui avait un shell personnalisé pour la gestion de l'un de leurs produits fonctionnant sous Linux et je cherche à reproduire une fonctionnalité clé de ce shell.

Tout le travail a été effectué par un processus d'arrière-plan et la sortie du journal affichée pour tous les utilisateurs connectés.

Le journal suivrait en arrière-plan votre coque et la ligne d'invite resterait toujours parfaitement en bas.

Par exemple

Log line 1
Log line 2
Log line 3
![ROOT@PRODUCT51-LIVE]:~/ #

La façon dont j'ai essayé de le faire avec bash était de démarrer une queue détachée dans le fichier .bashrc des utilisateurs, mais lorsque la sortie de la commande est envoyée à stdout - elle apparaît sous l'invite bash, par exemple

![ROOT@PRODUCT51-LIVE]:~/ #Log line 1
Log line 2
Log line 3

Et l'utilisateur devrait appuyer sur Entrée ou CtrlCpour une ligne d'invite propre.

Je n'ai pas d'idées sur la façon de faire en sorte que l'invite passe toujours au bas de la sortie et je pense que j'utilise la mauvaise terminologie pour trouver quoi que ce soit sur Google car je n'ai pas de chance - quelqu'un sait-il comment faire cela avec bash?


1
Vous voulez que la mise à jour de sortie soit instantanée ou lorsque vous obtenez une nouvelle invite?
ahilsend

Instantanément, il est donc aussi identique que possible à l'exécution de "tail -f", mais avec l'invite en bas.
iamacarpet

Qu'advient-il de la tail -fsortie et de l'invite et de la sortie de la commande lorsque vous entrez une commande qui a une quantité importante de sortie, en particulier lorsque votre processus d'arrière-plan envoie activement sa sortie?
pause jusqu'à nouvel ordre.

Dans leur cas, les commandes qui s'exécuteraient ne provoquaient que la sortie via le processus d'arrière-plan, pas par elles-mêmes, donc ce n'était pas un problème. Dans ce cas, une fois que nous obtenons une solution qui donne l'effet souhaité, je pense qu'il s'agira de jouer et de voir à quel point la sortie mélangée serait mauvaise d'une mise en œuvre à l'autre.
iamacarpet

1
Ensuite, je soutiens fortement la suggestion d'utiliser screen ou tmux. La sortie ne sera pas mélangée ou ne se battra pas pour l'espace d'écran et vous pouvez redimensionner les fenêtres (déplacer le fractionnement) et les faire défiler indépendamment. Si votre objection est que les lignes d'en-tête / pied de page / d'état soient "lourdes", il est possible de configurer cela. Aucune roue réinventée.
pause jusqu'à nouvel ordre.

Réponses:


1

Ce qui suit fait ce dont vous avez besoin, sans utiliser tmux ou screen ou d'autres programmes. Conserve l'invite en bas. Remplacez "/ var / log / cron" par le fichier dont vous avez besoin:

#!/bin/bash 
L=$(tput lines)
L1=${L}
(( L1-- ))
C=$(tput cols)
tput cup ${L} 0
tail -f /var/log/cron | while read line; do 
  tput sc
  printf "\e[1;${L1}r\e[${L1};${C}f" 
  echo; echo ${line}
  printf "\e[1;${L}r" && tput rc
done

la clé de ce sont les caractères de contrôle ANSI pour le terminal. En particulier l'instruction "\ e [x; y" qui définit une nouvelle zone de défilement. Ainsi, à mesure que chaque ligne du fichier journal est lue, la ligne du bas de la fenêtre est exclue de la zone de défilement, la ligne du fichier journal est insérée, puis le bas est ajouté à nouveau.


Merci Michael, cela fonctionne à merveille =] - J'ai le problème occasionnel que vous tapez alors qu'il y a beaucoup de ligne de journal qui défile, vous ne pouvez pas reculer tout le texte sur votre ligne de console (je testais avec un journal d'apache occupé), mais pour ce que je veux l'utiliser, cela ne devrait pas être un problème.
iamacarpet

@iamacarpet Awesome. Heureux que cela fonctionne pour vous.
Michael Martinez

11

La réponse est écran ou tmux a été utilisé

Je vais vous expliquer comment vous pouvez configurer un tel écran en utilisant

1) Installer l'écran en utilisant soit apt-get install screensur les yum install screendérivés Ubuntu / Debian ou RedHat.

2) screen -S shell_and_logs

3) Appuyez ensuite sur Ctrl+ a, suivi de S(S majuscule).
Un écran horizontal apparaîtra

4) Appuyez sur Ctrl+ asuivi de TAB
Cela vous amènera à la deuxième fenêtre partagée.

5) Créez une autre fenêtre ici pour obtenir l'invite de commande en appuyant sur Ctrl+ arelâchez les touches puis appuyez surc

6) Vous pouvez redimensionner le deuxième windo en appuyant sur Ctrl+ apuis en tapant :resizeaprès quoi Lines:apparaîtra. Saisissez le nombre de lignes que vous souhaitez afficher.

7) Enfin, vous pouvez basculer entre les fenêtres de Ctrl+ asuivi deTAB

Voir l'exemple ci-dessous


Merci val0x00ff - J'aime l'idée, elle fait le travail - mais elle n'a pas l'air aussi propre que l'expérience fournie par le système en question. Pour un utilisateur inexpérimenté, ce n'est pas aussi transparent - c'est évidemment un autre shell, plutôt que de simplement avoir l'impression que votre shell principal vous tient au courant.
iamacarpet

@iamacarpet tail -F /var/log/messages &est une autre façon de vous montrer des messages lorsque quelque chose change, par exemple lorsqu'un échec de connexion est découvert ou lorsqu'un service rencontre des problèmes. Ce n'est cependant pas idéal car cela gâchera votre shell interactif.
Valentin Bajrami

Oui, c'est exactement ce que je demandais - un moyen de le faire sans gâcher le shell interactif - comme c'est ce qu'ils avaient réussi à faire sur le shell des entreprises - mais ce serait bien de ne pas avoir à écrire un shell à partir de zéro pour l'accomplir.
iamacarpet

1
@iamacarpet Il y a un tas d'autres outils en plus screenet tmuxqui peuvent le faire - par exemple, certains BSD sont livrés avec une windowcommande. Étant donné le choix, je recommanderais cette solution plutôt qu'un shell personnalisé ou les autres options disponibles en raison de sa flexibilité. Il peut ne pas être aussi transparent pour l'utilisateur final, mais ils ne sauront vraiment pas la différence, et les utilisateurs avancés / administrateurs système pourront utiliser la flexibilité supplémentaire offerte par screen.
voretaq7

@iamacarpet t=$(mktemp); printf '%s\n' 'screen tail -F /var/log/messages' split focus screen > "$t"; screen -S screenname -c "$t"Mettez-le dans un script et exécutez-le chaque fois que vous le souhaitez. Merci à Geirha pour cela sur #bash @ irc.freenode.org
Valentin Bajrami
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.