bashの完了により、bashの起動がゆっくりに


15

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

問題が何であるか、または物事をどのようにスピードアップできるかを知るためのアイデア。


これは/ bin / bashですか?-/ bin / dashを試してみると少し速くなるかもしれません。
Sirex

3
これが、bash-completion
Vi

回答:


8

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


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

確かに、でもということだけではない2つのフル秒、負荷に半秒かかります。しかし、それは少なくとも問題の一部かもしれません。実行するdu -hs /etc/bash_completion*wc -l /etc/bash_completion{,.d/*} | grep total、確認する場合。


「トレース」モードで、手動でスクリプトのソースを試すことができます。

set -x
. /etc/bash_completion

実行時に各行が表示されます。時間がかかる特定のコマンドがある場合は、それに注意する必要があります。

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


単純なテキストモードでも機能がクリープしますか?あなたが思っているよりも可能性が高いです。
Vi。

@Vi:zshが起動スクリプトをバイトコードにコンパイルするのを見て
...-user1686

1
ありがとうございました。それは本当に簡単でした。悲しいことに、すべてのコマンドが顕著に異なるわけではありません。そのため、実際に問題を引き起こしているのは膨大な量のようです。
user75250

12

私はかなりハック的な解決策を見つけましたが、それはかなり十分に機能しているようです。

解決

~/.bashrc追加の下部:

trap 'source / etc / bash_completion; トラップUSR1 'USR1
{スリープ0.1; builtin kill -USR1 $$; }&disown

説明

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

シェルがシグナルを受信したときに実行されるハンドラーをセットアップしますSIGUSR1。ハンドラーが完了をロードするため、ハンドラー自体が非アクティブになります。

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

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

問題点

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


1
これは、スタートアップを後押しするものではないようです-0.26sのような高い数値を報告しますがtime bash -lc true、これの有無にかかわらず〜0.12sをtime source /etc/bash_completion報告します。これは効果的に修正れましたか?
-l0b0

前に終了するためtime bash -lc true、ここで適切に動作するかどうかはわかりませんので、何もソースしません。とにかくここで報告されるのは〜0.17sで、それが表示されるのを待つ時間です。true~0.1stime source /etc/bash_completionPS1
cYrus

2
独創的!説明では、トラップコマンドUSR1は最後にa を逃します。
魚モニター14

SIGUSRを使用すると、シェルプロンプトでEnterキーを押すまで、シグナルハンドラーは呼び出されません。実行中はその時点で一時停止します。SIGQUITに切り替えましたが、うまくいくようです。
ジョンナリー

5

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

最新のバージョンは、オンザフライで動的に完了をロードするため、プロンプトのロード時間を少なくとも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 カーソルを右上隅に移動します。

注:ユーザーがrootであるかどうかを確認し、一貫性の#代わりに使用することもできます$

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

注:削除すると\e[2J、ちらつきが回避されますが、プレースホルダーが実際のプロンプトよりも長い場合は、ジャンク文字が残ります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.