Aqui está o produto final em ação em um xterm de tela dividida, dos padrões basicamente do shell ao trabalho em apenas alguns comandos:

Uma maneira mais difícil de fazer isso do que é demonstrado na captura de tela pode ser assim:
PS1='$( { date ; fc -l -0 ; } >${TGT_PTY} )'$PS1
Onde ${TGT_PTY}estaria o que você obtém do ttycomando ao executar um shell interativo na tela em que deseja sua saída. Ou, realmente, você pode usar qualquer arquivo gravável, pois é essencialmente apenas um alvo para o redirecionamento de arquivos.
Eu uso a sintaxe pty para pseudo-terminal, porque estou assumindo que é um xterm de algum tipo, mas você pode dedicar um vt com a mesma facilidade - e seu histórico transmitido é sempre apenas uma CTRL-ALT-Fncombinação de teclas. Se fosse comigo eu poderia combinar as duas noções e torná-lo um screenou tmuxsessão em um vt dedicado ... Mas eu discordo.
Em uma máquina recém-inicializada, sou recebido com o /bin/loginprompt típico em um gettyconsole Linux típico . Pressiono CTRL-ALT-F2para acessar um kmsconconsole menos típico que se comporta muito mais como um xtermque com um tty. Entro no comando ttye recebo em resposta /dev/pts/0.
Geralmente, os xterms multiplexam um único dispositivo de terminal em vários usando pseudo-terminais - portanto, se você fizesse algo semelhante no X11 alternando entre as guias ou janelas do terminal, provavelmente também receberia saída /dev/pts/[0-9]*. Mas os consoles de terminais virtuais acessados com CTRL-ALT-Fncombinações de teclas são verdadeiros dispositivos de terminal e, portanto, recebem sua própria /dev/tty[0-9]*designação.
É por isso que, depois de entrar no console 2, quando digito ttyno prompt, a resposta é, /dev/pts/0mas quando faço o mesmo no console 1, a saída é /dev/tty1. De qualquer forma, de volta ao console 2, faço:
bash
PS1='$( { date ; fc -l -0 ; } >/dev/tty1 )'$PS1
Não há efeito discernível. Continuo digitando mais alguns comandos e depois mudo para o console 1 pressionando CTRL-ALT-F1novamente. E lá encontro entradas repetidas que se parecem com <date_time>\n<hist#>\t<hist_cmd_string>todos os comandos que digitei no console 2.
Com exceção da gravação direta em um dispositivo terminal, outra opção poderia ser algo como:
TGT_PTY=
mkfifo ${TGT_PTY:=/tmp/shell.history.pipe}
{ echo 'OPENED ON:'
date
} >${TGT_PTY}
E então talvez ...
less +F ${TGT_PTY}
O comando rough prompt não atende às suas especificações - nenhuma string de dateformatação para e nenhuma opção de formatação para fcelas - mas seu mecanismo não exige muito: toda vez que seu prompt renderiza o último comando do histórico e a data e hora atuais são gravadas em o ${TGT_PTY}arquivo que você especificar. É simples assim.
Observar e imprimir o histórico do shell é fco objetivo principal do. É um shell embutido, mesmo que datenão seja. O In zsh fcpode fornecer todos os tipos de opções de formatação sofisticadas, várias das quais se aplicam a carimbos de data e hora. E é claro, como você notou acima, basho historypode fazer o mesmo.
No interesse de uma saída mais limpa, você pode usar uma técnica que expliquei melhor aqui para definir uma variável de rastreamento persistente no shell atual, apesar de ter que rastreá-lo e processá-lo em subshells na sequência de prompt.
Aqui está um meio portátil de formatar com suas especificações:
_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
Eu implemento o contador last_history$_LH que apenas rastreia as atualizações mais recentes para que você não escreva o mesmo comando de histórico duas vezes - por exemplo, apenas pressionando enter. Há um pouco de disputa necessária para incrementar a variável no shell atual, para que ela retenha seu valor mesmo que a função seja chamada em um subshell - o que é novamente explicado melhor no link .
Sua saída parece <hist#>\t[%F %T]\t<hist_cmd>\n
Mas essa é apenas a versão totalmente portátil. Com bashisso, pode ser feito com menos e implementando apenas os recursos internos do shell - o que provavelmente é desejável quando você considera que este é um comando que será executado toda vez que você pressionar [ENTER]. Aqui estão duas maneiras:
_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
Como alternativa, usando basho historycomando 's , você pode definir a _HISTfunção desta maneira:
_HIST() { [ -z ${_LH#$1} ] ||
HISTTIMEFORMAT="[%F %T]<tab>" \
history 1 >${TGT_PTY}
printf "(_LH=$1)-$1"
}
A saída para qualquer método também se parece com: <hist#>\t[%F %T]\t<hist_cmd>\nembora o historymétodo inclua alguns espaços em branco à esquerda. Ainda assim, acredito que os historycarimbos de data e hora do método serão mais precisos, pois não acho que precisariam esperar o comando referenciado ser concluído antes de adquirir o carimbo.
É possível evitar o rastreamento de qualquer estado nos dois casos, se você filtrar o fluxo de alguma forma uniq- como você pode fazer mkfifocomo mencionei antes.
Mas fazê-lo no prompt como este significa que ele sempre é atualizado apenas assim que necessário, apenas pela simples ação de atualizar o prompt. É simples.
Você também pode fazer algo semelhante ao que está fazendo, tailmas definir
HISTFILE=${TGT_PTY}
fn+1para comparar! Obrigado!