Sé que esta pregunta no es oscura, ya que se hace aquí para seguir actualizándose (y duplicada aquí).
Lo que estoy tratando de lograr es un poco diferente. No me gusta la idea de que mi aviso reescriba un archivo cada ls
Escribo (history -a; history -c; history -r
).
Me gustaría actualizar el archivo al salir. Eso es fácil (en realidad, predeterminado), pero debe agregar en lugar de volver a escribir:
shopt -s histappend
Ahora, cuando se cierra un terminal, me gustaría que todos los demás que quedan abiertos estén al tanto de la actualización.
Prefiero hacer esto sin verificar a través de $PS1
en cada command
que escribo. Creo que sería mejor capturar algún tipo de señal. ¿Cómo lo harías tú? Si no es posible, tal vez un simple cronjob
?
¿Cómo podemos resolver este rompecabezas?
Respuesta aceptada:
¿Señales creativas y envolventes, dices? Bien:
trap on_exit EXIT
trap on_usr1 USR1
on_exit() {
history -a
trap '' USR1
killall -u "$USER" -USR1 bash
}
on_usr1() {
history -n
}
Tira eso en .bashrc
y ve. Esto usa señales para decirle a cada bash
proceso para verificar si hay nuevas entradas en el historial cuando sale otra. Esto es bastante horrible, pero realmente funciona.
¿Cómo funciona?
trap
establece un controlador de señal para una señal del sistema o uno de los eventos internos de Bash. La EXIT
evento es cualquier terminación controlada del shell, mientras que USR1
es SIGUSR1
, una señal sin sentido de que nos estamos apropiando.
Cada vez que sale el shell, nosotros:
- Anexar todo el historial al archivo de forma explícita.
- Deshabilitar el
SIGUSR1
controlador y hacer que este shell ignore la señal. - Envía la señal a todos los
bash
en ejecución procesos del mismo usuario.
Cuando un SIGUSR1
llega, nosotros:
- Cargue todas las entradas nuevas del archivo de historial en la lista de historial en memoria del shell.
Debido a la forma en que Bash maneja las señales, en realidad no obtendrá los nuevos datos del historial hasta que presione Enter la próxima vez, así que esto no funciona mejor en ese frente que poner history -n
en PROMPT_COMMAND
. Sin embargo, ahorra leer el archivo constantemente cuando no ha pasado nada, y no se escribe nada hasta que se cierra el shell.
Sin embargo, todavía hay un par de problemas aquí. La primera es que la respuesta predeterminada a SIGUSR1
es terminar el caparazón. Cualquier otro bash
los procesos (ejecutando scripts de shell, por ejemplo) serán eliminados. .bashrc
no se carga con shells no interactivos. En su lugar, un archivo nombrado por BASH_ENV
está cargado:puede configurar esa variable en su entorno globalmente para que apunte a un archivo con:
trap '' USR1
en él para ignorar la señal en ellos (lo que resuelve el problema).
Relacionado:¿Comando de terminal para saber si un servidor es virtual o físico?Finalmente, aunque esto hace lo que pediste, el orden que recibirás será un poco inusual. En particular, los fragmentos de la historia se repetirán en diferentes órdenes a medida que se cargan y guardan por separado. Eso es esencialmente inherente a lo que está solicitando, pero tenga en cuenta que el historial de flecha hacia arriba se vuelve mucho menos útil en este punto. Sin embargo, las sustituciones de historial y similares se compartirán y funcionarán bien.