I have an infinite while loop bash script embedded in tmux status bar. In ~/.tmux/conf:

set -g status-right '... #(path/loop.sh) ...'

Tmux seems to run this script with sh -c. After tmux started:

$ ps x | grep loop.sh
23433 pts/4    S+     0:00 grep --color=auto loop.sh
31814 ?        S      0:00 sh -c path/loop.sh
31818 ?        S      0:00 /bin/bash path/loop.sh

tmux kill-session terminates the sh -c process. If I strace it and kill the session:

$ strace -p 31814
strace: Process 31814 attached
wait4(-1, 0x7ffeacbfbf9c, 0, NULL)      = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=27643, si_uid=1000} ---
+++ killed by SIGTERM +++

But the subshell is left untouched because of the infinite loop:

$ ps x | grep loop.sh
 2443 pts/4    S+     0:00 grep --color=auto loop.sh
31818 ?        S      0:00 /bin/bash path/loop.sh


I want the subshell to be terminated automatically after the tmux session ends. Is there a way to do this, by changing tmux settings or handling SIGTERM sent to the sh -c process?

(Edit: tmux version is 2.8)

  • This may have been fixed in tmux 2.7 or earlier, as a quick test showed my background script getting sighup. – meuh Mar 9 '19 at 21:01

Yes, child processes started with tmux -c "start process here" seem to survive the corresponding tmux sessions. I have pored over tmux' extensive man page and for a while I hoped that setting up a tmux command's after-hook globally could help. After-hooks have the following form:

 $ tmux set-hook -g after-session-closed your_cmd_here

where "your_cmd_here" could have been used to kill the child process generating your infinite loop. But it does not help that way, because "your_cmd_here" must in fact be a tmux cmd not a linux shell cmd.

Instead a quick hack would be to add a line inside the infinite loop of your /path/loop.sh script, such as:

 [ "x$(ps -e | grep tmux | grep -v grep)" = "x" ] && break

This will break you out of the infinite loop as soon as tmux does not show any active process in output of ps -ae. On the contrary, if a tmux related process shows then the loop continues unaffected.

Actually a better version of the above test, for the corner case where you would quit your tmux session(s), but sill have e.g. a man tmux process active on your system, is:

 [ $(\ps -e |  awk 'BEGIN {rv=0}; tolower($0) ~/tmux/ {if ($4 == "tmux") {rv=1}; exit} END {print rv}') == "1" ] && break
  • The above deals with cases when tmux appears in the output of \ps -e but not as the main process, i.e. not in position 4 on the output line of ps -e, but as an argument to a running process, or casually as a (sub-)string embedded in the output of \ps -e.
  • Note how I used the unadulterated form of ps by adding a backslash before the cmd as \ps. This is to prevent modified versions of the cmd to mess with positional parameter numbering in awk. E.g. if you used \ps -eF instead of \ps -e for instance, you would need to change $4 to $11.


| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.