Detecting SSH Sessions in Bash: Robust Methods for Environment-Aware Shell Configuration


2 views

When developing portable bash configurations across multiple machines, session context detection becomes crucial. The primary issue arises when environment variables like SSH_CLIENT get stripped during privilege escalation or shell transitions. Here's a comprehensive approach to robust SSH session detection.

The most reliable approach examines several SSH-related environment variables:


if [ -n "$SSH_CONNECTION" ] || [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
    IS_SSH_SESSION=true
else
    case $(ps -o comm= -p $PPID 2>/dev/null) in
        sshd|*/sshd) IS_SSH_SESSION=true;;
    esac
fi

When environment variables aren't available, we can examine the process tree:


is_ssh_session() {
    # Check if we're in a tmux/screen session first
    if [ -n "$TMUX" ] || [ -n "$STY" ]; then
        pstree -s $$ | grep -q sshd
        return $?
    else
        # Direct SSH session check
        [ -n "$SSH_TTY" ] || ps -o comm= -p $PPID | grep -q sshd
    fi
}

To maintain SSH detection across sudo sessions without preserving the entire environment:


check_ssh_origin() {
    local pid=$$
    while [ $pid -ne 1 ]; do
        if ps -p $pid -o comm= | grep -q sshd; then
            return 0
        fi
        pid=$(ps -o ppid= -p $pid)
    done
    return 1
}

Here's how to integrate this into your bashrc for conditional aliases:


# In ~/.bashrc or your shell config
if is_ssh_session; then
    alias reboot='echo "SSH session detected - use physical console for reboot"'
    alias halt='echo "SSH session detected - use physical console for shutdown"'
else
    alias reboot='sudo /sbin/reboot'
    alias halt='sudo /sbin/halt'
fi

For systems where process inspection isn't reliable, consider these methods:


# TTY-based detection
if tty | grep -q '^/dev/pts/'; then
    # Likely SSH session (pseudo-terminal)
fi

# Terminal emulator check
if [[ "$TERM" == "xterm-256color" && -n "$SSH_CONNECTION" ]]; then
    # SSH session with color support
fi
  • Containerized environments may require additional checks
  • Jump hosts or SSH tunnels might obscure the original connection
  • Some sudo configurations preserve SSH environment variables
  • Consider adding a manual override variable for edge cases

When working with remote servers, it's often useful to determine whether your current shell session was initiated via SSH. This can help customize your environment—for instance, disabling dangerous commands like halt on remote systems. The most common method involves checking environment variables set by the SSH daemon.

if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then  
  echo "This is an SSH session."  
  # Customize remote aliases/behavior  
  alias halt='echo "Command disabled on remote systems!"'  
else  
  echo "Local shell session detected."  
fi

The primary variables (SSH_CLIENT, SSH_CONNECTION, SSH_TTY) are discarded during sudo operations unless explicitly preserved. To handle this:

# Option 1: Use sudo -E to preserve environment  
sudo -E bash -c 'echo $SSH_CLIENT'  

# Option 2: Check parent processes  
if ps -o comm= -p $PPID | grep -q sshd; then  
  echo "SSH session (via process check)"  
fi

For systems where environment variables are unavailable, consider these approaches:

# Method 1: Check tty name (SSH sessions often use /dev/pts/*)  
if [[ $(tty) =~ /dev/pts/[0-9]+ ]]; then  
  echo "Likely SSH session"  
fi  

# Method 2: Parse netstat/lsof for SSH connections  
if lsof -iTCP -sTCP:ESTABLISHED -p $$ | grep -q sshd; then  
  echo "Active SSH connection detected"  
fi  

# Method 3: Systemd-specific check (Linux)  
if [ -n "$XDG_SESSION_TYPE" ] && [ "$XDG_SESSION_TYPE" = "tty" ]; then  
  echo "Local session"  
elif systemctl --user show-environment | grep -q SSH_CONNECTION; then  
  echo "SSH session via systemd"  
fi

Here's a consolidated solution for your bash configuration:

# ~/.bashrc snippet  
function is_ssh_session() {  
  [[ -n "$SSH_CLIENT" || -n "$SSH_TTY" ]] || \  
  ps -o comm= -p $PPID | grep -q sshd || \  
  [[ $(tty) =~ /dev/pts/[0-9]+ ]]  
}  

if is_ssh_session; then  
  alias halt='echo "Remote system protection: halt disabled"'  
  export PS1="$$\e[1;31m$$[SSH]$$\e[0m$$ \u@\h:\w\$ "  
fi