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


69

Я хочу определить из сценария оболочки (точнее, .zshrc), управляется ли он через SSH. Я пробовал переменную HOST, но это всегда имя компьютера, на котором работает оболочка. Могу ли я получить доступ к имени хоста, откуда идет сеанс 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

Это означает, что сервер имеет эту информацию.

Ответы:


90

Вот критерии, которые я использую в своем ~/.profile:

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

(Почему вы хотите проверить это в конфигурации вашей оболочки, а не при запуске сеанса?)


3
Работал отлично, спасибо! github.com/balupton/dotfiles/commit/...
balupton

1
Возможно, вы захотите сделать это в своей конфигурации оболочки, если вы хотите включить переадресацию агента ssh из удаленной оболочки (поскольку в каждой оболочке, которую вы хотите пересылать, нужно устанавливать переменные среды), если я что-то не пропустил?
опустошение

@underrun Я не понимаю твою точку зрения. Если вы запускаете другую оболочку в том же сеансе, она наследует переменные окружения, установленные с помощью .profile. И какое это имеет отношение к переадресации агентов?
Жиль "ТАК - перестань быть злым"

1
@underrun Если вы хотите проверить наличие переадресации агента SSH, проверьте SSH_AUTH_SOCKпеременную. Но зачем вам запускать агент SSH в этом случае? Вы имели в виду запуск агента, если вы вошли в систему без переадресации агента? Почему бы не запустить агент, если его еще нет ( [ -n "$SSH_AUTH_SOCK" ] || eval $(ssh-agent))?
Жиль "ТАК - перестань быть злым"

1
@Praxeolitic SSH_*Переменные также устанавливаются в подпроцессах оболочки, которая находится в начале сеанса SSH, например, если вы запускаете сеанс экрана через SSH (вы должны сбросить переменные перед началом сеанса, если вам это нужно). Я думаю, что причиной тестирования родительского процесса является то, что я начал это делать до того, как sshd определил какие-либо переменные среды.
Жиль "ТАК ... перестать быть злым"

21

Вы должны быть в состоянии проверить с помощью SSH_TTY, SSH_CONNECTIONили SSH_CLIENTпеременных.


1
Кроме того, добавить их к env_keepв , sudoersчтобы заставить его работать по suкомандам :)
Thomas G.

10

У меня просто была такая же проблема в Linux с использованием Bash. Сначала я использовал переменную окружения SSH_CONNECTION, но потом понял, что она не установлена, если вы su -.

Решение lastlog выше не сработало ни после, suни su -.

Наконец, я использую who am i, который показывает удаленный IP (или имя хоста) в конце, если это соединение SSH. Это также работает после 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 ...


1
не работает в удаленных tmuxсеансах, а также имеет проблемы при входе в систему через IPv6 и обратного имени DNS не существует.
Bene

@bene: что не работает? Регулярное выражение или who am iне показывает ваш адрес IPv6?
mivk

1) who am iничего не возвращает в удаленном tmuxсеансе. 2) IPv6-адрес может содержать двоеточия, которые не разрешены вашим регулярным выражением. Это может быть сложно, так как who am iсодержится (:0.0)в X сессий для меня (xterm).
Bene

@bene: альтернативное решение, которое я только что добавил, должно также работать с IPv6. Я не знаю о tmux, но он тоже работает screen.
mivk

7

Я думаю, что ответы Жиля и Cakemox хороши, но только для полноты ...

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

исходит от pam_lastlog1 .

Вы можете распечатать pam_lastlogинформацию с помощью команды lastlog2 , например

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

для локального входа, по сравнению с

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

для входа по SSH.

В моей системе это работает, чтобы извлечь его

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

lastи wможет быть полезным, например,

$ 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 


1 Linux / FreeBSD документация для pam_lastlog.
2 справочные страницы по Linux / FreeBSD lastlog(8) .


1

Начните с изучения вашей среды и поиска правильного варианта

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

Вы можете подключиться ко многим из этих переменных среды, чтобы инициировать конкретные действия в зависимости от их присутствия.


-1

Это для проверки всех установленных соединений от другого пользователя с использованием SSH

netstat | grep ssh

Это совсем не надежно.
DannyNiu
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.