启动 tmux 时可选运行几个命令

启动 tmux 时可选运行几个命令

我有一个~/.tmux/dev如下所示的文件:

selectp -t 0    # select the first pane
splitw -h -p 50 # split it into two halves

selectp -t 1    # select the new, second (1) pane
splitw -v -p 50 # split it into two halves

selectp -t 0    # go back to the first pane
send-keys 'vim .' Enter

如果我tmux source-file ~/.tmux/dev从 tmux 会话内部运行,它可以正常工作。

我想创建一个 bash 脚本,打开 tmux 并自动运行这些命令。

我尝试跑步

tmux new 'tmux source-file ~/.tmux/dev'

但我只看到两个窗格;带有 vim 的窗格丢失了。

我读过了如何让 tmux 打开一组窗格而无需手动输入它们?,但在安装用于管理 tmux 配置的工具之前,我想了解这里发生了什么。

在此先感谢您对这个问题所提供的任何见解。

答案1

事情是这样的:

  1. tmux new 'tmux source-file ~/.tmux/dev'

    new命令创建一个新会话,该会话包含一个窗口和一个窗格。该命令tmux source-file ~/.tmux/dev在此新窗格中运行。

    • 因此,您有一个新的会话N(其中 N 是某个数字),
    • 一个窗口N:0(或任何你设置的值base-index),
    • 单个窗格N:0.0(或任何您已base-pane-index设置好的窗格),
    • 运行命令tmux source-file ~/.tmux/dev
  2. 命令source-file已处理。

    1. 添加了额外的窗格。
    2. 窗格 0 已被(重新)选择。
    3. 然后,命令在窗格 0 处send-keys“键入” + Enter 。此输入将被忽略,因为此窗格只是运行vim .
      tmux发送source-file命令的客户端。
  3. tmux客户端退出,从而关闭窗格 0。

因此,令人意外的是,窗格 0(即N:0.0)仅运行source-file忽略您“键入”命令的命令。此窗格从不运行可以解释“键入”命令的交互式 shell。

至少有几种方法可以解决这个问题:

  • 首先~/.tmux/devnew-window窗格 0 运行您的“默认命令”(即,可能是交互式 shell)。

    此方法的优点是,不假设当前窗格正在运行交互式 shell,也不假设当前窗格正在运行交互式 shell 0(即,如果您对已拆分窗口的一部分的窗格运行原始命令系列,会发生什么情况?)。这意味着您可以安全地绑定source-file ~/.tmux/dev到可以在任何上下文中运行的键(因为它会为其所有窗格创建一个新窗口)。从 shell 中,您可以运行tmux source-file ~/.tmux/dev(在当前会话中创建一个新窗口),也可以运行原始命令tmux new 'tmux source-file ~/.tmux/dev'来创建新会话。

    这种方法的一个小缺点是,当你运行 时tmux new 'tmux source-file ~/.tmux/dev',初始窗口仍将运行发送的客户端source-file并相当快地退出。这意味着你的“主窗口”(带有分割的窗口)将比你的窗口高一个base-index,并且未来的新窗口将被放置在“主窗口”。你可以使用类似下面的方法修复这个问题:

    tmux new 'tmux move-window -t 99 \; source-file ~/.tmux/dev'
    

    它将(短暂的)初始窗口移动到高索引,以便 innew-window最终~/.tmux/dev位于base-index

  • 使用(例如)tmux new 'tmux source-file ~/.tmux/dev ; zsh -l',以便窗格在source-file命令完成后最终运行交互式 shell。

    这样做的缺点是,您最终会将首选的 shell “硬编码” 到此命令中。此外,send-keys输入 ( vim .+ Enter) 在技术上是在 shell 启动之前发送的;这可能没问题,但可能并不总是完全可靠。

    你可以通过查询来避免“硬编码”你的 shelltmux对于default-command(或者如果没有设置,default-shell(或者如果没有设置,使用 SHELL)),但这可能比你真正想要做的更多。

答案2

我可以通过这种方式解决类似的问题:

#!/bin/bash

tmp=$(mktemp --tmpdir=/tmp/).tmux

cleanup () {
        rm -f "$tmp"
}
trap cleanup EXIT

dump_cmd () {
        local i=$1
        shift
        echo "tcpdump -i $i -s 1500 \"port 67 or port 68\" -e $@"
}

cat <<-EOT > "$tmp"
        new-window
        send-keys '$(dump_cmd eno1)' Enter
        splitw -v -p 50
        send-keys '$(dump_cmd enp12s0f2)' Enter
EOT

tmux new 'tmux move-window -t 99 \; source-file '"$tmp"

# EOF #

该脚本在两个窗格中的两个接口上启动两个嗅探器。

附言

可以简单地使用

        new-window '$(dump_cmd eno1)'
        splitw -v -p 50 '$(dump_cmd enp12s0f2)'

而不是这四行,但^C也会tcpdump删除该窗格。这可能不是您想要的。

相关内容