Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm currently setting up a fairly complex bash configuration which shall be used on multiple machines. I try to find out if it is possible to determine whether I'm logged in via SSH or on a local machine. This way I could, for instance, set some aliases depending on that fact. Like aliasing halt to restart since stopping a remote server might not be the best thing to do.

What I know so far is, that the environment variable SSH_CLIENT is set when I logged in via ssh. Unfortunately, this variable is discarded when I start a super user shell with sudo -s. I also know that I can pass a parameter to sudo that instructs sudo to copy all my environment variables to the new shell environment, but if I don't want to do this, is there an other way?

share|improve this question

10 Answers 10

up vote 13 down vote accepted

You could use "w" or "who" command output. When you connect over ssh, they'll show your source IP.

share|improve this answer
Make educated guesses. For example, run ps afx and the TTY for the shell not running ps will be the other login. – Warner Oct 5 '10 at 13:52
Use who am i. – Paul Tomblin Oct 5 '10 at 13:53
"uname -n" will give you the hostname – Hubert Kario Oct 5 '10 at 16:15
The question appears to be more related to extract it from who am i, so that you can determine from there if you're SSHing or not. This works: hostname=$(who am i | cut -f2 -d\( | cut -f1 -d:) – blueyed Apr 7 '11 at 0:34
or you could be fun and use sed :) as in: who am i | sed 's/.*(\(.*\))/\1/g' – photoionized Apr 7 '11 at 23:04

You could add SSH_* to env_keep in sudoers so that this can be detected while switched to the other user.

share|improve this answer

If you want to know if you bash shell is directly a child process of sshd (not n>1 layers deep) you can

cat /proc/$PPID/status | head -1 | cut -f2

it should give you sshd or whatever is the parent process name of your current shell.

share|improve this answer
Doesn't work for sudo -s – Matt Aug 12 '15 at 22:47
ps -o cmd= $PPID or awk '/^Name:/ {print $2}' /proc/$PPID/status – Six Jan 1 at 0:39

Here is a great answer I found on unix.stackexchange:

  • If one of the variables SSH_CLIENT or SSH_TTY is defined, it's an ssh session.
  • The login shell's parent process can be checked with ps -o comm= -p $PPID. If it is sshd, it's an ssh session.
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
  case $(ps -o comm= -p $PPID) in
    sshd|*/sshd) SESSION_TYPE=remote/ssh;;
share|improve this answer
Doesn't work for sudo -s – Matt Aug 12 '15 at 22:46

I think you want to rethink the way you're thinking of the problem. The question isn't "am I logged in via SSH, because I want to turn off certain commands." It's "am I logged in at the console, because then I will enable certain commands."

share|improve this answer

Yes, as others noted, the info is in the presence of your IP in parentheses in the output of who am i.

You can use Bash regular expressions to detect it:

if [[ $(who am i) =~ \([0-9\.]+\)$ ]]; then echo SSH; else echo no; fi
share|improve this answer
It can also be a hostname. – blueyed Aug 12 '15 at 22:06

I've came up with the following, based on tips from others here.

It uses a variable for caching - I am using it in my shell theme.

is_ssh() {
    (( $+SSH_CLIENT )) && return
    if ! (( $+_ZSH_IS_SSH )); then
        # "who am i" displays current user from utmp(5).  This will be empty for
        # a "normal" terminal.  With Konsole, it is ":0" for display :0,
        # for ssh it is the hostname and with tmux sth like "tmux(PID).ID".
        local whoami="$(who am i)"}
        local host="${whoami#*\(*}"
        [[ -n $host && $host != tmux* && $host != :* ]]
    return $_ZSH_IS_SSH

Source: is_ssh in

share|improve this answer

Look for your shell's parent cmdline and recurse. Maybe something like the following:

#!/usr/bin/env bash

## Find out how I'm logged in
# Tested on RHEL5.5

ME=`basename $0`

## Read the shell's PPID
PAR=`ps --no-headers -p $PD -o ppid`

## CMDLINE can contain stuff like the following:
# /sbin/getty-838400tty4 // logged in at a console
# gnome-terminal         // logged in Gnome Terminal
# -bash                  // in a subshell
# su-                    // we became another user using su
# sshd: jc@pts/1         // logged in over ssh
# login                  // logged in terminal or serial device

eval `python - << __EOF__
import re
f = open("/proc/${PAR}/cmdline", 'r')
ln = f.readline()
if'^ssh', ln): 
    print "echo Logged in via ssh"
if'getty.*?tty', ln):
    print "echo Logged in console"
if"gnome-terminal", ln):
    print "echo Logged in Gnome"
if'^login', ln):
    print "echo Logged in console"
if'^-?bash', ln) or'^su', ln): 
    print "./$ME $PAR"

Edited to make it actually work :)

share|improve this answer

All of the other answers work if you are at the first level of login. But if, once login, you run 'su' or 'sudo' (in my case, to switch to a user account without shell for security reasons, I had to run: sudo su - <userid> -s /bin/bash -l), their solution fail.

Following is a universal solution; using pstree, you check for sshd as a parent.

if pstree -p | egrep --quiet --extended-regexp ".*sshd.*\($$\)"; then
  echo "I am remote."
  echo "I am local."

Here is the output of the egrep, when --quiet is removed. It shows the whole hierarchy that matches if one is connected remotely.

   |            |-sshd(18599)---sshd(18603)---bash(18604)---sudo(18823)---bash(18824)-+-egrep(22417)
share|improve this answer

Please keep in mind that this answer is very, very Linux specific.

while [[ -z "${tty_bits-}" || $tty_bits -ne 0 ]]; do
  read initiator_name parent_pid tty_bits < <(
    awk '{ print substr($2, 2, length($2) - 2) " " $4 " " $7 }' /proc/$parent_pid/stat

echo $initiator_name

This makes a key assumption: the login process won't have a controlling TTY; you probably want to check if you have a controlling TTY before running this code (which, based upon your requirements, probably is a safe bet, anyway).

The code iterates upwards through the process tree, until it find the process that has no controlling TTY. $initiator_name will be the name of this process ("sshd", for example).

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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