Завершення Bash змушує баш починати повільно


15

Запуск базу в моїй системі ubuntu займає близько 2 секунд. Якщо я видаляю завантажувальний / etc / bash_completition у .bashrc, він запускається без зволікань. Звичайно, я не хочу відмовлятися від завершення, і не думаю, що завантаження цього файлу є законною причиною затримки на 2 секунди.

Будь-які ідеї, як я можу з’ясувати, в чому проблема, або як я можу пришвидшити справи.


це / bin / bash? - спробуйте / bin / dash може бути трохи швидшим.
Сірекс

3
Ось чому я деінсталював bash-завершення
Vi.

Відповіді:


8

Оновлення в 2013 році. Більшість баш-завершень було переписано для автоматичного завантаження завершень лише за потреби. Основний сценарій зараз набагато вищий.


Сценарій завершення іноді може бути величезним у стандартах сценарію оболонки. На одному сервері, до якого я маю доступ, це майже 1700 рядків (57 Кб), і це лише основний сценарій . В /etc/bash_completion.dє ~ 200 додаткові скрипти для різних інших команд ( openssl, mutt, mount...) на загальну суму 25537 ліній або 1,2 МБ. Кожен скрипт під час отримання джерела перевіряє, чи є команда фактично доступною, перш ніж визначати обробники завершення; ~ 330 разів у цьому випадку, кожен з яких включає перевірку $PATHна виконуваний файл із заданим іменем. (Хоча я б очікував, /usr/binщо це запам'ятовується в пам'яті ...)

Справді, навіть для завантаження цього потрібно лише півсекунди, а не дві повні секунди. Але це може бути хоча б частиною проблеми. Виконати du -hs /etc/bash_completion*або wc -l /etc/bash_completion{,.d/*} | grep totalякщо ви хочете перевірити.


Ви можете спробувати скрипт вручну в режимі "слід":

set -x
. /etc/bash_completion

Ви побачите кожен рядок, як він виконується. Якщо є певна команда, яка потребує тривалого часу, ви повинні її помітити.

( set +xвимикає режим відстеження.)


Функція повзання навіть у спрощеному текстовому режимі? Це швидше, ніж ви думаєте.
Ві.

@Vi: Після побачення zsh компілює свої сценарії запуску для байт-коду ...
user1686

1
Дякую. Thats було дійсно легко. На жаль, всі команди не помітно відрізнялися. Таким чином, це виглядає як його справді величезна кількість, що викликає проблему.
користувач75250

12

Я знайшов дещо хакітське рішення, яке, здається, працює досить досить.

Рішення

Внизу ~/.bashrcдодайте:

trap 'source / etc / bash_completion; пастка USR1 'USR1
{сон 0,1; вбудований вбити -USR1 $$; } і відмовиться

Пояснення

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

Налаштуйте оброблювач, який запускається, коли оболонка отримує сигнал SIGUSR1; обробник завантажить комплектацію і, отже, він відключиться.

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

Асинхронно зачекайте трохи, а потім надішліть сигнал поточній оболонці. disownпотрібен для придушення bashзворотного зв'язку з процесом. sleepпотрібен для роботи асинхронно.

Проблеми

Чомусь перша команда, видана цій оболонці, не буде записана в історію.


1
Це, мабуть, не дає імпульсу для запуску - time bash -lc trueзвіти ~ 0,12 з цим або без нього, навіть якщо time source /etc/bash_completionповідомляють про більш високі числа, як-от 0,26. Це ефективно було виправлено ?
l0b0

Я не знаю, чи time bash -lc trueпрацює тут правильно, оскільки trueзакінчується раніше, ~0.1sтому нічого не дає джерела. У будь-якому випадку, тут time source /etc/bash_completionповідомляється ~ 0,17, і це приблизно час, який мені потрібно дочекатися PS1появи.
cYrus

2
Геніальний! Пояснюючи, команди пастки пропускають a USR1в кінці.
Монітор риб

За допомогою SIGUSR, обробник сигналу не викликається, поки я не натискаю клавішу Enter у запиті оболонки. У цій точці є пауза, коли вона працює. Я перейшов на SIGQUIT і, здається, працює добре.
Джон Наллей

5

Ви повинні використовувати найновішу версію (2.0) bash_completion. Якщо ви використовуєте Debian, він знаходиться в хриповому вигляді, але він не залежить від будь-якого іншого пакету хрипких, так що ви можете встановити його на стиснення без проблем.

Найновіша версія динамічно завантажує завершення, тому вона розділила час для швидкого завантаження для мене щонайменше на 10 разів.


1

Ви можете використовувати заповнювач місця, поки завершення завантажуються; його повинно вистачити, щоб обманути очі. Це, очевидно, працює лише в тому випадку, якщо потрібний час source /etc/bash_completionменший за час, необхідний вам для набору та видачі першої команди оболонки, інакше вона також буде відкладена.

Ідея полягає у тому, щоб повторити підробку PS1, розібрати завершення та остаточно стерти термінал.

Припустимо , що ваш PS1є \u@\h:\w\$, вони вимушені звертатися могли б написати що - щось на кшталт:

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

Де:

  • 2J стирає термінал;
  • H перемістіть курсор у верхній правий кут.

Примітка. Ви можете перевірити, чи користувач користується рутом і використовує #замість $для послідовності:

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

Примітка: Видалення \e[2Jдозволяє уникнути мерехтіння, але воно залишить непотрібні символи, якщо заповнювач заповнення довший за фактичний запит.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.