bash_profileからバックグラウンドで長期実行スクリプトを取得する

bash_profileからバックグラウンドで長期実行スクリプトを取得する

.bash_profile端末を開くたびにスクリプトを実行するのに数秒かかりますので、これは非常に迷惑になります。

テストの結果、いくつかのコマンドに時間がかかることがわかったので、そのコマンドを.bash_profile新しいスクリプトに移動しました。.bash_profile_load_in_background

.bash_profileバックグラウンドでソースを見つけようとします。

.bash_profile

# fast stuff here

#.....

# slow stuff here

source .bash_profile_load_in_background & # notice the &

いくつかの変数を設定していますが、.bash_profile_load_in_backgroundバックグラウンドで送信すると正しく伝播されません。source&

以下は「遅い」スクリプトの要約バージョンです。

[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm

[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

if type brew &>/dev/null; then
  HOMEBREW_PREFIX="$(brew --prefix)"
  if [[ -r "${HOMEBREW_PREFIX}/etc/profile.d/bash_completion.sh" ]]; then
    source "${HOMEBREW_PREFIX}/etc/profile.d/bash_completion.sh"
  else
    for COMPLETION in "${HOMEBREW_PREFIX}/etc/bash_completion.d/"*; do
      [[ -r "$COMPLETION" ]] && source "$COMPLETION"
    done
  fi
fi

if [ -f $(brew --prefix)/etc/bash_completion ]; then
 . $(brew --prefix)/etc/bash_completion
fi

# parse the git branch
gb() {
     __git_ps1
}

# change the prompt to show working directory and git branch
PS1="\[\e[32m\]\w \[\e[91m\]\$(gb)\[\e[00m\]? "

PS1バックグラウンドスクリプトが完了すると、プロンプトが変わらないことが簡単にわかります。

一方、「ブロック」スクリプトをインラインで受け取ると、すべてが期待どおりに機能します。

つまり

調整

source .bash_profile_load_in_background & # notice the &

到着

source .bash_profile_load_in_background # REMOVE THE &

なぜこれが起こるのですか?

.bash_profile簡単な方法でロード時間を短縮する方法はありますか?一部の機能が適用されるまでに数秒かかるかどうかは関係ありませんが、現在の範囲内で適用する必要があります。

ベストアンサー1

いたずら

この他の答え試したことがうまくいかなかった理由を説明してください。少なくともある程度は機能する秘訣があります。私は本当にそれをお勧めしません。それは.bash_profileそれがうまくいく方法ではありません。

アイデアは次のとおりです。

  1. .bash_profile一時ファイルを作成し、そのパスを覚えてみましょう。

    tmpf="$(mktemp)"
    

    mktempポータブルではありません。)

  2. trapシェルが一時ファイルをソースとして使用するように設定しますSIGUSR1。取得したファイルとトラップは不要になるため、トラップの一部としてクリーンアップすることを検討してください。

    trap '
      . "$tmpf"
      rm "$tmpf"
      trap - USR1
    ' USR1
    
  3. .bash_profile_background_wizardバックグラウンドで実行されます。スクリプトは一時ファイルに書き込むことができる必要があるため、記述子またはパス(引数または環境内)を指定してください。例:

    tmpf="$tmpf" ~/.bash_profile_background_wizard &
    

    このスクリプトは長期実行ジョブを開始し、一時ファイルにシェルコードを記述する必要があります。そうしなければならない立てる関数と変数の定義、長期実行タスクに依存するすべて、準備が整ったときにメインシェルが「受け入れる」ことを望むすべて。実行する操作によっては、スクリプトをスクリプト化するのは簡単ではないかもしれません。一時ファイルがすぐに作成されることを忘れないでください。Fメインシェルで。declare -p variable >>"$tmpf"それとも構文が${variable@Q}役に立ちます。

    一時ファイルにすべてのコードを記述したら、スクリプトをSIGUSR1メインシェルに送信する必要があります。

    kill -s USR1 "$PPID"
    

    そして出てください。

  4. トラップのため、メインシェルは.bash_profile_background_wizard


ノート

  • メインシェルが同期コマンドの完了を待っている間に信号が発生した場合コマンドが完了するまでトラップは実行されません。

  • シグナルが到着する前に子を生成する場合は、bash子がシグナルに反応することを期待しないでください。なぜなら:

    • PIDが違うので信号が届かないので、
    • トラップを継承しません。

    bashソースを取得する方法でサブキーを生成すると、トリック全体がその.bash_profileサブキーで始まります。bash 独立して

  • シグナルが到着する前にバックグラウンドプロセスを生成する場合は、デフォルトのシェルが最終的に一時ファイルをインポートし、独自の環境を変更したときにそのプロセスの環境が更新されるとは期待しないでください。

  • トラップが実行される前にデフォルトのシェルを終了すると、一時ファイルはそのまま残ります(trap '…' EXIT便利かもしれません)。


概念の証拠

次のコードは、インタラクティブBashに貼り付けるためのものです。これにより、アイデアを汚染することなくアイデアをテストできます.bash_profile。メカニズムは上記と同じです。

# imagine this block is sourced from .bash_profile
{
export PS1='poor prompt > '
tmpf="$(mktemp)"
trap '
  . "$tmpf"
  rm "$tmpf"
  trap - USR1
' USR1
# wizard in background
tmpf="$tmpf" bash -c '
  sleep 10  # delay
  PS1="RICH PROMPT >>> "
  declare -p PS1 >>"$tmpf"
  kill -s USR1 "$PPID"
' &
}
# Initially you will see a poor prompt.
# Run few basic commands or keep striking Enter.
# After 10 seconds the prompt should change.

おすすめ記事