La finalización de bash hace que bash comience lentamente

15

Iniciar un bash en mi sistema ubuntu tarda unos 2 segundos. Si elimino la carga / etc / bash_completition en .bashrc, se inicia sin demora. Por supuesto, no quiero renunciar a la finalización y no creo que cargar ese archivo sea una razón legítima para un retraso de 2 segundos.

Alguna idea de cómo puedo averiguar cuál es el problema o cómo puedo acelerar las cosas.

usuario75250
fuente
es esto / bin / bash? - try / bin / dash podría ser un poco más rápido.
Sirex
3
Es por eso que desinstalé bash-complete
Vi.

Respuestas:

8

Actualización en 2013: la mayor parte de la finalización de bash se reescribió a finalizaciones de carga automática solo cuando fue necesario. El guión central es mucho más ligado ahora.


El script de finalización a veces puede ser enorme en los estándares de script de shell. En uno de los servidores a los que tengo acceso, son casi 1700 líneas (57 KB) y ese es solo el script central . En /etc/bash_completion.dhay ~ 200 secuencias de comandos adicionales para varios otros comandos ( openssl, mutt, mount...) por un total de 25537 líneas o 1,2 MB. Cada secuencia de comandos, cuando se obtiene, verifica si un comando está realmente disponible antes de definir los controladores de finalización; ~ 330 veces en este caso, cada una de las cuales implica buscar $PATHun archivo ejecutable con un nombre de pila. (Aunque esperaría /usr/binestar en la memoria caché ...)

Es cierto que incluso eso solo tarda medio segundo en cargarse, no dos segundos completos. Pero podría ser al menos parte del problema. Ejecutar du -hs /etc/bash_completion*o wc -l /etc/bash_completion{,.d/*} | grep totalsi quieres comprobarlo.


Puede intentar obtener manualmente el script, en modo "rastreo":

set -x
. /etc/bash_completion

Verá cada línea a medida que se ejecuta. Si hay un comando en particular que lleva mucho tiempo, debería notarlo.

( set +xdeshabilita el modo de seguimiento).

usuario1686
fuente
Característica de arrastre incluso en modo de texto simplista? Es más probable de lo que piensas.
Vi.
@ Vi: Después de ver que zsh compila sus scripts de inicio para bytecode ...
user1686
1
Gracias. Eso fue realmente fácil. Lamentablemente, todos los comandos no eran notablemente diferentes. Por lo tanto, parece que es la gran cantidad lo que está causando el problema.
user75250
12

Encontré una solución un poco hack que parece funcionar bastante bien.

Solución

En la parte inferior de ~/.bashrcagregar:

trap 'source / etc / bash_completion; trampa USR1 'USR1
{dormir 0.1; matanza incorporada -USR1 $$; } y rechazar

Explicación

trap 'source /etc/bash_completion ; trap USR1' USR1

Configure un controlador para que se ejecute cuando el shell reciba la señal SIGUSR1; el controlador cargará las finalizaciones y, por lo tanto, se desactivará solo.

{ sleep 0.1 ; builtin kill -USR1 $$ ; } & disown

Asincrónicamente espere un poco y luego envíe la señal al shell actual. disownes necesario para suprimir la bashretroalimentación del control del proceso. sleepes necesario para trabajar de forma asincrónica

Problemas

Por alguna razón, el primer comando emitido a este shell no se registrará en el historial.

Ciro
fuente
1
Esto no parece dar un impulso de inicio: time bash -lc trueinforma ~ 0.12s con o sin esto, a pesar de que time source /etc/bash_completioninforma números más altos como 0.26s. ¿Se ha solucionado esto efectivamente ?
l0b0
No sé si time bash -lc truefunciona correctamente aquí, ya que truetermina antes, ~0.1spor lo que no genera nada. De todos modos time source /etc/bash_completioninforma ~ 0.17s aquí y ese es el tiempo que necesito esperar para que PS1aparezca.
cYrus
2
¡Ingenioso! En explicación, los comandos de trampa pierden USR1a al final.
Fish Monitor
Con SIGUSR, el controlador de señal no se invoca hasta después de presionar enter en el indicador de comandos de la shell. Hay una pausa en ese punto mientras se ejecuta. Me cambié a SIGQUIT y parece funcionar bien.
Jon Nalley
5

Debe usar la última versión (2.0) de bash_completion. Si está utilizando Debian, está en wheezy, pero no depende de ningún otro paquete de wheezy, por lo que puede instalarlo sin problemas.

La última versión carga la finalización dinámicamente sobre la marcha, por lo que dividió el tiempo de carga rápido para mí por al menos 10 veces.

xryl669
fuente
1

Puede usar un marcador de posición mientras se cargan las finalizaciones; debería ser suficiente para engañar a tus ojos. Obviamente, esto solo funciona si el tiempo que necesita source /etc/bash_completiones menor que el tiempo que necesita para escribir y emitir el primer comando de shell; de lo contrario, también se retrasará.

La idea es hacer eco de una falsificación PS1, obtener las terminaciones y finalmente eliminar la terminal.

Supongamos que tu PS1es \u@\h:\w\$, ellos podrían escribir algo como:

echo -ne "$USER@$HOSTNAME:${PWD/$HOME/\~}\$ "
source /etc/bash_completion
echo -ne '\e[2J\e[H'

Dónde:

  • 2J borra el terminal;
  • H mueve el cursor a la esquina superior derecha.

Nota: es posible que desee comprobar si el usuario es root y usar en #lugar de $mantener la coherencia:

echo -ne "...$([ $UID = 0 ] && echo '#' || echo '$') "

Nota: la eliminación \e[2Jevita el parpadeo, pero dejará caracteres basura si el marcador de posición es más largo que el indicador real.

Ciro
fuente