web-dev-qa-db-ja.com

Bashの完了により、bashの開始が遅くなります

私のubuntuシステムでbashを開始するには約2秒かかります。 .bashrcの/ etc/bash_completitionの読み込みを削除すると、遅滞なく起動します。もちろん、私は完了をあきらめたくありませんし、そのファイルをロードすることが2秒の遅延の正当な理由であるとは思いません。

問題が何であるかを知る方法や、物事をスピードアップする方法についてのアイデア。

15
user75250

2013年の更新:bash-completionのほとんどは、必要な場合にのみ完了を自動ロードするように書き直されました。コアスクリプトは今でははるかに洗練されています。


完了スクリプトは、シェルスクリプト標準ではhugeの場合があります。私がアクセスできる1つのサーバーでは、ほぼ1700行(57 KB)であり、それはコアスクリプトです。 /etc/bash_completion.dには、他のさまざまなコマンド(opensslmuttmount...)用に合計25537行または1.2MBの追加スクリプトが200個あります。各スクリプトは、ソースが提供されると、完了ハンドラーを定義する前に、コマンドが実際に使用可能かどうかを確認します。この場合、約330回、それぞれが$PATHで指定された名前の実行可能ファイルをチェックする必要があります。 (/usr/binがメモリにキャッシュされることを期待しますが...)

確かに、thatでさえ、ロードに0.5秒しかかからず、2秒もかかりません。しかし、それは少なくとも問題の一部である可能性があります。確認する場合は、du -hs /etc/bash_completion*またはwc -l /etc/bash_completion{,.d/*} | grep totalを実行します。


「トレース」モードで、スクリプトを手動で調達してみることができます。

set -x
. /etc/bash_completion

実行されると、各行が表示されます。時間がかかる特定のコマンドがある場合は、それに気付くはずです。

set +xはトレースモードを無効にします。)

8
user1686

私はかなりうまくいくように見える少しハックな解決策を見つけました。

解決

~/.bashrcの下部に次を追加します:

 trap'source/etc/bash_completion;トラップUSR1'USR1 
 {sleep 0.1;組み込みのkill-USR1 $$; }&勘当

説明

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

シェルがシグナルSIGUSR1を受信したときに実行されるハンドラーを設定します。ハンドラーは補完をロードするため、それ自体を非アクティブ化します。

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

非同期的に少し待ってから、現在のシェルに信号を送信します。 disownは、bashプロセス制御フィードバックを抑制するために必要です。非同期で動作するには、sleepが必要です。

問題

何らかの理由で、このシェルに発行された最初のコマンドは履歴に記録されません。

12
cYrus

Bash_completionの最新バージョン(2.0)を使用する必要があります。 Debianを使用している場合、それはwheezyにありますが、他のwheezyパッケージとの依存関係がないため、問題なくスクイーズにインストールできます。

最新バージョンは完了をその場で動的にロードするため、プロンプトのロード時間を少なくとも10倍に分割しました。

5
xryl669

補完の読み込み中にプレースホルダーを使用できます。それはあなたの目をだますのに十分なはずです。これは明らかに、source /etc/bash_completionに必要な時間が、最初のShellコマンドを入力して発行するのに必要な時間よりも短い場合にのみ機能します。そうでない場合も、遅延します。

アイデアは、偽の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を削除すると、ちらつきは回避されますが、プレースホルダーが実際のプロンプトよりも長い場合は、ジャンク文字が残ります。

1
cYrus