Alert in tmux when a process completes - tmux

Can I set tmux to trigger an alert in a non-active window when a process completes?
For example: I start a long build process. I would like to be notified when it completes, not each time it prints a status.

I'm surprised this answer hasn't been given yet: You can use the tmux window setting visual-bell for this. With bell-action you can then configure whether you want to see bells for the current window only, or for non-current window only (other). Personally I prefer the second, as you won't see noise generated by the shell, and you probably don't care about the notification if it's in the current window.
set-window-option -g visual-bell on
set-window-option -g bell-action other
When a process generates a bell, tmux will highlight the the title of the window that rings the bell as well as show a "Bell in window X" notification.
Then ring the bell at the end of the process. E.g.:
make; echo -e '\a'
(or && || instead of ; if you want to ring only on success or failure respectively)

There 3 solutions I know, none really ideal. You may put those commands in your ~/.tmux.conf or just run them directly as Tmux command via Ctrl-B :.
Monitor and alert whenever the output changes (you may then redirect output somewhere else so that output changes only after the command is complete):
:set -g visual-activity on
:setw -g monitor-activity on
Monitor and alert whenever the output did not change for a while (30 seconds here):
:set -g visual-silence on
:setw -g monitor-silence 30
(deprecated and someday replaced by a better option) Monitor and alert whevener the output contains a string matching given pattern (and possibly run your command like my-command; echo foobar):
:set -g visual-content on
:setw -g monitor-content foo*bar
$ some-command; tmux display-message "Task 1 done". However the message will only show for a short duration defined via :set -g display-time 4000.
If you keep the visual-* to off (default), it'll only highlight the name of the window in which the alert occurred without showing a global alert status message.
For details about each of these settings, see tmux man page
Updated (thanks for Steven Lu)

I finally found a solution that works for me. I use zsh for my shell, which has a feature called "Hook Functions" -- shell functions that execute on certain actions: http://zsh.sourceforge.net/Doc/Release/Functions.html.
It's likely other shells have a similar feature.
The hook function I use is precmd, which is executed each time the prompt is shown. ie, when a command has just finished running.
In my .zshrc:
precmd () {
echo -n -e "\a"
}
This sends a bell to tmux, which causes it to highlight just the window that the command was running in.
If you are already focused on that tmux window, this does nothing because the bell is immediately cleared.
The benefit of this approach is that it does not trigger on all visual activity. It only triggers when a command completes.

you can wrap your running script with a && bash derivative which will call a tmux command to notify you.
using && means you will only get notified when the script exits with error code 0. if you want it to notify you anyway, just use ;
as for the tmux commands to wrap the script, have a look at those bunch, they should suffice
select-window
split-window -h 'exec echo...'
send-keys

For future reference, people can also checkout the tmux-notify plugin, created by ChanderG, which was designed for this purpose.
Disclaimer: I'm a contributor to this plugin. Feel free to check it out and open an issue/pull request or feature request if you find a bug or see something that is missing.

there are two options:
set -g visual-activity on
setw -g monitor-activity on
have you tried setting them in your tmux.conf?

As a good workaround, you can use:
https://github.com/tcreech/tmux-notifications
You simply do:
$ command ; tmux-notify
You will get a nice notification in the status-bar (if enabled)

Building on #psp940's answer (where StackOverflow won't let me add a comment):
precmd () {
echo -n -e "\a" >$TTY
}
If you're using powerlevel10k's instant prompt feature, redirecting the bell directly to the terminal avoids a warning about pre-init console output. See also here.

Adding onto the answers from #wump and #psp940; I've found that the simplest way to be alerted any time a command completes is to put a bell in your PS1:
in tmux.conf
set-window-option -g visual-bell on
set-window-option -g bell-action other
In your .bashrc:
# ring bell every time a command completes
export PS1+=$'\[\a\]'
I'm not sure whether the += and $'' are bash-isms, but the principle will work in any shell.
The surrounding \[+\] tell your shell that the characters between them are zero-width

Related

Sequence of keypresses crashes tmux

