Zakończenie bashu powoduje, że bash zaczyna się powoli


15

Rozpoczęcie bash na moim systemie Ubuntu zajmuje około 2 sekund. Jeśli usunę ładowanie / etc / bash_completition w .bashrc, rozpocznie się ono bezzwłocznie. Oczywiście nie chcę rezygnować z ukończenia i nie sądzę, aby ładowanie tego pliku było uzasadnionym powodem 2-sekundowego opóźnienia.

Wszelkie pomysły, w jaki sposób mogę dowiedzieć się, na czym polega problem lub jak mogę przyspieszyć.


to jest / bin / bash? - try / bin / dash może być nieco szybszy.
Sirex,

3
Właśnie dlatego odinstalowałem Bash-uzupełnianie
Vi.

Odpowiedzi:


8

Aktualizacja w 2013 r .: większość ukończenia bash została przepisana na automatyczne ładowanie tylko wtedy, gdy jest to potrzebne. Podstawowy skrypt jest teraz dużo ligher.


Skrypt ukończenia może czasem być ogromny w standardach skryptów powłoki. Na jednym serwerze mam dostęp, to prawie 1700 linii (57 KB) i to tylko podstawowy skrypt . W /etc/bash_completion.distnieją ~ 200 dodatkowe skrypty dla różnych innych poleceń ( openssl, mutt, mount...) na łączną kwotę 25537 linie lub 1,2 MB. Każdy skrypt podczas pobierania sprawdza, czy polecenie jest faktycznie dostępne, przed zdefiniowaniem procedur obsługi zakończenia; ~ 330 razy w tym przypadku, z których każdy obejmuje sprawdzenie $PATHpliku wykonywalnego o podanej nazwie. (Chociaż spodziewałbym /usr/binsię, że będę buforowany w pamięci ...)

Trzeba przyznać, że nawet załadowanie zajmuje tylko pół sekundy, a nie dwie pełne sekundy. Ale może to być przynajmniej część problemu. Uruchom du -hs /etc/bash_completion*lub wc -l /etc/bash_completion{,.d/*} | grep totaljeśli chcesz to sprawdzić.


Możesz spróbować ręcznie uzyskać skrypt w trybie „śledzenia”:

set -x
. /etc/bash_completion

Zobaczysz każdą linię w trakcie jej wykonywania. Jeśli jakieś polecenie zajmuje dużo czasu, powinieneś je zauważyć.

( set +xwyłącza tryb śledzenia).


Funkcja pełzania nawet w uproszczonym trybie tekstowym? Jest bardziej prawdopodobne niż myślisz.
Vi.

@Vi: Po zobaczeniu, jak Zsh kompiluje swoje skrypty startowe do kodu bajtowego ...
user1686,

1
Dziękuję Ci. To było naprawdę łatwe. Niestety, wszystkie polecenia nie różniły się znacząco. Wygląda więc na to, że to naprawdę ogromna ilość powoduje problem.
user75250,

12

Znalazłem nieco hackerskie rozwiązanie, które wydaje się działać dość dobrze.

Rozwiązanie

Na dole ~/.bashrcdodaj:

trap 'source / etc / bash_completion; pułapka USR1 'USR1
{spać 0,1; wbudowane zabijanie -USR1 $$; } i disown

Wyjaśnienie

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

Skonfiguruj moduł obsługi, który będzie uruchamiany, gdy powłoka odbierze sygnał SIGUSR1; program obsługi załaduje uzupełnienia, a zatem sam się dezaktywuje.

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

Asynchronicznie poczekaj chwilę, a następnie wyślij sygnał do bieżącej powłoki. disownjest potrzebny do stłumienia bashinformacji zwrotnych kontroli procesu. sleepjest potrzebne do pracy asynchronicznej.

Problemy

Z jakiegoś powodu pierwsze polecenie wydane dla tej powłoki nie zostanie zapisane w historii.


1
Wydaje się, że to nie przyspiesza uruchamiania - time bash -lc truezgłasza ~ 0,12 s z tym lub bez niego, nawet jeśli time source /etc/bash_completionraportuje wyższe liczby, takie jak 0,26 s. Czy udało się to skutecznie naprawić ?
l0b0

Nie wiem, czy time bash -lc truedziała tutaj poprawnie, ponieważ truekończy się wcześniej, ~0.1swięc nie pobiera niczego. W każdym razie time source /etc/bash_completionzgłasza ~ 0,17s tutaj i to jest czas, kiedy muszę czekać na PS1pojawienie się.
cyr

2
Pomysłowy! W wyjaśnieniu komendy pułapki tracą a USR1na końcu.
Fish Monitor

W przypadku SIGUSR procedura obsługi sygnału nie jest wywoływana, dopóki nie naciśniesz Enter w wierszu poleceń powłoki. W tym momencie następuje przerwa. Przełączyłem się na SIGQUIT i wydaje się, że działa dobrze.
Jon Nalley,

5

Powinieneś użyć najnowszej wersji (2.0) bash_completion. Jeśli używasz Debiana, jest w wheezy, ale nie ma zależności od żadnego innego pakietu wheezy, więc możesz zainstalować go w squeeze bez problemu.

Ostatnia wersja ładuje ukończenie dynamicznie w locie, więc podzielił dla mnie szybki czas ładowania co najmniej 10 razy.


1

Możesz użyć symbolu zastępczego podczas ładowania ukończeń; powinno wystarczyć oszukać oczy. Działa to oczywiście tylko wtedy, gdy potrzebny czas source /etc/bash_completionjest krótszy niż czas potrzebny na wpisanie i wydanie pierwszego polecenia powłoki, w przeciwnym razie również zostanie opóźnione.

Chodzi o to, aby powtórzyć fałszywkę PS1, zaopatrzyć się w uzupełnienia i wreszcie ulepszyć terminal.

Załóżmy, że PS1tak \u@\h:\w\$, mogą napisać coś takiego:

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

Gdzie:

  • 2J usuwa terminal;
  • H przesuń kursor do prawego górnego rogu.

Uwaga: Możesz sprawdzić, czy użytkownik jest rootem i użyć #zamiast $spójności:

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

Uwaga: Usunięcie \e[2Jpozwala uniknąć migotania, ale pozostawi niepotrzebne znaki, jeśli symbol zastępczy jest dłuższy niż rzeczywiste pytanie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.