在我的本地机器上,我有 3 个 node.js 实例同时运行。每个在名为“服务器”的 tmux 窗口中都有自己的 Pane 。问题是找出哪个节点在哪个 Pane 中运行并不容易,因为它们的日志是相似的。
我需要的是每个 Pane 的标题。据我所知,tmux 本身没有这个功能:它只有窗口的标题,而不是 Pane 的标题。在每个 Pane 中为每个 node.js 实例启动一个单独的 tmux session 看起来有点矫枉过正。
那么是否有一些小程序可以启动一个命令,用指定的状态栏包装它的输出?
提前致谢
最佳答案
tmux 确实支持每个 Pane 的标题,但它不提供每个 Pane 的位置来显示这些标题。
您可以使用转义序列 ESC ]2;
… ESC \
设置 Pane 的标题(例如,请参阅 tmux 联机帮助页中名为 Names and Titles 的部分)。您可以像这样从 shell 执行此操作:
printf '\033]2;%s\033\\' 'title goes here'
每个 Pane 的标题默认为系统的主机名。默认情况下,事件 Pane 的标题显示在 tmux 状态行的右侧( session 变量
status-right
的默认全局值为 "#22T" %H:%M %d-%b-%y
,显示 Pane 标题、时间和日期的 22 个字符)。因此,只要您对能够看到事件 Pane 的标题感到满意(即愿意切换 Pane 以查看非事件 Pane 的标题),您就可以使用默认功能。只需在为每个 Pane 启动主命令之前发送适当的标题设置转义序列。
如果您绝对需要一条专线来显示一些每个 Pane 的信息,那么嵌套的 tmux session 可能不会像您最初想象的那样(不必要)“过度杀伤”。
在一般情况下,要在某些给定终端上提供不受侵犯的状态行,您将需要一个完整的终端(重新)仿真器,它位于原始终端和新终端(少一个行)之间。需要这种(重新)仿真来转换发送到内部终端的控制序列并将它们转换为原始终端。例如,要在外部终端的底部维护一个状态行,命令
发送到内部终端必须成为
当翻译并发送到外部终端时。同样,发送到内部终端的 LF 必须变成
在外部终端。
像 tmux 和 screen 这样的程序就是这样的终端重新仿真器。当然,终端仿真器还包含许多其他功能,但是您需要大量的终端仿真代码才能提供可靠的状态行。
然而,有一个轻量级的解决方案,只要
像许多终端模拟器一样,tmux 在其 Pane 中支持“设置滚动区域”终端控制命令。您可以使用此命令将滚动区域限制在终端的顶部(或底部)N-1 行,并将某种实例标识文本写入非滚动行。
需要限制(不允许光标移动命令,不允许调整大小),因为生成输出的程序(例如 Node.js 实例)不知道滚动已被限制在特定区域。如果输出生成程序碰巧将光标移到滚动区域之外,则输出可能会出现乱码。同样,终端模拟器可能会在调整终端大小时自动重置滚动区域(因此“非滚动行”可能最终会滚动消失)。
我写了一个脚本,使用
tput
生成相应的控制序列,写入非滚动行,将光标移动到滚动区域后运行一个程序:#!/bin/sh
# usage: no_scroll_line top|bottom 'non-scrolling line content' command to run with args
#
# Set up a non-scrolling line at the top (or the bottom) of the
# terminal, write the given text into it, then (in the scrolling
# region) run the given command with its arguments. When the
# command has finished, pause with a prompt and reset the
# scrolling region.
get_size() {
set -- $(stty size)
LINES=$1
COLUMNS=$2
}
set_nonscrolling_line() {
get_size
case "$1" in
t|to|top)
non_scroll_line=0
first_scrolling_line=1
scroll_region="1 $(($LINES - 1))"
;;
b|bo|bot|bott|botto|bottom)
first_scrolling_line=0
scroll_region="0 $(($LINES - 2))"
non_scroll_line="$(($LINES - 1))"
;;
*)
echo 'error: first argument must be "top" or "bottom"'
exit 1
;;
esac
clear
tput csr $scroll_region
tput cup "$non_scroll_line" 0
printf %s "$2"
tput cup "$first_scrolling_line" 0
}
reset_scrolling() {
get_size
clear
tput csr 0 $(($LINES - 1))
}
# Set up the scrolling region and write into the non-scrolling line
set_nonscrolling_line "$1" "$2"
shift 2
# Run something that writes into the scolling region
"$@"
ec=$?
# Reset the scrolling region
printf %s 'Press ENTER to reset scrolling (will clear screen)'
read a_line
reset_scrolling
exit "$ec"
你可以这样使用它:
tmux split-window '/path/to/no_scroll_line bottom "Node instance foo" node foo.js'
tmux split-window '/path/to/no_scroll_line bottom "Node instance bar" node bar.js'
tmux split-window '/path/to/no_scroll_line bottom "Node instance quux" node quux.js'
只要终端支持并发布其
csr
和 cup
terminfo 功能,该脚本也应该在 tmux 之外工作。关于command-line - Tmux 中的 Pane 标题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9747952/