如何根据我的会话名称自动将我的所有“tmux”会话记录到目录中的文件中?

如何根据我的会话名称自动将我的所有“tmux”会话记录到目录中的文件中?

我有几个命名tmux会话。例如:

$ tmux new -s mysession1
$ tmux new -s mysession2

我想在 my 中添加一些内容,它会根据会话名称~/.tmux.conf自动将每个会话记录到目录中的文件中。~/mytmuxsessions/例如,在上面给出mysession1mysession2创建的情况下,它将创建以下日志文​​件,其中包含我的终端窗口命令的输出(就像命令一样script -f file.log):

  1. ~/mytmuxsessions/mysession1.log
  2. ~/mytmuxsessions/mysession2.log

我尝试研究一下,发现了这一点:

  1. tmux 中是否有相当于 GNU Screen 的“log”命令?
  2. https://blog.sleeplessbeastie.eu/2019/10/28/how-to-store-the-contents-of-tmux-pane/

这些问题试图将一个键绑定到一个命令,但我希望它是自动的,即,作为我可以戴上~/.tmux.conf并忘记它的东西。例如,此命令似乎正在执行的操作是在日志文件中处理我当前的所有输出:

capture-pane -b temp-capture-buffer -S - \; save-buffer -b temp-capture-buffer ~/tmux.log \; delete-buffer -b capture-buffer

但我想要的是类似于Linux scriptcommand的东西script -f mysession.log,我可以将其放入 my 中~/.tmux.conf,根据我的会话名称不断将终端输出保存到日志文件中。

答案1

我无法找到一种方法来仅使用.tmux.conf.我所说的“动态”一词是指根据您的情况中的会话名称,并根据Unix时间戳就我而言。但是,我能够使用基本代码tmux 日志记录;我修改了源代码以获得适合我的东西。

请注意,此解决方案不会将特定会话中的所有内容保存在一个日志文件中。这是可以做到的,但是将此类会话中可能存在的不同窗口和窗格组合起来会很困难。但是,此解决方案将为会话中的每个窗格保存一个日志文件,因此日志文件中将包含您的所有输入和输出。您始终可以从 派生tmux-plugins/tmux-login,或者您可以根据他们组合在一起的内容编写自己的代码并仅使用您喜欢的代码。


长话短说

tmux-logging从git 存储库安装tmux-plugins

更改变量定义以filename_suffix匹配您想要的格式。这应该在 中完成/path/to/tmux-plugins/tmux-logging/scripts/variables.sh

将其复制toggle_logging.sh到另一个脚本 - 我称之为~/.ensure_tmux_logging_on.sh,它位于我的$HOME目录中,因此将来的更新tmux不会将其删除。更改脚本,以便if is_logging不执行任何操作(或仅输出一条消息)。保留关联的else分支不变。

~/.ensure_tmux_logging_on.sh从您的.bash_profile(或.bash_login.login.profile- 以确保它被非登录 shell 调用为准)调用您的。tmux总是打开一个非登录 shell,因此.bashrc除非您从以前的脚本之一获取它,否则它将不起作用。看这里 (1),这里 (2), 或者这里 (3)- 所有这三个都是同一个问题的答案 - 了解更多详细信息。

在某处记下笔记,因为如果有更新tmux-logging,您将不得不使用相同的技巧。

我试图找出一种方法来执行此操作.tmux.conf,但在获取会话信息时遇到困难,因为这似乎是在可访问的变量中设置的 .tmux.conf已被采购。


更多细节

我用的是Tmux 插件管理器( tpm) 安装方法tmux-logging,意思是我一次性安装tpm好了。以下是一些快速命令,可以执行和tmux-logging的自述文件中描述的操作。tpmtmux-logging笔记,如果您已经有tpm,请按照以下网址的说明进行操作自述tmux-logging文件,即添加行

set -g @plugin 'tmux-plugins/tmux-logging'

