Cómo obtener el historial compartido compartido entre diferentes pestañas

19

Utilicé la respuesta en /unix//a/1292/41729 para habilitar el historial compartido en tiempo real entre terminales de bash separadas. Como se explica en la respuesta anterior, esto se logra agregando:

# avoid duplicates..
export HISTCONTROL=ignoredups:erasedups  
# append history entries..
shopt -s histappend

# After each command, save and reload history
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

Esto funciona bien si los shells de bash están separados (por ejemplo, abriendo diferentes terminales de bash usando CTRL+ALT+T. Sin embargo, no funciona si uso tabs(desde un terminal abierto `CTRL + SHIFT + T) en lugar de nuevas ventanas. ¿Por qué esta diferencia de comportamiento? ¿Cómo? ¿Puedo compartir el historial de bash también entre varias pestañas?

ACTUALIZACIÓN: Noté un comportamiento inusual: si escribo CTRL+C, el último comando escrito en cualquiera de los otros terminales (tanto una pestaña como no) se muestra correctamente. Es como si CTRL + C fuerza un vaciado del historial para que luego se comparta correctamente.

Como ejemplo, las salidas (T1 denota el terminal 1 y el terminal 2 de T2):

T1:
ls -lah <enter>
# the list of files and directory is shown

T2:
cd Documents <enter>

T1:
<up> (i.e. I press the up arrow)
ls -lah #i.e the last command in terminal 1 is shown rather than the last of terminal 2
^C (i.e. I press CTRL+C)
<up>
cd Documents #the last command issued in terminal 2 is correctly displayed

Espero que esto pueda ofrecer alguna pista!

lucacerona
fuente
¿Agregaste eso a tu ~.bashrcarchivo? En una nota al margen, exportar esas variables no tiene sentido; solo desperdicia espacio ambiental.
geirha
@geirha sí, lo he agregado a mi archivo .bashrc. Gracias por el comentario sobre la exportación.
lucacerone

Respuestas:

2

Parece que está intentando acceder al historial del otro terminal antes de que se realice la sincronización. PROMPT_COMMANDse ejecuta justo antes de que se imprima una nueva solicitud, es decir, después de ejecutar un comando y antes de escribir el siguiente comando. Por lo tanto, no sucederá de inmediato en T1; debe hacer que se muestre una nueva solicitud.

Para probar esto, pruebe esta variante en sus pasos (agregué un extra <enter>en T1):

T1:
ls -lah <enter>
# the list of files and directory is shown

T2:
cd Documents <enter>

T1:
<enter>
<up> (i.e. I press the up arrow)

Con esta presión adicional de enter, obtienes un nuevo mensaje, que se ejecuta PROMPT_COMMANDy sincroniza tu historial, por lo que esperaría que esta flecha hacia arriba recupere el en cdlugar del ls, como quisieras. Desafortunadamente, no creo que haya una manera de hacer que la sincronización ocurra instantáneamente en todos los terminales sin ejecutar ningún comando como parece querer; efectivamente, esto requeriría que todas sus sesiones de inicio de sesión estén sincronizando sus listas de historial continuamente todo el tiempo, lo que sería una gran pérdida de rendimiento de CPU y disco.

Pablo
fuente
tienes razón, presionar enter se sincroniza después. Incluso si hay un desperdicio de memoria o CPU, ¿cómo podría forzar la sincronización? (Si es demasiado, siempre puedo desactivarla, pero me gustaría intentarlo)
lucacerone
1

Hice la misma pregunta y aquí está la respuesta que se me ocurrió ...

HISTSIZE=9000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

history() {
  _bash_history_sync
  builtin history "$@"
}

_bash_history_sync() {
  builtin history -a         #1
  HISTFILESIZE=$HISTSIZE     #2
  builtin history -c         #3
  builtin history -r         #4
}

PROMPT_COMMAND=_bash_history_sync
Scott Goodgame
fuente
Fuente: unix.stackexchange.com/a/48116/37944
Radu Rădeanu
dos aclaraciones antes de intentarlo: ¿debería eliminar la otra historia - opciones entonces? esto va en .bashrc ¿verdad?
lucacerone
desafortunadamente no funciona ...
lucacerone
Cada vez que HISTFILESIZEse cambia, intenta automáticamente truncar el archivo de historial existente. El cambio HISTSIZEtiene un efecto similar en el historial actual. Como referencia, vea el comentario en variables.cbash src justo antes sv_histsize.
Brian Vandenberg
1

agrega esas líneas a tu .bashrcarchivo

# avoid duplicates..
export HISTCONTROL=ignoredups:erasedups  
# append history entries..
shopt -s histappend

trap 'history -r' USR1 
export PROMPT_COMMAND="history -a ; history -c; ps a | awk '/ bash$/ {system (\"kill -USR1 \" \$1)}'; $PROMPT_COMMAND"

Nota:

Inicialmente, hice mi compartimento de prueba enviando la señal USR1 a bash con killall, luego pensé en usar un nombre de shell único, una copia de bash llamada testhell, para evitar matar mis propios shells que podrían ejecutarse (procesos cron por ejemplo) pero extrañamente eso no era trabajando.

El killall no fue lo suficientemente selectivo, lo reemplacé con un script que mata solo los procesos bash ajustados a un tty ( ps ainforma solo procesos vinculados a un tty)

No olvide reiniciar su sesión para tener un PROMPT_COMMAND nuevo, cuando estaba probando vi muchas de mis pruebas anteriores apiladas dentro de PROMPT_COMMAND.

Emmanuel
fuente
No necesita el nuevo usuario y el otro shell, solo puede decirle killallque envíe la señal solo a los procesos del mismo usuario con un -uargumento adicional , e.g. -u $ (whoami) `.
Philipp Wendler
Creo que la sintaxis de csh es incorrecta ... @PhilippWendler, ¿podría explicar un poco más?
lucacerone
La pregunta es sobre bash, así que usé la sintaxis bash. No se csh. Para bash, killall -q -USR1 -u $(whoami) bashenvía la señal USR1 a todos los procesos de bash del usuario actual.
Philipp Wendler
@Philipp ty btw No probé la solución de shell dedicada, era para arreglar un caso en el que se ejecutaría el script cron bash.
Emmanuel
@LucaCerone que reescribí parece funcionar
Emmanuel
0

Tuve el mismo comportamiento extraño en Yakuake cuando intenté crear un indicador de bash elaborado que mostrara el número de otros inicios de sesión. El número no aumentó para las pestañas. Mi solución era decirle a Yakuake que se ejecutara bashnuevamente en cada pestaña nueva, esencialmente comenzando bash en bash. Comenzó a funcionar sin problemas. Puede ser que también te ayude. Mi suposición ciega es que la GUI para la consola carga las configuraciones de bash y luego las alimenta a las instancias de bash. Puede ser para poder jugar con ellos.

Barafu Albino
fuente
He intentado cargar bash en bash, pero sin ningún éxito :(
lucacerone