Назад | Перейти на главную страницу

Как определить, вошел ли я в систему через SSH?

В настоящее время я настраиваю довольно сложную конфигурацию bash, которая будет использоваться на нескольких машинах. Я пытаюсь выяснить, можно ли определить, вошел ли я в систему через SSH или на локальном компьютере. Таким образом, я мог бы, например, установить некоторые псевдонимы в зависимости от этого факта. Как алиасинг halt к restart поскольку остановка удаленного сервера может быть не лучшим решением.

На данный момент я знаю, что переменная среды SSH_CLIENT устанавливается, когда я входил в систему через ssh. К сожалению, эта переменная отбрасывается, когда я запускаю оболочку суперпользователя с sudo -s. Я также знаю, что могу передать sudo параметр, который инструктирует sudo скопировать все переменные моей среды в новую среду оболочки, но если я не хочу этого делать, есть ли другой способ?

Вы можете использовать вывод команды «w» или «who». Когда вы подключаетесь по ssh, они покажут ваш исходный IP.

Вот отличный ответ, который я нашел на unix.stackexchange:


  • Если одна из переменных SSH_CLIENT или SSH_TTY определен, это сеанс ssh.
  • Родительский процесс оболочки входа в систему можно проверить с помощью 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

Вы могли бы добавить SSH_* к env_keep в sudoers чтобы это можно было обнаружить при переключении на другого пользователя.

Если вы хотите знать, является ли оболочка bash напрямую дочерним процессом sshd (а не n> 1 уровня в глубину), вы можете

cat / proc / $ PPID / status | голова -1 | вырезать -f2

это должно дать вам sshd или любое другое имя родительского процесса вашей текущей оболочки.

Я думаю, вы хотите переосмыслить то, как вы думаете о проблеме. Вопрос не в том, «вошел ли я через SSH, потому что хочу отключить определенные команды». Это «я вошел в систему с консоли, потому что тогда я активирую определенные команды».

Да, как отмечали другие, информация находится в присутствии вашего IP-адреса в круглых скобках в выводе who am i.

Вы можете использовать регулярные выражения Bash, чтобы обнаружить это:

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

Я придумал следующее, основываясь на советах других здесь.

Он использует переменную для кеширования - я использую ее в своей теме оболочки.

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_ssh в https://github.com/blueyed/oh-my-zsh/blob/master/themes/blueyed.zsh-theme#L51-63.

Найдите командную строку и рекурсию родительской оболочки. Может быть что-то вроде следующего:

#!/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__
`

Отредактировано, чтобы он действительно работал :)

Все остальные ответы работают, если вы находитесь на первом уровне входа в систему. Но если после входа в систему вы запускаете 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

Вот результат работы egrep после удаления --quiet. Он показывает всю иерархию, которая соответствует при удаленном подключении.

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

Имейте в виду, что это очень, очень Специфично для 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»).

Если вы не используете функцию X11Forward. Возможно, самый простой способ проверить это через

echo $DISPLAY

Если вы входите через SSH без X11Forward, он обычно пуст, в противном случае, как :1