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.