从 bash_profile 在后台获取长时间运行的脚本

Avn*_*arr 3 bash background-process

.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 &

Run Code Online (Sandbox Code Playgroud)

我正在设置一些变量,但当发送到后台.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\]? "
Run Code Online (Sandbox Code Playgroud)

很容易看出,PS1一旦后台脚本完成,提示就不会改变。

另一方面,如果我以“阻止”内联方式获取脚本,一切都会按预期工作:

IE

调整

source .bash_profile_load_in_background & # notice the &

source .bash_profile_load_in_background # REMOVE THE &

为什么会发生这种情况?

.bash_profile有什么办法可以以简单的方式完成这项工作并加快加载时间?我不在乎有些功能是否需要几秒钟才能生效,但它必须在当前范围内生效。

Kam*_*ski 5

诡计

\n

这个另一个答案解释了为什么您的尝试不起作用。有一个技巧可以让它发挥作用,至少在某种程度上。我真的不推荐它,这不是.bash_profile应该如何工作的。

\n

这是这个想法:

\n
    \n
  1. 让我们.bash_profile创建一个临时文件并记住它的路径:

    \n
    tmpf="$(mktemp)"\n
    Run Code Online (Sandbox Code Playgroud)\n

    mktemp不可携带。)

    \n
  2. \n
  3. 设置 a trap,以便 shell 将临时文件作为源SIGUSR1。获取后,不再需要文件和陷阱,因此请考虑将清理作为陷阱的一部分。

    \n
    trap \'\n  . "$tmpf"\n  rm "$tmpf"\n  trap - USR1\n\' USR1\n
    Run Code Online (Sandbox Code Playgroud)\n
  4. \n
  5. .bash_profile_background_wizard在后台运行。该脚本必须能够写入临时文件,因此给它一个描述符或路径(作为参数或在环境中)。例子:

    \n
    tmpf="$tmpf" ~/.bash_profile_background_wizard &\n
    Run Code Online (Sandbox Code Playgroud)\n

    该脚本应启动长时间运行的任务并将 shell 代码写入临时文件。它应该构建函数和变量的定义,任何依赖于长时间运行的任务的东西,任何你希望主 shell 在准备好时“采用”的东西。根据您想要做什么,编写脚本的脚本可能并不容易。请记住,临时文件即将被主 shell解析。declare -p variable >>"$tmpf"或者语法${variable@Q}会有用。

    \n

    将所有代码写入临时文件后,脚本应发送SIGUSR1到主 shell

    \n
    kill -s USR1 "$PPID"\n
    Run Code Online (Sandbox Code Playgroud)\n

    并退出。

    \n
  6. \n
  7. 由于陷阱,主 shell 将获取.bash_profile_background_wizard.

    \n
  8. \n
\n
\n

笔记

\n
    \n
  • 如果信号在主 shell 等待某个同步命令完成时出现,则陷阱将不会执行,直到该命令完成

    \n
  • \n
  • 如果您在信号到来之前生成子级bash,则不要指望子级会对信号做出反应。因为:

    \n
      \n
    • 由于PID不同,它不会收到信号,
    • \n
    • 它不会继承陷阱。
    • \n
    \n

    请注意,如果您bash以导致子项获取源的方式生成子项.bash_profile,则整个技巧将为该子项bash 独立启动。

    \n
  • \n
  • 如果您在信号到来之前生成一个后台进程,则不要期望当主 shell 最终获取临时文件并可能更改其自己的环境时,进程的环境会被更新。

    \n
  • \n
  • 如果您在陷阱运行之前退出主 shell,那么临时文件将保留(trap \'\xe2\x80\xa6\' EXIT可能很方便)。

    \n
  • \n
\n
\n

概念证明

\n

以下代码片段旨在粘贴到交互式 Bash 中。这样您就可以测试这个想法,而不会污染您的.bash_profile. 其机制与上面介绍的相同。

\n
tmpf="$(mktemp)"\n
Run Code Online (Sandbox Code Playgroud)\n