Завершение Bash заставляет запуск Bash медленно

15

Запуск bash в моей системе Ubuntu занимает около 2 секунд. Если я удаляю загрузку / etc / bash_completition в .bashrc, она начинается без задержки. Конечно, я не хочу отказываться от завершения и не думаю, что загрузка этого файла является законной причиной задержки в 2 секунды.

Любые идеи, как я могу узнать, в чем проблема или как я могу ускорить процесс.

user75250
источник
это / bin / bash? - try / bin / dash может быть немного быстрее.
Sirex
3
Вот почему я деинсталлировал bash-дополнения
Vi.

Ответы:

8

Обновление в 2013 году: большая часть завершения bash была переписана для завершения автозагрузки только при необходимости. Базовый сценарий теперь намного легче.


Скрипт завершения иногда может быть огромным в стандартах сценария оболочки. На одном сервере, к которому у меня есть доступ, это почти 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отключает режим трассировки.)

user1686
источник
Функция ползет даже в упрощенном текстовом режиме? Это более вероятно, чем вы думаете.
Ви.
@Vi: После того, как zsh скомпилировал свои скрипты запуска в байт-код ...
user1686
1
Спасибо. Это было действительно легко. К сожалению, все команды не были различимы. Так что, похоже, это действительно огромное количество, которое вызывает проблему.
user75250
12

Я нашел немного хакерское решение, которое, кажется, работает достаточно.

Решение

Внизу ~/.bashrcдобавить:

trap 'source / etc / bash_completion; ловушка USR1 'USR1
{сон 0,1; встроенная команда kill -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. Это было эффективно исправлено ?
10
Я не знаю, time bash -lc trueработает ли здесь правильно, так как trueзаканчивается раньше, ~0.1sпоэтому ничего не получается. В любом случае, здесь time source /etc/bash_completionсообщается ~ 0,17 с, и это примерно то время, когда мне нужно ждать PS1появления.
cYrus
2
Гениальный! В объяснении, команды trap пропускают a USR1в конце.
Fish Monitor
В SIGUSR обработчик сигнала не вызывается до тех пор, пока я не нажму клавишу ввода в командной строке. В этот момент есть пауза, пока он работает. Я переключился на SIGQUIT, и, кажется, работает нормально.
Джон Налли,
5

Вы должны использовать последнюю версию (2.0) bash_completion. Если вы используете Debian, он находится в wheezy, но он не зависит от любого другого пакета wheezy, поэтому вы можете установить его без проблем.

Самая последняя версия загружает завершение динамически на лету, поэтому оно делило для меня время быстрой загрузки по крайней мере в 10 раз.

xryl669
источник
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 переместите курсор в верхний правый угол.

Примечание. Возможно, вы захотите проверить, является ли пользователь root, и использовать его #вместо $согласованности:

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

Примечание. При удалении можно \e[2Jизбежать мерцания, но в нем останутся ненужные символы, если заполнитель будет длиннее, чем фактическое приглашение.

Кир
источник