When I type C-b : to get to the command prompt, hitting escape and then quickly hitting any (or most) other key will cause tmux to indefinitely pause on the status bar. If you press enter, you can get back to tmux, but if you pres any two alphanumeric keys will cause the tmux server to crash. I have tried this on both set -g status-keys vi and set -g status-keys emacs as well as set -o vi and set -o emacs in bash. None of them seem to have an effect. I got my coworker to replicate this on his machine, so it doesn't seem like it's only me. What's up?
Seems to be fixed in the very newly released (11 hours ago) tmux 3.3!

Is it possible to quit tmux, while "keeping" the window in the terminal

Use case
I run command over a bastion in SSH and since the connection can be dropped we are using tmux or screen.
For short commands I'm using send-keys, let's say I'm using a command like kubectl get pods. I'd like to keep the output of this command but terminate the tmux session.
Using remain-on-exit is not what I'm looking for as it keeps a dead window.
I've seen those question already
https://unix.stackexchange.com/questions/17116/prevent-pane-window-from-closing-when-command-completes-tmux
TMUX: how to make new window stay when start shell-command quits?
I'd like to keep the output of this command but terminate the tmux session.
I use this in my ~/.tmux.conf, and now when I exit my running shell, pane output is saved to unique log file:
set -g remain-on-exit
set-hook pane-died 'capture-pane -S - -E - ; save-buffer "$HOME/logs/tmux/tmux-saved.#{host_short}-#{session_id}:#{window_id}:#{pane_id}-#{pane_pid}-#{client_activity}.log"; delete-buffer; kill-pane'
I'm not sure it's exactly what you are looking for, but you could use the capture-pane command to save the contents of a pane (subject to what is still in the pane's history) to a file.

Getting command running in a tmux pane

Is there a way to show the command which is currently running at a tmux pane?
I tried 'history', but it does not seem to show the commands which I had executed at tmux.
I also tried 'ps -ef', but it does not show the full command in the case like "./a.sh ; ./b.sh"
I found several answers online that include ps ... | tail -1. Unfortunately, these don't always work because sometimes the order of the commands is swapped, e.g. for two separate panes I get:
$ ps -t /dev/pts/12 -o args=
-bash
mpv some_movie.mp4
$ ps -t /dev/pts/10 -o args=
micro some_file.txt
-bash
I really wanted a single line of output so that I could show it in the status bar, but what I ultimately ended up going with is ps --forest via run-shell. It seems to always reliably show the correct order and with more information should there be nested commands running (e.g. via a bash script). Its output looks like:
$ ps --forest -o args -g $$
COMMAND
-bash
\_ ps --forest -o args -g 1695
Solution
So in my .tmux.conf, I've got:
bind '`' run-shell 'ps --forest -o pid,args -g #{pane_pid}'
It will replace the contents of your pane with the output from the ps --forest command. Once you type esc or ^C, the ps output disappears, and your pane goes back to whatever it was doing :) Ends up looking like:
running script.sh, which calls other-script.sh, which sleeps for 30s
viewing pane process tree via keybinding
(Old question but for future reference)
Try: tmux list-panes -t <your_pane_name> -F '#{pane_current_command}'
https://man7.org/linux/man-pages/man1/tmux.1.html#FORMATS
Try setting pane-border-status to bottom or top in your configuration file, with the tmux command prompt or just running tmux set pane-border-status bottom. Borders should appear around the panes and info about the current process appears much like in a regular terminal window's title bar.
I suspect the command wasn't written to the history file as the shell with the stuck/long-running job wasn't done yet.
You might try pstree -U to see process in their parent/child tree.

tmux - Environment variables don't show up in session