到您的插件列表~/.tmux.conf

tpm您可以使用此命令查看是否有(至少是标准安装)

$ test ! -d ~/.tmux/plugins/tpm && \
 echo -e "\n\nYou don't have \`tpm', continue with the next commands\n" || \
 echo -e "\n\n\
You have \`tpm'.
\033[0;31mPAY ATTENTION TO THIS MESSAGE\x21\033[0m
Follow the instructions at
'https://github.com/tmux-plugins/tmux-logging/'
then
\033[0;32mgo to the 'After getting tmux-logging' part of the answer\033[0m\n"

如果没有tpm,请运行

#(prompt can be in tmux or not)
## It's best, but not necessary, to get in the directory where we'll be doing stuff.
bbd025@MACHINE $ cd
## check the existence of ~/.tmux/plugins/tpm directory, 
##+ create it if it doesn't exist
bbd025@MACHINE $ test -d ~/.tmux/plugins/tpm || mkdir -p ~/.tmux/plugins/tpm
## clone in the tpm code
bbd025@MACHINE $ git clone https://github.com/tmux-plugins/tpm \
   ~/.tmux/plugins/tpm
## create ~/.tmux.conf if it doesn't exist
bbd025@MACHINE $ test -f ~/.tmux.conf || touch ~/.tmux.conf
## Add the lines to ~/.tmux.conf as directed by the READMEs. Note that
##+ that the lines with only a '.' allow for spacing between the end of
##+ anything currently in your ~/.tmux.conf and these lines
bbd025@MACHINE $ cat <<'EOF' | sed 's/^\.$//g;' >> ~/.tmux.conf
.
.
# List of plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
# -v- OUR LOGGING PLUGIN -v-
set -g @plugin 'tmux-plugins/tmux-logging'

# Other examples:
# set -g @plugin 'github_username/plugin_name'
# set -g @plugin 'github_username/plugin_name#branch'
# set -g @plugin '[email protected]:user/plugin'
# set -g @plugin '[email protected]:user/plugin'

#Initialize TMUX plugin manager(keep this line at the very bottom of tmux.conf)
run '~/.tmux/plugins/tpm/tpm'
EOF
bbd025@MACHINE $

获取 tmux-logging 后

请注意,如果您使用其他方法来安装tmux-logging或配置不同的内容,则需要使用 来/my/path/to/tmux-logging/代替~/.tmux/plugins/tmux-logging/.

如果您还没有这样做,请开始一个tmux会话

$ tmux

您应该会在底部看到一个绿色横幅类型的东西,让您知道您正在其中tmux。按[Prefix]+ Shift+ i(也称为[Prefix]+ I,默认情况下先按 +,然后按 + Ctrl。)bShifti

它将显示以下几行在实际终端中,而不是在绿色通知栏中。

TMUX environment reloaded.
Done, press ENTER to continue.

ENTER

现在,我们来编辑~/.tmux/plugins/tmux-logging/scripts/variables.sh.

对于接近您(OP)所需的输出文件名的内容(但当调用新窗口或窗格时不会被覆盖或扰乱 - 至少我猜会发生这种情况),请更改它,以便您拥有以下内容线路:

# General options
# Next, commented line has original variable
#replaced#filename_suffix="#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S.log"
filename_suffix="#{session_name}-#{window_index}-#{pane_index}.log"

(查看注释[1]以了解在tmux更新时我如何保证这些信息的安全。)

-#{window_index}-#{pane_index}如果您从未在会话中打开多个窗口或窗格,则可以删除。这将给出与OP所需的完全匹配的日志文件名称。如果你最终得到多个窗格,我真的不确定日志记录会发生什么,但我认为如果不覆盖它会变得混乱。仅供参考,您看到的变量来自~/.tmux/plugins/tmux-logging/scripts/shared.sh.

请注意,您还可以更改default_logging_path文件中的几行,但这是可以在 中处理的事情~/.tmux.conf,所以我没有搞乱它。

我所做的 - 我希望我的用户名成为日志文件的一部分,我想要一个绝对唯一且可跟踪的时间戳,并且我希望按时间顺序排序(并且我不喜欢我的文件每行超过 80 个字符) - 是改变线路所以我有

# General options
# -v- original before change by bballdave025 -v- , 2022-02-28
#filename_suffix=\
#"#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S.log"
filename_suffix="bbd025-%s\
-#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S%z.log"

如果您不想要tmux-文件名之前的内容,则应该对该variables.sh文件进行另一次更改。我不会为自己的机器执行此操作,因为略有不同的日志记录选项有不同的文件名前缀,但我这样做是为了这个答案。

因此,如果您不需要任何前缀,请更改variables.sh为以下行:

# original commented out on the line below
#default_logging_filename="tmux-${filename_suffix}"
default_logging_filename="${filename_suffix}"

现在,让我们将我们需要的内容添加到我们的~/.tmux.conf.第一行会将输出日志放入您指定的目录中。任何其他合法路径都可以放置在这里。让我们这样做,如果您使用tmux-logging屏幕捕获和/或日志缓冲区和继续日志记录选项,则屏幕捕获或带有缓冲区的完整历史记录将与自动启动日志文件保存在同一目录中。尽管我将这些行放在文件中的具体位置并不重要~/.tmux.conf,但我将其保留在 TMUX 插件管理器告诉我们保留在最后的最后一行之前。

set -g @logging-path "$HOME/mytmuxsessions"
set -g @screen-capture-path "$HOME/mytmuxsessions"
set -g @save-complete-history-path "$HOME/mytmuxsessions"

接下来,我们将复制toggle_logging.sh到一个新脚本并确保它包含在我们的脚本中~/.bash_profile(或由非登录脚本确定调用的任何内容)。

我实际上是~/.bashrc从我的~/.bash_profile代码中获取的:

# @file  .bash_profile

if [ -f ~/.bashrc ]; then
  . ~/.bashrc
fi

如果您的 中存在诸如以下的行~/.bashrc,您可以将其注释掉。

# If not running interactively, don't do anything
[[ "$-" != *i* ]] && return

## If not running interactively, don't do anything
#[[ "$-" != *i* ]] && return

否则,如果您想保留for 环境和函数仅在登录 shell 中使用,只需添加我将放在末尾的~/.bashrc行,或者为非登录脚本加载的任何文件。~/.bashrc~/.bash_login

最后,我们得到了toggle_logging.sh.运行下面给出的复制命令。再次,我将我的文件放在我的主文件夹(~又名$HOME)中,以确保它不会因未来的升级而被删除tmux。您可以选择适合您的目录和文件名,而不是下面选择的目录和文件名。

$ cp ~/.tmux/plugins/tmux-logging/scripts/toggle_logging.sh \
     ~/.ensure_tmux_logging_on.sh

(如果您没有使用tpm的选项tmux-logging,则需要从克隆或构建 的任何位置访问该脚本tmux-logging。)

现在,对您的进行更改~/.ensure_tmux_logging_on.sh,使其看起来如下所示。 (请注意,您不需要保留我注释掉的原始代码。这些部分就在那里,因此您可以搜索原始文本并替换它或像我一样将其注释掉。这样,您就可以知道新东西应该去哪里。)

---

### changed for auto-logging (I often put in my username and date of change)
### bballdave025, 2022-02-28
#orig#CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

#orig#source "$CURRENT_DIR/variables.sh"
#orig#source "$CURRENT_DIR/shared.sh"

## new for tmux auto-logging, bballdave025 2022-02-28
TMUX_LOGGING_SCRIPTS_DIR="$HOME/.tmux/plugins/tmux-logging/scripts"
CURRENT_DIR="$TMUX_LOGGING_SCRIPTS_DIR"
  ## Not really our current dir, but it allows other code called
  ##+ downstream to work.

source "$TMUX_LOGGING_SCRIPTS_DIR/variables.sh"
source "$TMUX_LOGGING_SCRIPTS_DIR/shared.sh"

---

### original function commented out, bballdave025 2022-02-28
#stop_pipe_pane() {
#  tmux pipe-pane
#  display_message "Ended logging to $logging_full_filename"
#}

### new function added, bballdave025 2022-02-28
confirm_logging()
{
  display_message "Logging already happening to ${logging_full_filename}"
}

---

#original comment## starts/stop logging
# starts/continues logging ( bballdave025, 2022-02-28 )
#orig#toggle_pipe_pane() {
## -v- new function name -v- , bballdave025, 2022-03-09
ensure_pipe_pane_on()
{
  if is_logging; then
    #orig#set_logging_variable "not logging"
    #orig#stop_pipe_pane
    # -v- bballdave025 2022-02-28 -v- first line probably unneeded (?)
    set_logging_variable "logging"
    confirm_logging
    # everything from here is as in the original
  else
    set_logging_variable "logging"
    start_pipe_pane
  fi
}

## -v- main changed -v- by bballdave025, 2022-03-08
#orig#main() {
#orig#  if supported_tmux_version_ok; then
#orig#    toggle_pipe_pane
#orig#  fi
#orig#}

main()
{
  if supported_tmux_version_ok; then
    ensure_pipe_pane_on
  fi
}
main

---

你不需要像我一样冗长,即你不需要所有的评论和旧行。我希望能够清楚地说明正在发生的变化。有多种方法可以使这段代码更简单;如果您了解发生了什么事,欢迎您这样做。

确保您的脚本可执行

$ chmod +x ~/.ensure_tmux_logging_on.sh

现在,我们有几行代码将其添加到您知道将在非登录终端调用的任何文件 - ~/.bash_profile、 a等~/.bashrc来源的文件中。~/.bash_profile在我的示例中,我让它被~/.bashrc`~/.bash_profile 调用用于非登录屏幕,所以我将在那里添加我的行。

有了这些行,它就会在我们第一次~/.ensure_tmux_logging_on.sh进入新终端时运行。只需在您(或其他文件)tmux的任何位置添加以下行即可;~/.bashrc我把它放在最后。

if [ ! -z $TMUX ]; then
  $HOME/.ensure_tmux_logging_on.sh
fi

在我的系统“RHEL 8”(基于 RedHat)上进行测试。

简短版本:它有效。您可以跳过下一部分,但我建议您查看下面的 5 项。

需要了解的重要事项如下:

1)现在,运行OP的命令,即

$ tmux new -s mysession1

导致日志文件,

~/mytmuxsessions/mysession1-1-1.log

类似地,$ tmux new -s mysession2导致日志文件,~/mytmuxsessions/mysession2-1-1.log

2)这些会话中任何新创建的窗口/窗格都将用数字表示,即使您在终端提示符下使用命令使用名称创建它们也是如此。

3)如果您不提供会话名称(只能通过从终端提示符启动新窗口并使用 (   -s   ) SESSION_NAME` 选项来提供名称,您将只能获得分配的会话编号。

4)当为 OP 进行设置时,任何新会话的日志与之前创建的会话具有相同的名称,例如,第二次使用tmux new -s mysession1将覆盖前一个日志文件。如果没有例子,感觉不是很清楚,所以这里是一个。

$ ls -lAh ~/mytmuxsessions # to see that mysession1-1-1.log is already there
-rw-r--r--. 1 bbd025 bbd025 405 Mar   1  10:22 mysession1-1-1.log
-rw-r--r--. 1 bbd025 bbd025 824 Feb   28 17:40 mysession2-1-1.log
$ tmux new -s mysession1 # I'll enter a new tmux session after this command
(tmux)$ # Some stuff.
(tmux)$ echo "Putting text, I/O, etc. in the logfile"
(tmux)$ alias ls='ls --color=auto'
(tmux)$ type ls
ls is aliased to 'ls --color=auto'
(tmux)$ tmux kill-session -t mysession1
$ ls -lAh ~/mytmuxsessions
-rw-r--r--. 1 bbd025 bbd025 1.6K Mar   2  13:02 mysession1-1-1.log
-rw-r--r--. 1 bbd025 bbd025 824  Feb   28 11:40 mysession2-1-1.log

第一个mytmuxsession1-1-1.log已创建Mar 1 10:22且大小为405字节的日志文件 不再存在。相反,我们现在已经mytmuxsession1-1-1.log创建了Mar 2 13:02,并且大小为1.6K

如果你想避免这种覆盖,只需以 BSD 命令的格式包含某种类型的日期字符串date,例如将 tmux-logging 更改variables.sh为类似的内容

filename_suffix="#{session_name}-#{window_index}-#{pane_index}\
-%Y%m%dT%H%M%S%z.log"

请注意,这与覆盖不同期间tmux我之前讨论过的会议。

5)我不确定这是否确实有必要,但我将以下内容添加到我的~/.bashrc(或~/.bash_profile其他)中。示例中还有一个带有更多注释/选项的版本。

## Function to be run every time one exits a bash terminal
finish()
{
  if [ ! -z $TMUX  ]; then
    $HOME/.tmux/plugins/tmux-logging/scripts/toggle_logging.sh
  fi
}

trap finish EXIT

短的 例子

在进行测试之前,您应该退出并重新启动终端,或者运行source ~/.bashrc(或获取您编辑的任何类似文件)。我更喜欢第二种方法,但如果您不确定~/.bash_profile~/bashrc等内容,最好重新启动。

编辑我有一个更长的例子,感觉比这个答案更像是矫枉过正。如果你真的想看的话,我已经截图了,附上。目前,页面 - p1、p2 和 p3 - 现在都指向www.google.comp1,p2, 和p3

我将不展示冗长的示例,而是仅展示一系列命令。对于我的真实日志,我在进入新tmux会话、窗口或窗格后运行了一些命令并发表了一些评论。最后,我将展示生成的文件。

我应该更详细地介绍一下我的系统。我通过 PuTTY 建立了与 RHEL8 计算机的 SSH 连接,这为我提供了一个主终端。从那里,我运行

$ tmux new -s mysession1

(这将打开会话:mysession1;窗口:1;和窗格:1。它还将启动日志文件mysession1-1-1.log。)

做了一些评论并按[Prefix]+后[w],这就是tmux终端的样子。

┌──────────────────────────────────────────────────────────────────────────────┐
│(0)  - mysession1: 1 windows (attached)                                       │
│(1)  └─> 1 bash* (1 panes) "bbd025@MACHINE: /home/bbd025"                     ┆
│┌ 1 (sort: index)────────────────────────────────────────────────────────────┐┆
││ bbd025@MACHINE:~                                                           ││
││ $ # I'm in tmux, and it looks like it's logging!                           ││
││ bbd025@MACHINE:~                                                           ││
││ $ # I'll press [Prefix]+[w] to see session info & then [ENTER] to get back ││
││ bbd025@MACHINE:~                                                           ││
││                                 ┌───┐                                      ││
││                                 │ 1 │                                      ││
││                                 └───┘                                      ││
│└────────────────────────────────────────────────────────────────────────────┘│
│[mysession1:bash*                  "bbd025@MACHINE: /home/bbd" HH:MM dd-mmm-yy│
└──────────────────────────────────────────────────────────────────────────────┘

[Prefix]+w调出您在上面看到的内容。要返回会话,请确保它突出显示(这是唯一的会话,因此您不必执行任何操作q),然后按ENTER

让我们分离会话并开始使用mysession2。抱歉,我在命令行中搞砸了,但我希望日志文件的大小正确

$ tmux detach-client -s mysession1

现在,我们回到非 tmux shell。尽管我显示了不同的代码块,但它替换了终端上的内容,同时仍位于同一终端位置。

$ tmux new -s mysession2

tmux出现的终端将有日志文件mysession2-1-1.log

此时,使用[Prefix]+w会弹出

(0)  - mysession1: 1 windows
(1)  └─> 1: bash* (1 panes) "bbd025@MACHINE: /home/bbd025"
(2)  - mysession2: 1 windows (attached)
(3)  └─> 1: bash* (1 panes) "bbd025@MACHINE: /home/bbd025"
$ tmux detach-client -s mysession2

让我们回到非 tmux shell,我们可以在其中杀死mysession2.

$ tmux kill-session -t mysession2

让我们尝试在 中打开另一个窗口mysession1,然后打开第二个窗口中的一个单独的窗格,看看日志如何结束。从非 tmux 终端开始。

tmux attach -t mysession1

您将看到您在原始窗格中输入的所有内容tmux new -s mysession1

$ tmux new-window -n second_window

tmux bash出现一个新的空白终端。这将有日志文件mysession1-2-1.log

$ tmux ls
mysession1: 2 windows (Created Mon Feb  28 12:02:06 2022) [80x29] (attached)
$ # I press [Prefix]+[n] to get to the next `tmux` window, i.e. the one with
$ #+ logfile, `mysession1-1-1.log`
$ tmux split-window -v # This is the same as [Prefix]+[%]

现在有两个终端 - 由一行破折号分隔 - 一个在另一个之上。底部终端有日志文件mysession1.1.2

$ tmux display-panes
$ # You'll have seen numbers on each pane. The bottom one should have
$ #+ shown '2'. If you want to make sure you are typing in pane 2, do
$ tmux select-pane -t 2
$ # You could also have done [Prefix]+[q]+[2]

从窗格 2 中,我们打开一个没有名称的新窗口。

$ tmux new -w

您现在位于带有 logfile 的 tmux 终端中0-1-1

现在,在之后tmux kill-server,让我们对日志文件进行最后的检查。

# In T0
$ ls -Ss1pq --block-size=1
total 28672
12288 mysession1-1-1.log
 4096 0-1-1.log
 4096 mysession1-1-2.log
 4096 mysession2-1-1.log
 4096 mysession1-2-1.log
$ ls -lAh
total 28K
-rw-r--r--. 1 bbd025 bbd025 1.3K Mar  8 12:03 0-1-1.log
-rw-r--r--. 1 bbd025 bbd025 8.5K Mar  8 11:49 mysession1-1-1.log
-rw-r--r--. 1 bbd025 bbd025  767 Mar  8 11:49 mysession1-1-2.log
-rw-r--r--. 1 bbd025 bbd025  648 Mar  8 11:49 mysession1-2-1.log
-rw-r--r--. 1 bbd025 bbd025  725 Mar  7 17:41 mysession2-1-1.log

笔记:

[1] 我们的新filename_suffix变量可能无法在tmux更新后继续存在。这样我就可以记住并有权访问更改,我会(在OP的情况下)将以下内容添加到我的~/.bash_profile

export MY_TMUX_FNAME_SUFFIX_LINE='filename_suffix="#{session_name}-#{window_index}-#{pane_index}.log"'

对于我的情况,我会添加以下内容。为了让事情变得更简单,我跳过了每行 80 个字符的规则。

export MY_TMUX_FNAME_SUFFIX_LINE='filename_suffix="bbd025-%s-#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S%z.log"'

现在,你基本上有了一个环境变量 - 可见

echo $MY_TMUX_FNAME_SUFFIX_LINE

您可以在将来的更新后查看tmux,这样您就知道如何保留为日志文件名称所做的个性化设置。

相关内容