Como posso detectar se o shell é controlado pelo SSH?


69

Quero detectar de um script de shell (mais especificamente .zshrc) se ele é controlado por SSH. Eu tentei a variável HOST, mas é sempre o nome do computador que está executando o shell. Posso acessar o nome do host de onde vem a sessão SSH? Comparar os dois resolveria o meu problema.

Toda vez que faço login, há uma mensagem informando o último horário e host do login:

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

Isso significa que o servidor possui essas informações.

Respostas:


90

Aqui estão os critérios que eu uso no meu ~/.profile:

  • Se uma das variáveis SSH_CLIENTou SSH_TTYfor definida, é uma sessão ssh.
  • Se o nome do processo pai do shell de login for sshd, é uma sessão 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

(Por que você deseja testar isso na configuração do shell e não na inicialização da sessão?)


3
Trabalhou muito obrigado! github.com/balupton/dotfiles/commit/…
balupton

11
convém fazer isso na configuração do shell se desejar ativar o encaminhamento do agente ssh a partir do shell remoto (já que os vários ambientes devem ser definidos em cada shell do qual você deseja encaminhar), a menos que esteja faltando alguma coisa?
o encaixe

@underrun Eu não entendo o seu ponto. Se você executar outro shell na mesma sessão, ele herdará as variáveis ​​de ambiente definidas por .profile. E o que isso tem a ver com encaminhamento de agente?
Gilles 'SO- stop be evil'

11
@underrun Se você deseja testar a presença de encaminhamento de agente SSH, teste a SSH_AUTH_SOCKvariável. Mas por que você executaria um agente SSH nesse caso? Você quis dizer iniciar um agente se estiver logado sem encaminhamento de agente? Por que não iniciar um agente se já não existe um ( [ -n "$SSH_AUTH_SOCK" ] || eval $(ssh-agent))?
Gilles 'SO- stop be evil'

11
@Praxeolitic As SSH_*variáveis ​​também são definidas nos subprocessos de um shell que está no início de uma sessão SSH, por exemplo, se você iniciar uma sessão de tela sobre SSH (você deve desmarcar as variáveis ​​antes de iniciar a sessão, se quiser). Acho que a razão para testar o processo pai é que comecei a fazer isso antes do sshd definir qualquer variável de ambiente.
Gilles 'SO- stop be evil'

21

Você deve ser capaz de verificar através das SSH_TTY, SSH_CONNECTIONou SSH_CLIENTvariáveis.


11
Também adicioná-los para env_keepem sudoersfazê-lo funcionar em toda sucomandos :)
Thomas G.

10

Eu apenas tive o mesmo problema no Linux, usando o Bash. Eu primeiro usei a variável de ambiente SSH_CONNECTION, mas depois percebi que ela não está definida se você su -.

A solução lastlog acima não funcionou após suou su -.

Finalmente, estou usando who am i, que mostra o IP remoto (ou o nome do host) no final, se for uma conexão SSH. Também funciona após su.

Usando expressões regulares do Bash, isso funciona:

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

Se o zsh não suportar expressões regulares, o mesmo poderá ser alcançado de várias maneiras diferentes com grep, cut, sed ou o que for.

Para os curiosos, abaixo é para isso que eu uso isso, no .bashrc do root:

    # 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

Uma alternativa que também funciona suseria procurar recursivamente por sshdmeio dos processos pai:

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

Se a função for adicionada ao .bashrc, ela poderá ser usada como if is_ssh; then ...


11
não funciona em tmuxsessões remotas e também tem problemas se estiver conectado via IPv6 e não existir um nome reverso de DNS.
21813 bene

@bene: o que não funciona? A expressão regular ou who am inão mostra seu endereço IPv6?
Mvk

1) who am inão retorna nada em uma tmuxsessão remota . 2) O endereço IPv6 pode conter dois pontos que seu regex não permite. Isso pode ser complicado, pois who am icontém (:0.0)em X sessões para mim (xterm).
bene

@bene: A solução alternativa que acabei de adicionar também deve funcionar com IPv6. Eu não sei sobre o tmux, mas também funciona screen.
mivk

7

Eu acho que as respostas de Gilles e Cakemox são boas, mas apenas por completude ...

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

vem de pam_lastlog1 .

Você pode imprimir pam_lastloginformações usando o comando lastlog2 , por exemplo

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

para um login local, em comparação com

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

para um login SSH.

No meu sistema, isso funciona para extraí-lo

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

laste também wpode ser útil, por exemplo

$ 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 documentação do Linux / FreeBSD para pam_lastlog.
2 páginas de manual do Linux / FreeBSD lastlog(8) .


1

Comece examinando seu ambiente e encontrando a opção certa

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

Você pode conectar-se a muitas dessas variáveis ​​de ambiente para acionar ações específicas com base na presença delas.


-1

Isso é para verificar todas as conexões estabelecidas de outro usuário usando SSH

netstat | grep ssh

Isso não é de todo confiável.
DannyNiu
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.