I'm trying to move from screen to tmux (to eventually using tmux from within byobu). However, I have a severe problem with environment variables not being applied, especially PS1. None of them get copied to the session (or window) environments. I found this thread that seemed relevant:
How do I start tmux with my current environment?
However, I actually can see all my right variables when I do
:show-environment -g
But none of them get carried over to the session environment, so I don't see anything when I do
:show-environment
I do have the right update-environment statement in my ~/.tmuxrc file:
# start a non-login shell by default for each new window
set -g default-command 'bash'
# Prefix is C-a like in screen
unbind C-b
set -g prefix C-a
# Carry over the PS1
set-option -ga update-environment "PS1"
Frankly this all seems like a mess to me. I can see the benefit of starting from a clean session for each screen, but for the most part this seems like a pain. I export the variable I intend to use in sub-processes, such as as the Python virtualenvwrapper functions, and expect them to be available.
Is there a way to disable this behavior? If not, what should I try to carry over my PS1 variable to tmux?
EDIT 11/13/2013
I realized that removing the first line (default-command bash) does carry over all of the environment variables. However, I really don't want each new screen of tmux to launch as a login shell. For instance, I specifically declared my PS1 variable in a login shell, so that it wouldn't be overwritten whenever I open a new screen.
Based on the following post, every new screen in tmux should launch as a non-login shell:
https://superuser.com/questions/614277/profile-and-bash-profile-ignored-when-starting-tmux-from-bashrc
Why is this not happening by default for me?
Tmux cannot update running processes (e.g. bash), it can only update its own environment. If you were to start a new window/pane it would pick up the new environment. My suggestion would be to use a utility function like this:
#!/bin/bash
tmup ()
{
echo -n "Updating to latest tmux environment...";
export IFS=",";
for line in $(tmux showenv -t $(tmux display -p "#S") | tr "\n" ",");
do
if [[ $line == -* ]]; then
unset $(echo $line | cut -c2-);
else
export $line;
fi;
done;
unset IFS;
echo "Done"
}
This goes through all the updated environment that tmux has learned about and updates your shell.

"tmux set -g mouse-mode on" not scrolling

