43

I make heavy use of screen's "log" command to log the output of a session to a file, when I am making changes in a given environment. I searched through tmux's man page, but couldn't find an equivalent. Is anyone aware of a similar feature in tmux, or do I have to write my own wrapper scripts to do this?

EDIT: I'm aware of 'script' and other utilities that allow me to log a session. The reason that screen's functionality is so useful is the ability to define a logfile variable which uses string escapes to uniquely identify each session.

e.g. I have a shell function which, given a hostname, will SSH to that host in a new screen window and set the window title to the hostname. When I start a log of that session, it is prefixed with the window title.

If this functionality doesn't exist in tmux, I'll have to create a new set of shell functions to set up 'scripts' of sessions I want to log. This isn't hugely difficult, but it may not be worth the effort given that screen does exactly what I need already.

5 Answers 5

40

Let me see if I have deciphered your screen configuration correctly:

  • You use something like logfile "%t-screen.log" (probably in a .screenrc file) to configure the name of the log file that will be started later.
  • You use the title <hostname> (C-a A) screen command to set the title of a new window, or
    you do screen -t <hostname> ssh0 <hostname> to start a new screen session.
  • You use the C-a H (C-a :log) screen command to toggle logging to the configured file.

If so, then is nearly equivalent (requires tmux 1.3+ to support #W in the pipe-pane shell command; pipe-pane is available in tmux 1.0+):

  • In a configuration file (e.g. .tmux.conf):

    bind-key H pipe-pane -o "exec cat >>$HOME/'#W-tmux.log'"
    
  • Use tmux rename-window <hostname> (C-b ,) to rename an existing window, or
    use tmux new-window -n <hostname> 'ssh <hostname>' to start a new tmux window, or
    use tmux new-session -n <hostname> 'ssh <hostname>' to start a new tmux session.
  • Use C-b H to toggle the logging.

There is no notification that the log has been toggled, but you could add one if you wanted:

bind-key H pipe-pane -o "exec cat >>$HOME/'#W-tmux.log'" \; display-message 'Toggled logging to $HOME/#W-tmux.log'

Note: The above line is shown as if it were in a configuration file (either .tmux.conf or one you source). tmux needs to see both the backslash and the semicolon; if you want to configure this from the a shell (e.g. tmux bind-key …), then you will have to escape or quote both characters appropriately so that they are delivered to tmux intact. There does not seem to be a convenient way to show different messages for toggling on/off when using only a single binding (you might be able to rig something up with if-shell, but it would probably be ugly). If two bindings are acceptable, then try this:

bind-key H pipe-pane "exec cat >>$HOME/'#W-tmux.log'" \; display-message 'Started logging to $HOME/#W-tmux.log'
bind-key h pipe-pane \; display-message 'Ended logging to $HOME/#W-tmux.log'
8
  • Nice! That looks to do pretty much exactly what I need. Mar 30, 2011 at 19:16
  • Hrrm. So attempting to do this from the shell yields some issues. Any suggestions as to how to manage passing the entire line to tmux intact?" Mar 30, 2011 at 22:16
  • 2
    @KamilDziedzic: You might try including a tmux pipe-pane … command in your default-command (i.e. before starting a shell); of course that would only work for “default” panes (nothing started with explicit commands, e.g. new-window sqlite3). There have been hints that “hook” support might land in some future version of tmux; this might let you configure a command (e.g. pipe-pane …) to be automatically run after some other command new-session, new-window, or split-pane). Jul 12, 2013 at 22:34
  • 1
    @sebelk: If you consider an individual line to be an “entry” then you could use a shell’s read and date to arrange that. E.g. bind-key H pipe-pane -o 'exec bash -c "while IFS= read -r line; do echo \"\$(date +%%Y%%m%%dT%%H%%M%%SZ%%z): \$line\"; done" >>$HOME/"#W-tmux.log"' May 13, 2014 at 5:23
  • 1
    @ChrisJohnsen, ...that could made far more efficient if we knew bash was 4.1 or newer -- spawning a subshell to run a fresh copy of date for each line of output is going to be a serious performance hit! Much better to printf '%(%Y%m%dT%H%M%S)T: %s\n' "$line" (escaping as necessary for inclusion in a tmux config file, thus presumably doubling the %s and escaping the "s). May 4, 2015 at 22:37
9

Here's a tmux plugin that enables logging without messing with key bindings in .tmux.conf:

https://github.com/tmux-plugins/tmux-logging

Features:

  • prefix + P toggles pane logging. Output is cleared from unwanted ANSI characters!
  • prefix + Alt + P saves complete pane history to a file
4

After looking through the documentation for tmux, I can't find any equivalent of screen's window logging. It looks like you'd have to use your shell functions to do what you'd like, or just use screen. You can turn on debugging, which logs both the server and client side, but it also includes a lot of extraneous tmux-related logs as well, so it wouldn't exactly what you're asking for.

You could possibly use tmux's clipboard to automate saving the buffer to another session, which would be set up to accept the contents of the clipboard and save to a file. This seems kind of hackish.

1
  • 2
    That was my conclusion as well. I've decided to stick with screen for now, which is a shame, as other than this oversight, tmux seems pretty nice. Jan 21, 2011 at 16:30
1

i do it using script, this is from my tmux.conf file

bind ^C new-window "script -f /home/jcosta/mydocs/work/logs/$(date '+%d%m%Y_%H%M%S')_$$.log"
bind c new-window "script -f /home/jcosta/mydocs/work/logs/$( date '+%d%m%Y_%H%M%S')_$$.log"
bind | split-window "script -f /home/jcosta/mydocs/work/logs/$(date '+%d%m%Y_%H%M%S')_$$.log"
1
  • 1
    A poor replacement to screen's log command, which allows logging on the fly. But then if you are in tmux and want to use screen's logging, you have to start a new shell anyway.
    – Arcege
    Mar 28, 2011 at 21:23
1

You can use the pipe-pane command after the tmux prefix (with the default prefix, this would be CTRL+b:pipe-pane).

Example 1

The example found here will overwrite the target file (in this case, myfile):

pipe-pane "cat >myfile"

Example 2

The example in the tmux manual will bind a key combo to toggle logging and to append to the specified file instead of overwriting it:

The -o option only opens a new pipe if no previous pipe exists, allowing a pipe to be toggled with a single key, for example:

bind-key C-p pipe-pane -o 'cat >>~/output.#I-#P'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .