Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to detect from a shell script (more specifically .zshrc) if it is controlled through SSH. I tried the HOST variable but it's always the name of the computer which is running the shell. Can I access the hostname where the SSH session is coming from? Comparing the two would solve my problem.

Every time I log in there is a message stating the last login time and host:

Last login: Fri Mar 18 23:07:28 CET 2011 from max on pts/1
Last login: Fri Mar 18 23:11:56 2011 from max

This means the server has this information.

share|improve this question

4 Answers 4

up vote 24 down vote accepted

Here are the criteria I use in my ~/.profile:

  • If one of the variables SSH_CLIENT or SSH_TTY is defined, it's an ssh session.
  • If the login shell's parent process name is sshd, it's an ssh session.
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
  SESSION_TYPE=remote/ssh
# many other tests omitted
else
  case $(ps -o comm= -p $PPID) in
    sshd|*/sshd) SESSION_TYPE=remote/ssh;;
  esac
fi

(Why would you want to test this in your shell configuration rather than your session startup?)

share|improve this answer
    
Worked great thanks! github.com/balupton/dotfiles/commit/… –  balupton Nov 6 '13 at 6:52
    
you might want to do this in your shell configuration if you want to enable ssh agent forwarding from your remote shell (since the environment vars need to be set in each shell you want to forward from) unless i'm missing something? –  underrun Apr 14 at 16:31
    
@underrun I don't understand your point. If you run another shell in the same session, it inherits the environment variables set by .profile. And what does this have to do with agent forwarding? –  Gilles Apr 14 at 20:41
    
@Gilles if i want to us agent forwarding from a machine i'm ssh'd into already i will want to eval $(ssh-agent) but only if i've connected over ssh. i need both the ssh-agent process and the env vars right? –  underrun Apr 15 at 18:36
    
@underrun If you want to test for the presence of SSH agent forwarding, test for the SSH_AUTH_SOCK variable. But why would you run an SSH agent in that case? Did you mean start an agent if you're logged in without agent forwarding? Why not start an agent if there isn't already one ([ -n "$SSH_AUTH_SOCK" ] || eval $(ssh-agent))? –  Gilles Apr 15 at 19:11

You should be able to check via the SSH_TTY, SSH_CONNECTION, or SSH_CLIENT variables.

share|improve this answer

I think Gilles and Cakemox's answers are good, but just for completeness...

Last login: Fri Mar 18 23:07:28 CET 2011 from max on pts/1

comes from pam_lastlog.

You can print pam_lastlog information using the lastlog command, e.g.

$ lastlog -u mikel  
Username         Port     From             Latest
mikel            tty1                      Fri Jan 28 10:58:10 +1100 2011

for a local login, compared to

Username         Port     From             Latest
mikel            pts/9    mikel-laptop     Sat Mar 19 11:11:58 +1100 2011

for an SSH login.

On my system, this works to extract it

$ lastlog -u mikel | sed -ne '2{p;q}' | cut -c 27-42
mikel-laptop 

last and w could be helpful too, for example

$ TTY=$(tty)
$ last -n 1 ${TTY#/dev/} | sed -ne '1{p;q}'
mikel    pts/12       :0.0             Sat Mar 19 11:29   still logged in 
share|improve this answer

I just had the same problem in Linux, using Bash. I first used the environment variable SSH_CONNECTION, but then realized that it is not set if you su -.

The lastlog solution above didn't work either after su or su -.

Finally, I am using who am i, which shows the remote IP (or the hostname) at the end if it's an SSH connection. It also works after su.

Using Bash regular expressions, this works:

if [[ $(who am i) =~ \([-a-zA-Z0-9\.]+\)$ ]] ; then echo SSH; else echo no; fi

If zsh doesn't support regular expressions, the same can be achieved in many different ways with grep, cut, sed, or whatever.

For the curious, below is what I use this for, in root's .bashrc :

    # We don't allow root login over ssh.
    # To enable root X forwarding if we are logged in over SSH, 
    # use the .Xauthority file of the user who did su

    w=$(who am i)
    if [[ $w =~ \([-a-zA-Z0-9\.]+\)$ ]] ; then
        olduser=${w/ .*/}
        oldhome=$(getent passwd $olduser | cut -d: -f 6)
        [ -f "$oldhome/.Xauthority" ] \
          && export XAUTHORITY=$oldhome/.Xauthority
    fi

An alternative which also works with su would be to recursively search for sshd through the parent processes:

#!/bin/bash

function is_ssh() {
  p=${1:-$PPID}
  read pid name x ppid y < <( cat /proc/$p/stat )
  # or: read pid name ppid < <(ps -o pid= -o comm= -o ppid= -p $p) 
  [[ "$name" =~ sshd ]] && { echo "Is SSH : $pid $name"; return 0; }
  [ "$ppid" -le 1 ]     && { echo "Adam is $pid $name";  return 1; }
  is_ssh $ppid
}

is_ssh $PPID
exit $?

If the function is added to .bashrc, it can be used as if is_ssh; then ...

share|improve this answer
    
doesn’t work in remote tmux sessions and also has issues if logged in via IPv6 and no DNS reverse name exists. –  bene Feb 10 '13 at 16:58
    
@bene: what doesn't work? The regular expression, or does who am i not show your IPv6 address? –  mivk Feb 10 '13 at 19:08
    
1) who am i doesn’t return anything in a remote tmux session. 2) IPv6 address might contain colons which your regex doesn’t allow. This might be tricky since who am i contains (:0.0) in X sessions for me (xterm). –  bene Feb 11 '13 at 15:05
    
@bene: The alternative solution which I just added should also work with IPv6. I don't know about tmux, but it does also work in screen. –  mivk Dec 15 '13 at 14:54

Your Answer

 
discard

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.