how to scroll to beginning/end of scroll buffer in tmux? - scroll

^b+page up/down scrolls up/down one page of scroll buffer, but how do we scroll to beginning ?
like wise with end (besides pressing ^C to kill scrolling)

this depends on the binding of "mode-keys". If you "set-option -g mode-keys emacs" (actually, this is the default settings), then you can go to the beginning and the end of the buffer using corresponding emacs keys.
Enter the copy mode using: ctrl-b + [
Go to the beginning using: Alt + shift + , (or, in emacs' notation: M-<)
Similarly, going to the end is achieved by M->
HOW TO TEST
Please note that configuration in ~/.tmux.conf only takes effect after the tmux server restarts. That is when you kill all sessions and then restart tmux.
In fact, however, there is simpler way to test: just run the following command at command line:
tmux set-option -g mode-keys emacs
I don't think there is a way change only one key. But you do have the choice to
tmux set-option -g mode-keys vi
You should be able move around in copy mode using h j k l etc.

You can use like:
bind-key -T copy-mode C-S-Home send -X history-top # Ctrl+Shift+Home
bind-key -T copy-mode C-S-End send -X history-bottom # Ctrl+Shift+End
This way when you are in copy mode Ctrl+Shift+Home will take you to the beginning of scroll buffer and Ctrl+Shift+End will take you to the end of scroll buffer.

Related

bind source-file in tmux on startup from bash

I have a .tmux.conf file which binds a set of further tmux instructions when I press the correct keys (in this case, Ctrl + b followed by 'k'):
bind k source-file ~/.tmux/myfile
When I go into my tmux terminal and press Ctrl + b followed by k, it works fine, and the script in myfile runs as expected. I'm now trying to launch this all using a command in my .bashrc file by sending the keys to the tmux session once it has launched:
launch_things() {
tmux new-session -d -s mysession
tmux send-keys -t mysession C-b k
tmux a -t mysession
}
However, this doesn't work. It's starting the tmux session, apparently benting the keys to it, then attaching to the session. I'm not sure if it's because I've done something wrong with the sending of the keys, or if it's not possible to send combinations of keys like this. Note that I can see the letter k on the screen when I attach, so the send-keys functionality is doing something.
Can anyone either tell me what I'm doing wrong, or suggest another way to launch my bound source-file (~/.tmux/myfile) from my bash script please?
P.S. I'm running Ubuntu 16.04 if that makes a difference.
It seems that send-keys when sending strings does not try to interpret them for the prefix character. There is the command send-prefix but that behaves in the same way.
So the simple answer is to do tmux source-file ~/.tmux/myfile or perhaps the longer
tmux attach-session -t mysession\; source-file ~/.tmux/myfile\; detach-client

How to clear bell state from all tmux windows

I help maintain a large number of Unix-like servers, and so keep a script called tmux-rebuild that I use to rebuild all the tmux sessions and windows with SSH links to each server.
I have tmux configured to show the window's name in red with an exclamation mark in its status bar when a terminal bell character is printed in that window. This is very handy for programs like irssi alerting me to when I have messages in another window.
I also have my $PS1 set up on every server to print a terminal bell at the end of every prompt. This is useful because if I run a long job in one window and switch to another, I can immediately see when it's finished because when my prompt is written to the screen after the job is done, tmux makes the window name come up in red with an exclamation mark. This is great for my workflow.
However it causes a slight problem with the rebuild script mentioned above, because when I start up tmux after running it, every window in every session is flagged in red, due to the first prompt being printed to the screen. This makes the feature useless until I visit every window, and there are something like 40-50 of them.
Is there something I can add to my script that will clear all alerts from sessions and windows after they are created? I don't mind using a kludge if necessary.
From the tmux man page, specifically the last sentence here:
kill-session [-aC] [-t target-session]
Destroy the given session, closing any windows linked to it
and no other sessions, and detaching all clients attached
to it. If -a is given, all sessions but the specified one is
killed. The -C flag clears alerts (bell, activity, or
silence) in all windows linked to the session.
So, simply:
tmux kill-session -C
Figured out an acceptable workaround; I redefined the next/previous bindings to allow repeats:
# Allow repeats for next/prev window
bind-key -r n next-window
bind-key -r p previous-window
This allows me to quickly sweep up the alerts for all windows in a session by pressing my prefix key and tapping "n" until they're all clear, and I'm back in my original window.
With tmux 1.6 (and later), list-windows can generate customizable output, so it is fairly simple to read the output lines and make a loop that runs select-window for each window.
Add list-session (to loop over all sessions, optionally), and display-message (to parse session specifiers, and to record the current/“last” windows so they can be properly restored), and you might end up with something like this:
#!/bin/sh
# usage: tmux-select-each [session [...]]
#
# Select every window in specified session(s). If no sessions are
# specified, process all windows in all sessions.
#
# This can be handy for clearing the activity flags of windows in
# freshly spawned sessions.
if test $# -gt 0; then
for session; do
tmux display-message -p -t "$session:" '#S'
done
else
tmux list-sessions -F '#{session_name}'
fi |
while read -r session; do
active_window=$(tmux display-message -p -t "$session:" '#S:#I')
last_window=$(tmux display-message -p -t "$session:"\! '#S:#I' 2>/dev/null)
tmux list-windows -t "$session" -F '#{session_name}:#{window_index}' |
while read -r window; do
if test "$window" = "$active_window" ||
test "$window" = "$last_window"; then
continue
fi
tmux select-window -t "$window"
done
if [ -n "$last_window" ]; then
tmux select-window -t "$last_window"
fi
tmux select-window -t "$active_window"
done

GNU screen: Launch command in session without changing window to it

We have an attended-upgrade script which launches apt-get update && apt-get upgrade simultaneously on all our administered systems. Ideally, we'd want to launch them all inside a screen session. When I do it like this:
File: upgrade.sh
for host in $ALLHOSTS
do
some_commands_which_take_considerable_time
screen -X screen sh -c "ssh $host \"apt-get update && apt-get upgrade\""
done
$ screen ./upgrade.sh
, it works, but as there are new windows arriving on the session, they are automatically being switched to. Instead, I'd rather have a version where the active window is fixed unless contained process quits or I switch manually using ^A n.
Bonus points if there is a possibility to preserve windows with exited processes, but keeping them separate from windows with active processes.
You can do this with tmux. For example:
# Start a session named "apt-get" and leave it running in the background.
tmux session-new -d -s apt-get
# Preserve windows with inactive processes.
tmux set-option -t apt-get set-remain-on-exit on
# Start a new window without switching to it. You can also do this from
# within a running tmux session, not just outside of it.
tmux new-window -d -t apt-get -n upgrade-$host \
"ssh $host 'apt-get update && apt-get upgrade'"
Note that you can have multiple windows with the same name, or modify the argument to the -n flag for unique names. The tmux application doesn't care.
As an example, you could name each window "upgrade," but that would make it difficult to identify your SSH sessions at a glance. Instead, this example appends the value of the host variable (populated by your for-loop) to each window name. This makes it easier to navigate, or to programmatically close windows you are no longer interested in. This is especially valuable when you have a lot of unclosed windows displaying terminated processes.
Overall, the syntax is a little cleaner and more intuitive than GNU screen's for this sort of task, but your mileage may vary.
W/r/t preserving windows after a subprocess exits, one possibility is to invoke the zombie command in your screen config file(s), which requires that you specify two keyboard characters that kill or resurrect the window, respectively. E.g.:
zombie KR
Then, K would kill a window whose subprocess has terminated, while R would attempt to relaunch the subprocess in the same window. Note that, in a zombie window, those keys are captured at the top level (i.e., do not precede them with your normal screen control character prefix sequence).
In order to prevent automatic switching to a newly created window, try altering your invocation of screen to something like the following:
screen -X eval 'screen sh -c "ssh $host \"apt-get update && apt-get upgrade\""' 'other'
Thanks to CodeGnome, I'll probably go with tmux as I believe there is no way to do it with screen (that's unfortunate, really!).
To give a better sketch of how it can be used:
#!/bin/sh
tmux new-session -d -s active
tmux new-session -d -s inactive
tmux set-option -t active set-remain-on-exit on
for host in $ALLHOSTS
do
tmux new-window -d -t active: -n upgrade-$host "
./do_upgrade_stuff.sh $host
tmux move-window -s active:upgrade-$host -t inactive:
"
done

How to send commands when opening a tmux session inside another tmux session?

A typical situation may be:
$ tmux
[0] $ ssh example.com
$ tmux attach
[0] $
I open a tmux session, then ssh in to a server and attach to an existing tmux session. At this point I have one tmux session inside another. How do I send commands to the inner tmux session?
Note: Both tmux sessions have the same key bindings.
The send-prefix command can be used to send your prefix keystroke to (the process running in) the active pane. By default, the prefix is C-b and C-b is bound to send-prefix (so that hitting it twice sends a single C-b to the active pane). This is just what we need to access the bindings of the inner tmux instance.
The first C-b is captured by the “outer” tmux instance as its prefix key. The second one is captured by the “outer” tmux instance and triggers its C-b binding (send-prefix). This sends a C-b to the outer instance’s active pane. The process running in this pane is (ultimately, through an ssh instance) the “inner” tmux instance. It captures the C-b as its prefix key. Now your next keystroke will be passed through the outer tmux instance and captured by the inner one to trigger a binding.
To trigger the c binding (new-window) in a second-level instance of tmux, you would type C-b C-b c. For a third-level instance of tmux you would type C-b C-b C-b C-b c.
This doubling for each level can be annoying if you are commonly dealing with multiple layers of tmux. If you can spare some other key, you could make a non-prefixed binding to make things (possibly) easier to type:
bind-key -n C-\ send-prefix
bind-key -n C-^ send-prefix \; send-prefix
Create new window in second-level tmux: C-\ c
Create new window in third-level tmux: C-^ c (or C-\ C-\ c)
If you have a limited number of tmux commands that you want to (easily) send to the lower-level tmux instances, you might instead use send-keys to create some specific bindings (possibly just in your top-level tmux instance):
bind-key C-c send-keys C-b c
bind-key C send-keys C-b C-b c
Create new window in second-level tmux: C-b C-c
Create new window in third-level tmux: C-b C
To access the inner, hold control and hit B twice.
EDIT:
I do NOT recommend use C-q as a bind-key, as it is a default control-key command for
un-freezes the screen and lets screen display continue
A situation happens here, and #Paschalis provides a solution:
if it happens to be twice unlucky (a remote tmux session with C-q as prefix): Type Cltr-q, then :, and enter in tmux: send-keys C-q
Below it is the answer:
To make it simple, add the below line in your ~/.tmux.conf
bind-key -n C-q send-prefix
Then you can directly use C-q as bind-key for your remote tmux.

How do I terminate a window in tmux?

How do I terminate a window in tmux? Like the Ctrlak shortcut in screen, where Ctrla is the prefix.
try Prefix + &
if you have
bind q killp
in your .tmux.conf, you can press Prefix + q to kill the window too, only if there is only one panel in that window.
if you have multiple panes and want to kill the whole window at once use killw instead of killp in your config.
the default of Prefix above is Ctrl+b,
so to terminate window by default you can use Ctrl+b &
<Prefix> & for killing a window
<Prefix> x for killing a pane
If there is only one pane (i.e. the window is not split into multiple panes, <Prefix> x would kill the window)
As always iterated, <Prefix> is generally CTRL+b. (I think for beginner questions, we can just say CTRL+b all the time, and not talk about prefix at all, but anyway :) )
Generally:
tmux kill-window -t window-number
So for example, if you are in window 1 and you want to kill window 9:
tmux kill-window -t 9
For me solution looks like:
ctrl+b q to show pane numbers.
ctrl+b x to kill pane.
Killing last pane will kill window.
Kent's response fully answered your question, however if you are looking to change tmux's configuration to be similar to GNU Screen, here's a tmux.conf that I've used to accomplish this:
# Prefix key
set -g prefix C-a
unbind C-b
bind C-a send-prefix
# Keys
bind k confirm kill-window
bind K confirm kill-server
bind % split-window -h
bind : split-window -v
bind < resize-pane -L 1
bind > resize-pane -R 1
bind - resize-pane -D 1
bind + resize-pane -U 1
bind . command-prompt
bind a last-window
bind space command-prompt -p index "select-window"
bind r source-file ~/.tmux.conf
# Options
set -g bell-action none
set -g set-titles on
set -g set-titles-string "tmux (#I:#W)"
set -g base-index 1
set -g status-left ""
set -g status-left-attr bold
set -g status-right "tmux"
set -g pane-active-border-bg black
set -g pane-active-border-fg black
set -g default-terminal "screen-256color"
# Window options
setw -g monitor-activity off
setw -g automatic-rename off
# Colors
setw -g window-status-current-fg colour191
set -g status-bg default
set -g status-fg white
set -g message-bg default
set -g message-fg colour191
If you just want to do it once, without adding a shortcut, you can always type
<prefix>
:
kill-window
<enter>
ctrl + d kills a window in linux terminal, also works in tmux.
This is kind of a approach.
Lot's of different ways to do this, but my favorite is simply typing 'exit' on the bash prompt.
While you asked how to kill a window resp. pane, I often wouldn't want to kill it but simply to get it back to a working state (the layout of panes is of importance to me, killing a pane destroys it so I must recreate it); tmux provides the respawn commands to that effect: respawn-pane resp. respawn-window. Just that people like me may find this solution here.
By default
<Prefix> & for killing a window
<Prefix> x for killing a pane
And you can add config info
vi ~/.tmux.conf
bind-key X kill-session
then
<Prefix> X for killing a session
I can confirm following working on tmux running in ssh via Windows Command:
Copy: Press shift, select using mouse, press Ctrl+Shift+C
Paste: Shift+Right click
No special settings were needed.

Resources