起動時にbashによって実行されているスクリプトを調べる


15

bashターミナルを起動した後、PATH変数に重複したエントリが含まれていることに気付きました。私の端末が起動ログインシェルは、そう~/.bash_profile、調達が続いている~/.profile~/.bashrc~/.profile重複するパスエントリを作成するのは、その中だけです。

教訓的であるために、これは、ソースされるべきであるファイルがソースされるべき順序です:

Sourced /etc/profile
Sourced /etc/bash.bashrc
Sourced .bash_profile
Sourced .profile
Sourced .bashrc

誰かがこれを「PATH変数に重複が含まれている」とマークする前に、読み続けてください。

最初は~/.profile、これは2回ソースされていることと関係があると考えたため、ソースされるたびにログファイルにファイルを書き込むようにしましたが、驚くべきことに、1つのエントリのみがログに記録されました。さらに驚くべきことは、にあったエントリをコメントアウト~/.profileすると、PATH変数にまだエントリが表示されるという事実です。これにより、3つの結論に至りましたが、そのうちの1つはすぐに除外されました。

  1. bashは有効なbashコメントを無視し、引き続きコメント付きコードを実行します
  2. ~/.profile出力を出力するコード(たとえばログファイル)を読み取り、無視するスクリプトがあります
  3. 別の~/.profile場所から調達されている私の別のコピーがあります

最初の1つは、いくつかの迅速なテストのため、そうではないとすぐに結論付けました。2番目と3番目のオプションは、助けが必要な場所です。

端末の起動時に実行されるスクリプトのログを収集するにはどうすればよいですか?echobashがソースであるかどうかを確認するためにチェックしたファイルで使用しましたが、端末で入力を開始する準備ができた時点まで実行を追跡する決定的なメソッドを見つける必要があります。

上記が不可能な場合は、実行中のスクリプトを確認するために他の場所を探すことができます


今後の参考資料

これは、パスに追加するために現在使用しているスクリプトです。

function add_to_path() {
    for path in ${2//:/ }; do
        if ! [[ "${!1}" =~ "${path%/}" ]]; then # ignore last /
            new_path="$path:${!1#:}"
            export "$1"="${new_path%:}" # remove trailing :
        fi
    done
}

私はこれを次のように使用します:

add_to_path 'PATH' "/some/path/bin"

スクリプトは、変数の前にパスが変数に既に存在するかどうかを確認します。

zshユーザーの場合、この同等のものを使用できます。

function add_to_path() {
    for p in ${(s.:.)2}; do
        if [[ ! "${(P)1}" =~ "${p%/}" ]]; then
            new_path="$p:${(P)1#:}"
            export "$1"="${new_path%:}"
        fi
    done
}

2018年8月28日編集

このスクリプトでできることは、パスを修正することです。だから私の.bashrcファイルの最初に、私はこのようなことをします:

_temp_path="$PATH"
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin'
add_to_path 'PATH' "$_temp_path"
unset _temp_path

何からPATH始めるべきかはあなた次第です。PATH最初に調べて決定します。


bashはのみから読み込む~/.profile 場合~/.bash_profileは存在しません ...
jasonwryan

@jasonwryan、Iソース~/.profile~/.bashrcから~/.bash_profile
smac89

回答:


30

システムが持っている場合strace、シェルによって開かれたファイルをリストできます。たとえば、

echo exit | strace bash -li |& grep '^open'

-liログインシェルインタラクティブを意味します。-iインタラクティブな非ログインシェルにのみ使用します。)

これにより、シェルが開いた、または開こうとしたファイルのリストが表示されます。私のシステムでは、次のとおりです。

  1. /etc/profile
  2. /etc/profile.d/*(のさまざまなスクリプト/etc/profile.d/
  3. /home/<username>/.bash_profile (これは失敗し、そのようなファイルはありません)
  4. /home/<username>/.bash_login (これは失敗し、そのようなファイルはありません)
  5. /home/<username>/.profile
  6. /home/<username>/.bashrc
  7. /home/<username>/.bash_history (コマンドラインの履歴。これはスクリプトではありません)
  8. /usr/share/bash-completion/bash_completion
  9. /etc/bash_completion.d/* (オートコンプリート機能を提供するさまざまなスクリプト)
  10. /etc/inputrc (キーバインディングを定義します;これはスクリプトではありません)

man strace詳細については使用してください。


ご意見をお寄せいただきありがとうございますが、私のbashには深刻な問題があると思います。echo $0ターミナルで実行-bashすると予想よりも与えるbash。これに関する他の提案はありますか?
smac89

3
@ smac89:ログインシェルの場合は正常です。Bashは、の最初の文字が$0ダッシュの-場合、またはオプションを指定して呼び出された場合、ログインシェルとして動作します-l
AlexP

OKそれは少し安心です。指定したコマンドを実行しましたが、出力は非常に複雑に見えますが、表示されているすべてのファイルに重複したエントリが含まれていません。これは、アカウントに最初にログインしたときに重複したエントリが発生する、つまり、最初に何かがそのファイルのエントリをソースし、ターミナルを開いたときに再び行われると考えるようになりました。実際、それはそれだと思う。アカウントにログインすると、エントリが取得され、ターミナルを開くとプロセスが繰り返されます。その音は可能ですか?
smac89

なぜあなたは置くことによって、昔ながらの方法をデバッグしていないecho PATH=\""$PATH"\"始まりと終わりの時.profile.bashrc?そして、誰もがやっていることを実行してPATHを完全に設定するか、ディレクトリを追加する場合はガードしてみecho ":$PATH:" | grep -q ":/path/to/dir:" || export PATH="$PATH:/path/to/dir"ませんか?
AlexP

4
sudo bash -c "echo exit|dtruss bash -li|& less|grep '^open'"macOSで使用します。(単にに置き換えstraceてくださいdtruss
マックスコプラン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.