1

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

Question

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)

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

1 Answer 1

1

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.

HTH.

You must log in to answer this question.

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