我有一个~/.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
事情是这样的:
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
。
- 因此,您有一个新的会话
命令
source-file
已处理。- 添加了额外的窗格。
- 窗格 0 已被(重新)选择。
- 然后,命令在窗格 0 处
send-keys
“键入” + Enter 。此输入将被忽略,因为此窗格只是运行vim .
tmux发送source-file
命令的客户端。
- 这tmux客户端退出,从而关闭窗格 0。
因此,令人意外的是,窗格 0(即N:0.0
)仅运行source-file
忽略您“键入”命令的命令。此窗格从不运行可以解释“键入”命令的交互式 shell。
至少有几种方法可以解决这个问题:
首先
~/.tmux/dev
让new-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'
它将(短暂的)初始窗口移动到高索引,以便 in
new-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
删除该窗格。这可能不是您想要的。