我tmux
在工作中使用它作为我的 IDE。我还在vim
各种 tmux 窗格中运行,并且经常将进程置于后台(或者我只是关闭窗口 - 我将 vim 配置为在窗口关闭时不删除打开的缓冲区)。现在我遇到了一个问题,因为我想要编辑的文件在我的其他 vim 会话之一中打开,但我不知道是哪一个。
是否可以在不手动检查所有窗口和窗格的情况下找到哪一个?在我的特殊情况下,我知道我没有编辑它,vim ~/myfile.txt
因为ps aux | grep myfile.txt
没有返回任何内容。
答案1
它没有告诉我一切,但我使用fuser ~/.myfile.txt.swp
它给了我 vim 会话的 PID。运行后ps aux | grep <PID>
我能够找出我正在使用哪个 vim 会话,这给了我一个提示,告诉我在哪个窗口中打开了它。
感谢 Giles 的灵感以及一点坚持和运气,我想出了以下命令:
⚘ (FNAME="/tmp/.fnord.txt.swp"; tmux switch -t $(tmux list-panes -a -F '#{session_name}:#{window_index}.#{pane_index} #{pane_tty}' | grep $(ps -o tty= -p $(lsof -t $FNAME))$ | awk '{ print $1 }'))
解释一下它的作用:
(FNAME="/tmp/.fnord.txt.swp";
这将创建一个子 shell 并设置FNAME
为环境变量。严格来说,这不是必需的 - 您可以$FNAME
自己替换为文件名,但它确实使编辑变得更容易。现在,从内到外进行工作:
lsof -t $FNAME
这会产生仅有的打开文件的进程的 PID。
ps -o tty= -p $(...)
这会产生pts
我们使用 发现的 PID 的lsof
。
tmux list-panes -a -F '#{session_name}:#{window_index}.#{pane_index} #{pane_tty}'
这会生成一个条目窗格列表,例如session:0.1 /dev/pts/1
。第一部分是 tmux 喜欢的目标格式,第二部分是pts
| grep $(...)$
这会过滤我们的窗格列表 - 尾随$
的是,因此它只会匹配一我们关心。我很偶然地发现了 和pts/2
,pts/22
所以有二匹配,哎呀!
| awk '{ print $1 }'
这会生成session:0.1
适合传递到 的窗格输出部分tmux switch -t
。
这应该适用于会话和窗格,使包含交换文件的窗格成为焦点。
答案2
你的问题的概要答案是:
for all the tmux sessions:
for all the windows in the session:
for all the panes in windows:
for all sub process pids (recursively):
find the open files
所有会话: tmux list-sessions -F '#{session_id}:#{session_name}
所有窗口: tmux list-windows -F '#{window_id}XX#{window_index}XX#{window_name}' -t "$session_id"
所有窗格: tmux list-panes -F '#{pane_id}:#{pane_index}:#{pane_pid}' -t ""$session_id":"$window_index""
所有子进程 pid: ps -o pid --no-headers --ppid $pid
打开文件:lsof -p $pid
上述的实现显示了一个树:
sessions
windows
panes
process
open files
显示哪个进程打开了文件(在我的例子中也是 vim)。
可以在以下位置找到https://github.com/nkh/tmux-ls
它已经在 github 上存在 5 年了,但我鼓励你克隆它,以防它被删除(或 github 崩溃)