To allow scrolling a tmux pane with a mouse, I put the following in my ~/.tmux.conf file:
set -g mouse-mode on
However, nothing changes. When I scroll, it still scrolls outside of tmux. Why is this?
So this option has been renamed in version 2.1 (18 October 2015)
From the changelog:
Mouse-mode has been rewritten. There's now no longer options for:
- mouse-resize-pane
- mouse-select-pane
- mouse-select-window
- mode-mouse
Instead there is just one option: 'mouse' which turns on mouse support
So this is what I'm using now in my .tmux.conf file
set -g mouse on
As #Graham42 noted, mouse option has changed in version 2.1. Scrolling now requires for you to enter copy mode first. To enable scrolling almost identical to how it was before 2.1 add following to your .tmux.conf.
set-option -g mouse on
# make scrolling with wheels work
bind -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'select-pane -t=; copy-mode -e; send-keys -M'"
bind -n WheelDownPane select-pane -t= \; send-keys -M
This will enable scrolling on hover over a pane and you will be able to scroll that pane line by line.
Source: https://groups.google.com/d/msg/tmux-users/TRwPgEOVqho/Ck_oth_SDgAJ
Just a quick heads-up to anyone else who is losing their mind right now:
https://github.com/tmux/tmux/blob/310f0a960ca64fa3809545badc629c0c166c6cd2/CHANGES#L12
So that's just
:setw -g mouse
this should work:
setw -g mode-mouse on
then resource then config file
tmux source-file ~/.tmux.conf
or kill the server
Paste here in ~/.tmux.conf
set -g mouse on
and run on terminal
tmux source-file ~/.tmux.conf
As #Graham42 said, from version 2.1 mouse options has been renamed but you can use the mouse with any version of tmux adding this to your ~/.tmux.conf:
Bash shells:
is_pre_2_1="[[ $(tmux -V | cut -d' ' -f2) < 2.1 ]] && echo true || echo false"
if-shell "$is_pre_2_1" "setw -g mode-mouse on; set -g mouse-resize-pane on;\
set -g mouse-select-pane on; set -g mouse-select-window on" "set -g mouse on"
Sh (Bourne shell) shells:
is_pre_2_1="tmux -V | cut -d' ' -f2 | awk '{print ($0 < 2.1) ? "true" : "false"}'"
if-shell "$is_pre_2_1" "setw -g mode-mouse on; set -g mouse-resize-pane on;\
set -g mouse-select-pane on; set -g mouse-select-window on" "set -g mouse on"
Hope this helps
You can still using the devil logic of setting options depending on your current Tmux version: see my previous answer.
But since Tmux v1.7, set-option adds "-q" to silence errors and not print out anything (see changelog).
I recommend to use this feature, it's more readable and easily expandable.
Add this to your ~/.tmux.conf:
# from v2.1
set -gq mouse on
# before v2.1
set -gq mode-mouse on
set -gq mouse-resize-pane on
set -gq mouse-select-pane on
set -gq mouse-select-window on
Restar tmux or source-file your new .tmux.conf
Side note: I'm open to remove my old answer if people prefer this one
This line:
set -g mouse-mode on
in your ~/.tmux.conf file won't work.
For one thing, the proper setting is not mouse-mode, but mode-mouse.
Second, it only works on older versions of tmux (pre-version 2; you can run tmux -V to see what version you have, but you can also run man tmux to see if mode-mouse is a supported option).
And third, technically man tmux says to use the mode-mouse option with setw (set-window-option) and not with set (set-option), although I've seen it work with set (as well as setw).
These lines should work:
If your version of tmux is recent enough (that is, if tmux -V shows version 2 or newer), you can put this line in your ~/.tmux.conf file:
set-option -g mouse on
But if you use an older version of tmux, put these lines in your ~/.tmux.conf file:
set-window-option -g mode-mouse on
set-option -g mouse-resize-pane on
set-option -g mouse-select-pane on
set-option -g mouse-select-window on
Again, if you're not absolutely sure which line(s) to put in your ~/.tmux.conf file, run man tmux and search for mouse-mode, mouse-resize-pane, mouse-select-pane, and/or mouse-select-window. If you find them, then use those options (the ones for the older version of tmux).
Putting these lines in will allow you to use the mouse scroll wheel, it will allow you click on various panes to activate them, and it will allow you to resize panes just by clicking-and-dragging on their splitter separator.
You can also copy-and-paste using your mouse. However, you may notice that copying-and-pasting with your mouse may not work like it normally does on your console. To work around this, I've noticed that holding down the SHIFT key while using your mouse's copy/paste abilities makes them work normally again. (On MacOS, fn seems to work for me better than SHIFT.) Or you can learn tmux's approach to copy-and-pasting (which I do recommend).
A note on using tmux's native ability to copy/select/paste:
Personally, I feel that the vi keys make more sense to me than the default emacs keys (for example, it feels more natural to exit selection mode with vi mode's ENTER than with emacs mode's CTRL+w or ALT+w), so I have this in my ~/.tmux.conf file:
# For vi-like keys in copy/paste/selection mode:
set-window-option -g mode-keys vi
However, I've noticed that on older versions on tmux, this line won't work, unless I've also included the line:
set-window-option -g mode-mouse on
Good to know: Occasionally, when you're using the mouse's scroll wheel, you'll discover that your pane/screen appears to be frozen or locked up (it won't respond to keyboard input), and it's not clear what to do to unlock it.
It's not locked up. You're likely in tmux's selection mode. To get out of it, try one of these:
Hit ENTER. (Will likely work in vi mode.)
Hit ALT+w. (Will likely work in emacs mode.)
Hit CTRL+w. (Will likely work in emacs mode.)
Hit META+w. (Will likely work in emacs mode.)
Hit Esc. (Will likely work in emacs mode.)
Hit q. (Will likely work in vi mode, and may work in emacs mode as well.)
Ultimately, you can try hitting:
CTRL+w     ENTER
or:
Esc     q
Chances are, that will put you back in the normal mode where your keyboard is responsive again.
Using the mouse with vim:
I've discovered that putting this line in my ~/.vimrc file:
:set mouse=a
seems to work well with tmux, better than this line:
:set mouse=r
I can't really explain the difference; if you're a vim user, try them out and see which setting works best for you.
If you need to test out these tmux options, you may find yourself editing your ~/.tmux.conf file, exiting tmux, and then restarting tmux. This can become a tedious process, so if you want some work-arounds, here are some options:
Option1: After editing (and saving) your ~/.tmux.conf file, run this command (while in tmux):
CTRL+B :source-file ~/.tmux.conf ENTER
This will immediately apply the new settings in your ~/.tmux.conf file into your current tmux session, without the need to restart tmux.
Option 2: If you're in a tmux session, you can turn on/off options temporarily just for that session by running commands like these at the Unix shell prompt:
tmux set-option -g mouse on
tmux set-window-option -g mode-keys vi
Option 3: You can also temporarily turn on/off options in a tmux session with:
CTRL+B :set-option -g mouse on ENTER
CTRL+B :set-window-option -g mode-keys vi ENTER
Good luck, and have fun using tmux !
Try this. It works on my computer.
set -g mouse on
Ctrl + B and then set mouse. -g is not needed anymore.

Resources