Durch die Bash-Vervollständigung wird die Bash langsam gestartet

15

Das Starten einer Bash auf meinem Ubuntu-System dauert ca. 2 Sekunden. Wenn ich das Laden von / etc / bash_completition in .bashrc entferne, wird es unverzüglich gestartet. Natürlich möchte ich die Vervollständigung nicht aufgeben und ich denke nicht, dass das Laden dieser Datei ein legitimer Grund für eine Verzögerung von 2 Sekunden ist.

Irgendwelche Ideen, wie ich herausfinden kann, was das Problem ist oder wie ich Dinge beschleunigen kann.

user75250
quelle
ist das / bin / bash? - try / bin / dash könnte etwas schneller sein.
Sirex
3
Deshalb habe ich bash-completion
Vi

Antworten:

8

Update im Jahr 2013: Der Großteil der Bash-Vervollständigung wurde nur bei Bedarf in Autoload-Vervollständigungen umgeschrieben. Das Kernskript ist jetzt viel heller.


Das Abschlussskript kann in Shell-Skriptstandards manchmal sehr umfangreich sein . Auf einem Server, auf den ich Zugriff habe, sind es fast 1700 Zeilen (57 KB) und das ist nur das Kernskript . In /etc/bash_completion.dgibt es ~ 200 zusätzlichen Skripte für verschiedene andere Befehle ( openssl, mutt, mount...) in Höhe von insgesamt 25.537 Zeilen oder 1,2 MB. Jedes Skript prüft, wenn es bereitgestellt wird, ob ein Befehl tatsächlich verfügbar ist, bevor Abschlusshandler definiert werden. In diesem Fall ~ 330 Mal, wobei jeweils $PATHnach einer ausführbaren Datei mit einem bestimmten Namen gesucht wird. (Obwohl ich erwarten würde /usr/bin, im Speicher zwischengespeichert zu werden ...)

Zugegeben, selbst das dauert nur eine halbe Sekunde, nicht zwei volle Sekunden. Aber es könnte zumindest ein Teil des Problems sein. Führen Sie du -hs /etc/bash_completion*oder wc -l /etc/bash_completion{,.d/*} | grep totalwenn Sie überprüfen möchten.


Sie können versuchen, das Skript im "Trace" -Modus manuell aufzurufen:

set -x
. /etc/bash_completion

Sie werden jede Zeile sehen, wie sie ausgeführt wird. Wenn es einen bestimmten Befehl gibt, der lange dauert, sollten Sie ihn bemerken.

( set +xDeaktiviert den Trace-Modus.)

Grawity
quelle
Feature-Creep auch im simplen Textmodus? Es ist wahrscheinlicher als Sie denken.
Vi.
@Vi: Nachdem zsh gesehen hat, wie es seine
Startskripte
1
Vielen Dank. Das war wirklich einfach. Leider waren nicht alle Befehle auffällig anders. Es sieht also so aus, als ob es tatsächlich die enorme Menge ist, die das Problem verursacht.
user75250
12

Ich habe eine etwas hackige Lösung gefunden, die ziemlich gut zu funktionieren scheint.

Lösung

Am Ende von ~/.bashrcadd:

trap 'source / etc / bash_completion; Falle USR1 'USR1
{Schlaf 0,1; eingebauter kill -USR1 $$; } & ablehnen

Erläuterung

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

Richten Sie einen Handler ein, der ausgeführt werden soll, wenn die Shell das Signal empfängt SIGUSR1. Der Handler lädt die Vervollständigungen und deaktiviert sich daher von selbst.

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

Warten Sie ein wenig asynchron und senden Sie dann das Signal an die aktuelle Shell. disownwird benötigt, um bashRückkopplungen der Prozesssteuerung zu unterdrücken . sleepwird benötigt, um asynchron zu arbeiten.

Probleme

Aus irgendeinem Grund wird der erste Befehl, der an diese Shell ausgegeben wird, nicht im Verlauf aufgezeichnet.

cYrus
quelle
1
Dies scheint nicht einen Startschub zu geben - time bash -lc trueBerichte ~ 0.12s mit oder ohne diese, obwohl time source /etc/bash_completionBerichte höhere Zahlen wie 0.26s. Wurde dies effektiv behoben ?
l0b0
Ich weiß nicht, ob es time bash -lc truehier richtig funktioniert, da es schon truefertig ist und ~0.1ses keine Quelle gibt. Sowieso time source /etc/bash_completionmeldet sich hier ~ 0.17s und das ist ungefähr die Zeit, die ich auf das PS1Erscheinen warten muss .
CYRUS
2
Genial! In der Erklärung fehlt den Trap-Befehlen ein USR1am Ende.
Fish Monitor
Mit SIGUSR wird der Signalhandler erst aufgerufen, nachdem ich an der Shell-Eingabeaufforderung die Eingabetaste gedrückt habe. An diesem Punkt tritt eine Pause auf, während das Programm ausgeführt wird. Ich habe zu SIGQUIT gewechselt und es scheint gut zu funktionieren.
Jon Nalley
5

Sie sollten die neueste Version (2.0) von bash_completion verwenden. Wenn Sie Debian verwenden, ist es in Wheezy, aber es hat keine Abhängigkeiten von irgendeinem anderen Wheezy-Paket, so dass Sie es problemlos in einem Squeeze installieren können.

Die neueste Version lädt die Fertigstellung dynamisch im laufenden Betrieb, sodass die Ladezeit für mich durch mindestens das 10-fache geteilt wurde.

xryl669
quelle
1

Sie können einen Platzhalter verwenden, während die Vervollständigungen geladen werden. es sollte genug sein, um deine Augen zu betrügen. Dies funktioniert natürlich nur, wenn die Zeit, die von benötigt source /etc/bash_completionwird, kürzer ist als die Zeit, die Sie zum Eingeben und Ausgeben des ersten Shell-Befehls benötigen. Andernfalls wird dies ebenfalls verzögert.

Die Idee ist, eine Fälschung PS1nachzuahmen, die Fertigstellungen zu beschaffen und schließlich das Terminal zu löschen.

Nehmen wir an , Ihr PS1heißt \u@\h:\w\$, sie könnten Sie schreiben so etwas wie:

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

Wo:

  • 2J löscht das Terminal;
  • H Bewegen Sie den Cursor in die obere rechte Ecke.

Hinweis: Möglicherweise möchten Sie überprüfen, ob der Benutzer root ist, und #stattdessen aus Gründen der $Konsistenz Folgendes verwenden:

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

Hinweis:\e[2J Wenn Sie diese Option entfernen, wird das Flackern vermieden, es verbleiben jedoch Junk-Zeichen, wenn der Platzhalter länger als die eigentliche Eingabeaufforderung ist.

cYrus
quelle