显示第一个提示后,shell 是否可以(自动)源文件?

显示第一个提示后,shell 是否可以(自动)源文件?

我想知道是否有什么办法将一些内容放入我的启动文件中这将导致其他文件被获取显示第一个提示后。

我更喜欢一种不依赖诸如preexecprecmdperiodichooks 之类的钩子的方法。 (我正在使用 zsh,但我知道人们已经通过一些巧妙的黑客攻击trap或类似的方式编写了代码将它们添加到 bash 中。)

我非常简单的第一个测试(我没想到会起作用,但我觉得有必要尝试一下,只是为了看到精确的结果)将其添加到我的.zshrc

{ sleep 100 && export VARIABLE_SET=1 } &

然后在 shell 加载后执行此命令,前后经过 100 秒:

echo $VARIABLE_SET

当然,它(以及我能想到的每一种排列)都失败了,并且没有提供关于如何做到这一点的有希望的线索。

我希望启动文件中的某些内容可以触发影响 shell 的源,即使它在第一个提示时不能立即可用。我想找到一种方法来延迟“昂贵”的采购,并使提示快速显示,因为许多使启动文件膨胀的东西都是不经常需要的。

我希望找到一种比使用钩子更简单的方法(但我已经使用钩子创建了一个概念验证,precmd以防没有其他方法可行)。

答案1

正如您所发现的,在后台运行命令&会将它们放入子shell中,并且子shell无法更改父进程的变量/环境变量。 (“不能“这句话应该读作解决方法很丑陋.)

因此,您需要source在当前 shell 中执行该命令。我将在下面列出一些选项。

所有这些都没有完全回答您提出的问题,但它们似乎为您试图解决的实际问题提供了解决方案。

zsh-defer(zsh脚本)

.zshrc

# load zsh-defer:
source "$HOME/zsh-defer.plugin.zsh"

# ... misc. commands ...

# defer 'source "$HOME/file"' for later execution:
zsh-defer source "$HOME/file"

可以通过重复调用来提示任意数量的命令( 等source .zshrc.2)。source .zshrc.3zsh-defer

好处:处理许多zinit无法处理的边缘情况。比 更复杂的解决方案sched

表现: zsh-defer其本身最多应该在几毫秒内加载。

执行:zle执行来自(zsh 的行编辑器)的命令。

zshzsh/sched模块

(如建议的@StéphaneChazelas 之前的回答

简单直接。

.zshrc

sched +10 "source $HOME/file" &>/dev/null || source "$HOME/file"

... &>/dev/null || ...部分:如果sched不可用,或因错误退出,则立即获取该文件,假设这比根本没有好。

详细信息sched:参见zsh 的文档

缺点:

  • 如果命令执行时间较长,则会在执行时阻塞 shell
  • Yearly check: do <evil thing>? [y/N]如果在您键入命令时延迟命令意外要求用户输入 (" "),则存在意外输入的风险

表现:sched命令最多需要几毫秒来执行。

使用功率等级10k提示即时提示

不需要额外的工作——做任何你想做的事.zshrc;在.zshrc处理过程中,提示将被加载并准备好进行交互(有一些警告) 。

表现:当 shell 开始处理后大约 10 毫秒内应该可以看到提示.zshrc

执行:各种 zsh 功能和技巧。需要额外小心,例如在执行命令时重定向(和缓冲)stdin,以避免意外输入。

插件管理器zinit

zinit可以使用zinit ice wait它来延迟执行任何命令,例如获取文件。

zinit可以仅用于该功能,无需将其用作插件管理器,并且它不会与其他插件管理器(如果有)相互干扰。

原始版本zdharma/zinit不再维护,但这些分叉是:

我不认为长时间运行的命令会阻止 shell,但我自己还没有对此进行测试。

表现:在我的系统上,zinit它本身加载大约需要 10 毫秒,或者 5 毫秒没有完成。

执行: zinit向 中添加一个 shell 函数zsh/sched,该函数在调用时立即将自身添加回表中sched,并且除此之外还执行用户设置的命令,使用zsh 钩子和其他 zsh 功能。

zsh-async图书馆

也可能有用 - 为了完整性而提到。

是一个用于在zsh中运行异步任务的小型通用库。它将要但是,在单独的进程中运行它们,将无法在父 shell 中设置环境变量。我相信有一些简单的解决方法,通过分配一个回调函数来允许在父 shell 中执行结果。

好处:使用相当广泛,并积极维护了八年。

执行:用于zsh/zpty启动执行延迟命令的伪终端。


推荐阅读

罗姆卡电视台's(作者zsh-defer功率等级10k关于分阶段 zsh 启动的一般想法和建议/延迟加载/延迟执行。

有关 shell 加载性能的额外常见问题解答

问:我可以编译.zshrc为字代码以使其执行速度更快吗?
A:理论上这是可能的,但很容易引入别名、错过重新编译等问题。不建议。
问:我现在明白了可能出现的问题。我还是想尝试一下这个。
A:不,真的,你不知道。

答案2

你总是可以使用sched.添加到您的~/.zshrc

sched +30 'source ~/.zsh/more-stuff'

并将~/.zsh/more-stuff在启动后 30 秒内获取(或在 30 秒后出现下一个提示时)。

答案3

你不能使用这个{...} &想法,因为这&会导致东西被放入子外壳中;那里设置的变量不会影响父级。

因此,我们可以将设置写入临时文件,并将该设置读入父文件。

一种方法可能是使用 DEBUG 陷阱。

尚未完全测试,但也许类似

( sleep 100 ; echo MYVAR=1 ; echo trap - DEBUG ) > ~/.slowstartfile.$$
trap '. ~/.slowstartfile.$$' DEBUG

DEBUG 陷阱通常在执行命令后调用。

所以

% ( sleep 10 ; echo MYVAR=1 ; echo trap - DEBUG ) > ~/.slowstartfile.$$ &
[1]     9411
% trap 'source ~/.slowstartfile.$$' DEBUG                           
% sleep 10
[1] +  Done                    ( sleep 10 ; echo MYVAR=1 ; echo trap - DEBUG ) > ~/.slowstartfile.$$ &
% echo $MYVAR                                                       
1

答案4

如果您正在寻找源文件.env来加载环境变量,那么多滕夫可以帮你。

相关内容