1

I am trying to figure out a way to detect whether the current terminal/connection (and under a tmux session as well) is through mosh or not.

From this thread, I found which pseudo-terminal session I am currently on:

$ tty
/dev/pts/69

So, I need to some information of the process that spawned this pseudo-terminal, or owns this tty as a children. With the information, perhaps I might be able to determine whether it is from sshd or mosh. But how can I do that?

Another challenge: If the current shell is under tmux, the retrieved tty might not match the sshd/mosh-server information since tmux also allocates another pseudo-terminal. Regardless of how the tmux session was created, I'll need to distinguish my current connection is from SSH or mosh. How will it be possible?

Some trials:

(1) For SSH, it was possible to find the sshd process that matches the tty:

$ ps x | grep sshd | grep 'pts\/27'
 5270 ?        S      0:00 sshd: wookayin@pts/27

So I can know the current connection is through SSH. However, through mosh, I could not find any relevant information.

(2) Using environment variables like SSH_CLIENT or SSH_TTY might not work because both ssh/mosh set these variables, and it is even wrong inside a tmux session.

  • Using ps -p $PPID, I could detect the parent is mosh-server, tmux: server or sshd. However, tmux+mosh is still a complicated situation. – Jongwook Choi Oct 1 '17 at 23:26
1

I have come up with a decent solution to this, and wrapped it as a simple script: is_mosh:

#!/bin/bash

has_ancestor_mosh() {
    pstree -ps $1 | grep mosh-server
}

is_mosh() {
    # argument handling
    for arg in "$@"; do
        case $arg in
          -v|--verbose) local VERBOSE=YES ;;
          *) ;;
        esac
    done

    if [[ -n "$TMUX" ]]; then
        # current shell is under tmux
        local tmux_current_session=$(tmux display-message -p '#S')
        local tmux_client_id=$(tmux list-clients -t "${tmux_current_session}" -F '#{client_pid}')
        # echo $tmux_current_session $tmux_client_id
        local pid="$tmux_client_id"
    else
        local pid="$$"
    fi

    local mosh_found=$(has_ancestor_mosh $pid)   # or empty if not found
    if [[ -z "$mosh_found" ]]; then
        return 1;    # exit code 1: not mosh
    fi

    test -n "$VERBOSE" && echo "mosh"
    return 0;        # exit code 0: is mosh
}


sourced=0
if [ -n "$ZSH_EVAL_CONTEXT" ]; then
  case $ZSH_EVAL_CONTEXT in *:file) sourced=1;; esac
elif [ -n "$BASH_VERSION" ]; then
  [ "$0" != "$BASH_SOURCE" ] && sourced=1
else
  case ${0##*/} in sh|dash) sourced=1;; esac
fi
if [[ $sourced == 0 ]]; then
  is_mosh $@
fi

The idea is quite simple: (i) to find the tmux client that is attached to the current tmux session, and then (ii) to search its ancestor processes to find if there is a mosh process.

It might not be complete, depending on environments, but I could successfully detect and apply 24-bit color feature only if it's not running under mosh (as mosh doesn't support 24-bit colors). Here is a solution (add these lines to your ~/.vimrc):

" 24-bit true color: neovim 0.1.5+ / vim 7.4.1799+
" enable ONLY if TERM is set valid and it is NOT under mosh
function! s:is_mosh()
  let output = system("is_mosh -v")
  if v:shell_error
    return 0
  endif
  return !empty(l:output)
endfunction

function s:auto_termguicolors()
  if !(has("termguicolors"))
    return
  endif

  if (&term == 'xterm-256color' || &term == 'nvim') && !s:is_mosh()
    set termguicolors
  else
    set notermguicolors
  endif
endfunction
call s:auto_termguicolors()

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.