为什么在 config.fish 中包含 exec tmux 不起作用

Naa*_*aar 1 shell fish tmux

我正在尝试设置fish run tmux,在登录时自动运行。所以我将以下内容添加到我的文件顶部config.fish

if status is-interactive
    exec tmux
end
Run Code Online (Sandbox Code Playgroud)

但现在如果我打开一个新的终端窗口,它会立即关闭。但在这里找到了这个实际上有效的答案

if status is-interactive
and not set -q TMUX
    exec tmux
end
Run Code Online (Sandbox Code Playgroud)

显然它的作用是它还检查 tmux 是否尚未激活,但是当我确定没有 tmux 会话处于活动状态以及我尝试使用的第一个代码有什么问题时,这有什么帮助。

让我补充一下,在 shell 中运行第一个(不将其放入配置文件中)效果很好。

fah*_*aho 5

当您这样做时exec tmux,就会用 tmux 替换 shell 进程。

然后,Tmux 将启动另一个 shell,该 shell 读取其配置文件并...用 tmux 替换自身。然后它将启动另一个 shell,该 shell 读取其配置文件并用 tmux 替换自身。

这是一个无限循环。这就是为什么您需要检查 tmux 是否已经是父进程之一,设置 $TMUX 是一个指示(从技术上讲,任何旧进程都可以设置该变量,它不受保护或任何东西,建议不要这样做)。


它退出而不是实际永远循环的原因是 tmux 检查 $TMUX - 如果您尝试tmux在 tmux 会话内部运行它会告诉您:

会话应小心嵌套,取消设置 $TMUX 以强制

然后退出。所以:

  • 鱼变成 tmux
  • 设置 $TMUX
  • 开始另一条鱼
  • 这成为另一个 tmux
  • 拒绝,因为 $TMUX 已经设置并退出

因为主导进程已退出,所以外部 tmux 也退出 - 由于这是终端中的顶级进程(因为它曾经是鱼),因此终端选项卡将关闭。

但无论如何失败,在不检查 $TMUX 的情况下执行此操作永远不会有任何意义。


可以看到,如果您继续启动 tmux,方法与仅在未设置 $TMUX 时执行相反的操作 - 仅在未设置 TMUX 时执行并清除它,会发生什么:

if set -q TMUX
    set -e TMUX
    exec tmux
end
Run Code Online (Sandbox Code Playgroud)

然后启动时TMUX=foo fish,会看到$TMUX已设置,将其删除,变成tmux。然后,Tmux 将设置 $TMUX 并启动另一条鱼,这将擦除 $TMUX 并成为另一个 tmux。

这将使您的终端充满 tmux 底部栏的多个副本,但实际上不允许您执行任何操作!

因此,如果您尝试这样做,您应该保持一个单独的终端打开,或者有一个单独的登录 shell,您可以使用它来停止它(通过再次从 config.fish 中删除这些行)。请确保您有办法再次删除它,这是一个有趣的实验,但在适当的情况下可能会破坏您启动终端的能力