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
SIGUSR1controlador y hacer que este shell ignore la señal. - Envía la señal a todos los
bashen 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.