Voici le produit final en action sur un xterm à écran partagé, des fonctions par défaut du shell à l'utilisation de quelques commandes:
Une façon plus grossière de le faire que celle illustrée dans la capture d'écran pourrait ressembler à ceci:
PS1='$( { date ; fc -l -0 ; } >${TGT_PTY} )'$PS1
Où ${TGT_PTY}
serait tout ce que vous retirez de la tty
commande lorsque vous exécutez réellement un shell interactif sur l'écran où vous voulez votre sortie. Ou, vraiment, vous pouvez utiliser n'importe quel fichier inscriptible car il s'agit essentiellement d'une cible pour la redirection de fichiers.
J'utilise la syntaxe pty pour le pseudo-terminal parce que je suppose que c'est un xterm d'une certaine sorte, mais vous pourriez tout aussi facilement dédier un vt - et votre historique en streaming n'est toujours qu'à une CTRL-ALT-Fn
combinaison de touches. Si c'était moi je pourrais combiner les deux notions et en faire une screen
ou tmux
session sur un vt dédié ... Mais je m'égare.
Sur une machine fraîchement démarrée, je suis accueilli par l' /bin/login
invite typique d'une getty
console Linux typique . J'appuie CTRL-ALT-F2
pour accéder à une kmscon
console moins typique qui se comporte beaucoup plus comme un xterm
que comme un tty
. J'entre la commande tty
et reçois en réponse /dev/pts/0
.
En général, xterms multiplexe un seul terminal en plusieurs en utilisant des pseudo-terminaux - donc si vous deviez faire une chose similaire dans X11 en basculant entre les onglets de terminal ou les fenêtres, vous recevriez probablement une sortie /dev/pts/[0-9]*
également. Mais les consoles de terminaux virtuels accessibles avec CTRL-ALT-Fn
des combinaisons de touches sont de véritables (terminaux) terminaux et reçoivent donc leur propre /dev/tty[0-9]*
désignation.
C'est pourquoi après la connexion à la console 2 lorsque je tape tty
à l'invite, la réponse est, /dev/pts/0
mais lorsque je fais de même sur la console 1, la sortie est /dev/tty1
. En tout cas, de retour sur la console 2 je fais alors:
bash
PS1='$( { date ; fc -l -0 ; } >/dev/tty1 )'$PS1
Il n'y a aucun effet perceptible. Je continue à taper quelques commandes supplémentaires, puis je passe à la console 1 en appuyant à CTRL-ALT-F1
nouveau. Et là, je trouve des entrées répétées qui ressemblent à <date_time>\n<hist#>\t<hist_cmd_string>
chaque commande que j'ai tapée sur la console 2.
À moins d'écrire directement sur un terminal, une autre option pourrait ressembler à ceci:
TGT_PTY=
mkfifo ${TGT_PTY:=/tmp/shell.history.pipe}
{ echo 'OPENED ON:'
date
} >${TGT_PTY}
Et puis peut-être ...
less +F ${TGT_PTY}
La commande d'invite approximative ne correspond pas à vos spécifications - pas de chaîne de date
formatage ni d'options de formatage pour les fc
deux - mais son mécanisme ne nécessite pas beaucoup: chaque fois que votre invite rend la dernière commande d'historique et la date et l'heure actuelles sont écrites dans le ${TGT_PTY}
fichier que vous spécifiez. C'est aussi simple que ça.
L'observation et l'impression de l'historique de la coque est fc
l'objectif principal de. C'est un shell intégré, même s'il date
ne l'est pas. Dans zsh
fc
peut fournir toutes sortes d'options de mise en forme fantaisie, dont plusieurs s'appliquent aux horodatages. Et bien sûr, comme vous le constatez ci - dessus, bash
est history
peut faire la même chose.
Dans l'intérêt d'une sortie plus propre, vous pouvez utiliser une technique que j'ai mieux expliquée ici pour définir une variable de suivi persistante dans le shell actuel , même si vous devez la suivre et la traiter en sous-coquilles dans la séquence d'invite.
Voici un moyen portable de formatage selon vos spécifications:
_HIST() { [ -z ${_LH#$1} ] ||
{ date "+${1}%t[%F %T]"
fc -nl -0
} >${TGT_PTY}
printf "(_LH=$1)-$1"
}
: "${_LH=0}"
PS1='${_LH##*[$(($(_HIST \!)))-9]}'$PS1
Je Mettre en oeuvre le last_history contre $_LH
que les pistes seulement les dernières mises à jour afin que vous n'écrivez pas la même commande l' histoire deux fois - par exemple juste pour entrer en appuyant sur. Il y a un peu de dispute nécessaire pour obtenir la variable incrémentée dans le shell actuel afin qu'elle conserve sa valeur même si la fonction est appelée dans un sous-shell - ce qui est, encore une fois, mieux expliqué dans le lien .
Sa sortie ressemble à <hist#>\t[%F %T]\t<hist_cmd>\n
Mais ce n'est que la version entièrement portable. Avec bash
cela, vous pouvez le faire avec moins et en implémentant uniquement des commandes internes de shell - ce qui est probablement souhaitable lorsque vous considérez que c'est une commande qui s'exécutera à chaque fois que vous appuyez sur [ENTER]
. Voici deux façons:
_HIST() { [ -z ${_LH#$1} ] || {
printf "${1}\t[%(%F %T)T]"
fc -nl -0
} >${TGT_PTY}
printf "(_LH=$1)-$1"
}
PROMPT_COMMAND=': ${_LH=0};'$PROMPT_COMMAND
PS1='${_LH##*[$(($(_HIST \!)))-9]}'$PS1
Alternativement, en utilisant bash
la history
commande de, vous pouvez définir la _HIST
fonction de cette façon:
_HIST() { [ -z ${_LH#$1} ] ||
HISTTIMEFORMAT="[%F %T]<tab>" \
history 1 >${TGT_PTY}
printf "(_LH=$1)-$1"
}
La sortie de l'une ou l'autre méthode ressemble également à ceci: <hist#>\t[%F %T]\t<hist_cmd>\n
bien que la history
méthode comprenne des espaces de début. Néanmoins, je pense que les history
horodatages de la méthode seront plus précis car je ne pense pas qu'ils devraient attendre que la commande référencée se termine avant d'acquérir leur tampon.
Vous pouvez éviter de suivre n'importe quel état dans les deux cas si seulement vous filtrez le flux avec uniq
- comme vous le feriez avec mkfifo
comme je l'ai mentionné précédemment.
Mais le faire dans l'invite comme ceci signifie qu'il est toujours mis à jour uniquement dès que cela est nécessaire par la simple action de mettre à jour l'invite. C'est simple.
Vous pouvez également faire quelque chose de similaire à ce que vous faites, tail
mais plutôt définir
HISTFILE=${TGT_PTY}
fn+1
pour comparer! Merci!