是否可以在 tmux 中创建具有相同连接的新窗格?

是否可以在 tmux 中创建具有相同连接的新窗格?

我的设置:在本地使用 Tmux,在不同的窗格中与不同的服务器建立许多连接

我想做的事:按下一个窗格内的快捷方式,即可打开一个已设置相同连接的新窗格。

为什么:工作流程。很多时候,当我在服务器上工作时,我需要打开一个新窗格来执行某些操作,同时其他一些操作正在运行。如果我可以打开一个已设置好所有内容的新窗格,我将节省大量的时间和精力。

我愿意通过其他方式来实现我想要做的事情。我可以在远程机器上设置 tmux,但我更喜欢在本地运行 tmux。

编辑:
我已经学会了 ssh 多路复用,这解决了我的问题的一部分(每个服务器只需登录一次)。我已将其添加到我的~/.ssh/config文件中:

### Multiplexing ###
Host *
    ControlMaster auto
    ControlPath ~/.ssh/sessions/%C
    ControlPersist 1h

现在我必须弄清楚如何在 tmux 中设置快捷方式以在新窗格中连接到同一主机。

答案1

解决方案

将以下脚本保存到_tmux_duplicate_pane您的目录中PATH

#!/bin/bash
set -e

pid="$(tmux display-message -p '#{pane_pid}')"
pid="$(ps -o tpgid:1= -p "$pid")"
dir="$(readlink -f "/proc/$pid/cwd")"
cd -- "${dir:?}"
exe="$(readlink -f "/proc/$pid/exe")"
readarray -d '' args <"/proc/$pid/cmdline"
name="${args[0]}"
args=("${args[@]:1}")

tmux split-window "$@" -c "$dir" bash -c "exec -a ${name@Q} ${exe@Q} ${args[*]@Q}"

使脚本可执行(chmod +x _tmux_duplicate_pane)。最后将其绑定到 中的按键tmux。示例:

tmux bind-key -T prefix u run-shell _tmux_duplicate_pane

该命令旨在在 shell 中调用。在~/.tmux.conf(永久设置)中,该命令应为bind-key …

现在prefixu应该可以按您想要的方式工作了。


解释

该脚本的工作方式是查找 中与当前窗格关联的进程的控制终端的前台进程组 ID tmux。它假设前台进程组 ID 的领导者是您要复制的命令。它从中检索信息/proctmux split-window相应地调用。


注意事项

  • 不要_tmux_duplicate_pane在窗格中作为命令运行。如果这样做,脚本将重复本身在新窗格中,它将变成以线性方式产生的叉炸弹。按照图示绑定到一个键并以这种方式使用它。

  • 该脚本假定您要执行的命令是活动窗格中前台进程组的领导者。如果出现以下情况,它将无法按预期工作:

    • 窗格中的(本地)shell 不会在单独的进程组中运行命令(例如,shell 是禁用作业控制的 Bash);
    • 或者您要执行的命令在管道中;例如,交互式 Bash(启用了作业控制)在一个进程组中运行整个管道,并且领导者是该行中的第一个命令;我们的脚本尝试复制领导者,但在管道的情况下,领导者可能不再存在,它可能提前退出;复制全部的管道是一项不简单的任务,依赖于 shell,脚本甚至不会尝试;
    • 或者由于其他原因,您所追求的命令不是前台进程组的领导者。

    该脚本应该能够成功复制在当前窗格中交互式现代 shell(如 Bash 或 Zsh)中运行的简单命令。

  • 中的条目/proc/$pid/cmdline不足以复制命令。第 0 个条目是任意的(例如,参见help execBash,注释-a)。另一方面/proc/$pid/exe,剩余的参数/proc/$pid/cmdline也不足以复制命令,同一个可执行文件可能会根据第 0 个参数而有不同的行为。该脚本使用exec -aBash 并构建一个保留可执行文件和第 0 个参数的 shell 命令。

  • 在某些情况下/proc/$pid/cmdline/proc/$pid/exe可能不适合我们的目的。示例场景:

    • 复制过程可能已经改变了cmdline. 原始参数数组可能会丢失。
    • 您调用并希望复制的进程可能已exec添加到具有另一个参数数组的另一个可执行文件中。您可能能够复制后者,但如果需要前者来为后者进行设置,则复制实例可能会失败。

    但在这种情况下,这种情况不应该发生ssh

  • 脚本将尝试复制任何命令,不仅仅是ssh。您可以添加一些逻辑、测试$exe和/或${args[0]},使脚本成为无操作,除非命令是ssh …

  • 当重复命令退出时,其窗格中将没有 shell。除非选项remain-on-exit处于on中,否则窗格将终止tmux。一个简单的解决方法是强制交互式 shell命令。例如,而不是tmux split-window … "…"你做的tmux split-window … "…; bash"

  • 在复制命令时,脚本会尝试在原始进程的当前工作目录中执行此操作。在某些情况下,这将是错误的,特别是当进程将相对路径作为参数然后更改其工作目录时。脚本无法知道在调用命令时哪个目录是当前目录;它知道现在的当前目录可能相同也可能不同。

  • 该脚本不会尝试复制原始进程的整个环境。如果您SSH_ASKPASS=… ssh …在窗格中运行并尝试复制此环境,则新ssh命令将不知道该变量。/proc/$pid/environment我猜可以进行解析;但脚本不会这样做。

  • 脚本在不同时刻检索不同的信息。这意味着它容易出现竞争条件。

  • 脚本中的目的cd是当出现问题时让脚本尽早失败。

  • 您提供给脚本本身的参数将传递给tmux split-window。这意味着您可以绑定tmux bind-key … '_tmux_duplicate_pane -h'并享受水平分割。

相关内容