it-swarm.cn

如何检测Shell是否受SSH控制?

我想从Shell脚本(更具体地说是.zshrc)中检测它是否通过SSH控制。我尝试了Host变量,但它始终是运行Shell的计算机的名称。我可以访问SSH会话来自的主机名吗?比较两者将解决我的问题。

每次我登录时,都会显示一条消息,说明上次登录时间和主机:

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

这意味着服务器具有此信息。

72
stribika

以下是我在~/.profile中使用的条件:

  • 如果定义了变量SSH_CLIENTSSH_TTY之一,则它是ssh会话。
  • 如果登录Shell的父进程名称是sshd,则它是ssh会话。
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

(为什么要在Shell配置中而不是会话启动时进行测试?)

95

您应该可以通过SSH_TTYSSH_CONNECTION, 要么 SSH_CLIENT变量。

23
Cakemox

我只是在Linux中使用Bash遇到了同样的问题。我首先使用了环境变量SSH_CONNECTION,但是随后意识到,如果您su -,则不会设置该变量。

上面的lastlog解决方案在susu -之后无效。

最后,我使用who am i,如果是SSH连接,它将在末尾显示远程IP(或主机名)。 su之后也可以使用。

使用Bash正则表达式,可以工作:

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

如果zsh不支持正则表达式,则可以使用grep,cut,sed或其他任何方式以相同的方式实现相同的目的。

出于好奇,下面是我在root的.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

也可以与su一起使用的替代方法是通过父进程递归搜索sshd

#!/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 $?

如果该函数添加到.bashrc,则可以用作if is_ssh; then ...

10
mivk

首先查看您的环境并找到正确的选项

printenv|grep SSH
SSH_CLIENT=192.168.1.xxx
SSH_CONNECTION=192.168.1.xxx
SSH_TTY=/dev/ttys021

您可以加入许多这些环境变量,以根据它们的存在来触发特定操作。

2
lfender6445