如何确定我是否通过SSH登录?


17

我当前正在设置一个相当复杂的bash配置,该配置将在多台机器上使用。我尝试找出是否可以确定我是通过SSH还是在本地计算机上登录。这样,例如,我可以根据该事实设置一些别名。就像别名一样haltrestart因为停止远程服务器可能不是最好的选择。

到目前为止,我所知道的是,SSH_CLIENT当我通过ssh登录时设置了环境变量。不幸的是,当我使用启动超级用户外壳程序时,此变量被丢弃sudo -s。我也知道我可以将参数传递给sudo,指示sudo将所有环境变量复制到新的shell环境中,但是如果我不想这样做,还有其他方法吗?

Answers:


14

您可以使用“ w”或“ who”命令输出。当您通过ssh连接时,它们会显示您的源IP。


1
进行有根据的猜测。例如,运行ps afx,而外壳未运行的TTY ps将是另一个登录名。
华纳2010年

6
使用who am i
Paul Tomblin

1
“ uname -n”将为您提供主机名
Hubert Kario 2010年

1
该问题似乎与从中提取有关who am i,与您联系更紧密,因此您可以从那里确定是否进行SSH。这有效:hostname=$(who am i | cut -f2 -d\( | cut -f1 -d:)
2011年

4
@PaulTomblin实际上,您可以使用who任何两个额外的参数。who am iwho is mewho is awesome或相同who potato potato。我发现一个事实很有趣。
kirkpatt '16

9

这是我在unix.stackexchange上找到的一个很好的答案:


  • 如果定义了变量SSH_CLIENT或之一,SSH_TTY则为ssh会话。
  • 可以使用登录shell的父进程进行检查ps -o comm= -p $PPID。如果是sshd,则为ssh会话。
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
  SESSION_TYPE=remote/ssh
else
  case $(ps -o comm= -p $PPID) in
    sshd|*/sshd) SESSION_TYPE=remote/ssh;;
  esac
fi

不适用于sudo -s
Matt


4

如果您想知道bash shell是否直接是sshd的子进程(不深于n> 1层),则可以

cat / proc / $ PPID /状态| 头-1 | 切-f2

它应该给您sshd或您当前shell的父进程名称是什么。


不适用于sudo -s
Matt

ps -o cmd= $PPIDawk '/^Name:/ {print $2}' /proc/$PPID/status

3

我认为您想重新考虑思考问题的方式。问题不是“我是通过SSH登录的,因为我想关闭某些命令”。它是“我已在控制台登录,因为那样我将启用某些命令。”


3

是的,正如其他人指出的那样,该信息在的输出中的括号中包含您的IP who am i

您可以使用Bash正则表达式来检测它:

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

1
它也可以是主机名。
2015年

如果主机名包含数字,则无法使用。
YoYoYonnY

1

根据其他人的提示,我提出了以下建议。

它使用一个变量进行缓存-我在shell主题中使用它。

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 != :* ]]
        _ZSH_IS_SSH=$?
    fi
    return $_ZSH_IS_SSH
}

来源:is_sshhttps://github.com/blueyed/oh-my-zsh/blob/master/themes/blueyed.zsh-theme#L51-63


0

查找外壳程序的父cmdline并递归。也许像下面这样:

#!/usr/bin/env bash

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

PD=${1:-$$}
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 re.search(r'^ssh', ln): 
    print "echo Logged in via ssh"
if re.search(r'getty.*?tty', ln):
    print "echo Logged in console"
if re.search("gnome-terminal", ln):
    print "echo Logged in Gnome"
if re.search(r'^login', ln):
    print "echo Logged in console"
if re.search(r'^-?bash', ln) or re.search(r'^su', ln): 
    print "./$ME $PAR"
f.close()
__EOF__
`

编辑以使其实际工作:)


0

如果您是第一级登录,则所有其他答案都可以使用。但是,如果登录后运行了“ su”或“ sudo”(在我的情况下,出于安全原因切换到不带外壳的用户帐户,则必须运行:sudo su-<userid> -s / bin / bash- l),他们的解决方案失败。

以下是通用解决方案;使用pstree,您将sshd作为父项进行检查。

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

这是删除--quiet时egrep的输出。它显示了远程连接时匹配的整个层次结构。

   |            |-sshd(18599)---sshd(18603)---bash(18604)---sudo(18823)---bash(18824)-+-egrep(22417)

0

请记住,这个答案非常非常特定于Linux。

parent_pid=$$
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
  )
done

echo $initiator_name

这是一个关键的假设:登录过程将没有可控制的TTY。您可能想在运行此代码之前检查您是否具有控制TTY(无论如何,根据您的要求,这可能是一个安全的选择)。

代码向上遍历进程树,直到找到没有控制TTY的进程。 $initiator_name将是此进程的名称(例如“ sshd”)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.