bashtmuxmosh

mosh: sources .bashrc twice with different PIDs


I use tmux in my build server. Recently I wrote a small .bashrc script that will automate attaching to tmux session if one exits. The script looks like follows

# Automate tmux Startup                                                                                                                                                                                     
if [ -z "$TMUX" ]; then                                                                                                                                                                                     
    # we're not in a tmux session                                                                                                                                                                           
   if [ `ps -o comm= -p $PPID` == "sshd" ]; then                                                                                                                                                            
        # even VNC can have $SSH_TTY and $SSH_CONNECTION set so we cant find out                                                                                                                            
        # if we want to attach to tmux during ssh so we need to see if parent                                                                                                                               
        # process is sshd see                                                                                                                                                                                                                                                                                                  
        # http://unix.stackexchange.com/questions/145780/linux-ssh-connection-is-set-even-  without-sshing-to-the-server                                                                                      
        # Only attach to tmux if its me                                                                                                                                                                     
        WHOAMI=$(whoami)                                                                                                                                                                                    
        if tmux has-session -t $WHOAMI 2>/dev/null; then                                                                                                                                                    
            tmux -2 attach-session -t $WHOAMI                                                                                                                                                                                                                                                                                                        
        else                                                                                                                                                                                                
           echo "Start tmux with username as session name 'tmux new -s $WHOAMI' "                                                                                                                          
        fi                                                                                                                                                                                                  
     fi #parent process check                                                                                                                                                                                
else                                                                                                                                                                                                        
   echo "Inside tmux"                                                                                                                                                                                       
fi 

The problem is whenever I ssh using mosh it just hangs inside the tmux window. I found that if I remove this script and then use mosh to just ssh and attach to tmux manually then I don't hit on this issue. This issue only happens if I place the above script in .bashrc.

My suspicion was that mosh is waiting for .bashrc to complete and waits for it indefinitely and in the mean time it also does not pass the mouse and keystroke controls over to tmux. I confirmed this by killing the tmux session from another terminal and found that mosh recovered and tried to execute my previously buffered keystrokes.

The strange thing is that how mosh managed to cross the ps -o comm= -p $PPID == "sshd" check. This is because for mosh the Process name of shell is bash and Parent process name of the shell is mosh-server and not sshd. Further investigation revealed that mosh executes .bashrc twice once as sshd and once as mosh-server. This is reproducible by putting ps -o comm= -p $PID -p $$ >> moshbash in .bashrc.My tmux attach was happening in sshd and hanging mosh forever.

A simple workaround I found was to do

mosh user@server -- tmux attach -t `whoami`

I can do a similar thing to my ssh as well to fire command from the client side and eliminate the .bashrc script altogether but I do not wish to spill over my server side automation to the client side.

Actually mosh does not seem to be wrong. It is sourcing a .bashrc file only once per PID .I think it is a bad design to have .bashrc kick of a blocking session to tmux since tmux also needs terminal we cant start off as a background process either so & also wont work. Is there any other way around this problem ? I think if we can distingusih between a mosh client setting up a sshd and a ssh client setting up sshd that information can be used.


Solution

  • .bashrc always executes everytime an interactive non-login bash instantiates so use .bash_profile instead so it would only run once during login to ssh. If the script or processes of the script summons bash, it would cause repeated summoning.

    See Bash Startup Files for more info and other startup files.