Come posso rilevare se la shell è controllata da SSH?


69

Voglio rilevare da uno script di shell (in particolare .zshrc) se è controllato tramite SSH. Ho provato la variabile HOST ma è sempre il nome del computer che esegue la shell. Posso accedere al nome host da cui proviene la sessione SSH? Il confronto tra i due risolverebbe il mio problema.

Ogni volta che eseguo l'accesso, viene visualizzato un messaggio che indica l'ora dell'ultimo accesso e l'host:

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

Questo significa che il server ha queste informazioni.

Risposte:


90

Ecco i criteri che uso nel mio ~/.profile:

  • Se una delle variabili SSH_CLIENTo SSH_TTYè definita, è una sessione ssh.
  • Se il nome del processo parent della shell di login è sshd, si tratta di una sessione 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

(Perché dovresti testarlo nella configurazione della shell piuttosto che nell'avvio della sessione?)


3
Ha funzionato alla grande grazie! github.com/balupton/dotfiles/commit/…
balupton

1
potresti volerlo fare nella configurazione della tua shell se vuoi abilitare l'inoltro dell'agente ssh dalla tua shell remota (dal momento che le variabili d'ambiente devono essere impostate in ogni shell da cui vuoi inoltrare) a meno che non mi manchi qualcosa?
underrun

@underrun Non capisco il tuo punto. Se si esegue un'altra shell nella stessa sessione, eredita le variabili di ambiente impostate da .profile. E cosa c'entra questo con l'inoltro dell'agente?
Gilles 'SO- smetti di essere malvagio' il

1
@underrun Se si desidera verificare la presenza dell'inoltro dell'agente SSH, verificare la SSH_AUTH_SOCKvariabile. Ma perché dovresti eseguire un agente SSH in quel caso? Intendevi avviare un agente se hai effettuato l'accesso senza inoltro agente? Perché non avviare un agente se non ce n'è già uno ( [ -n "$SSH_AUTH_SOCK" ] || eval $(ssh-agent))?
Gilles 'SO- smetti di essere malvagio' il

1
@Praxeolitic Le SSH_*variabili sono anche impostate nei sottoprocessi di una shell che sta alla testa di una sessione SSH, ad esempio se si avvia una sessione dello schermo su SSH (se necessario, è necessario annullare l'impostazione delle variabili prima di iniziare la sessione). Penso che la ragione per testare il processo genitore sia che ho iniziato a farlo prima che sshd definisse qualsiasi variabile d'ambiente.
Gilles 'SO- smetti di essere malvagio' il

21

Dovreste essere in grado di controllare tramite i SSH_TTY, SSH_CONNECTIONo SSH_CLIENTvariabili.


1
Aggiungili anche a env_keepin sudoersper farlo funzionare attraverso i sucomandi :)
Thomas G.

10

Ho avuto lo stesso problema in Linux, usando Bash. Ho usato prima la variabile di ambiente SSH_CONNECTION, ma poi ho capito che non è stato impostato se si su -.

La soluzione lastlog sopra non ha funzionato né dopo susu -.

Infine, sto usando who am i, che mostra l'IP remoto (o il nome host) alla fine se si tratta di una connessione SSH. Funziona anche dopo su.

Usando le espressioni regolari di Bash, funziona:

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

Se zsh non supporta le espressioni regolari, lo stesso può essere ottenuto in molti modi diversi con grep, cut, sed o altro.

Per i curiosi, di seguito è quello per cui lo uso, nel .bashrc di 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

Un'alternativa che funziona anche con la suricerca ricorsiva sshdattraverso i processi padre:

#!/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 la funzione viene aggiunta a .bashrc, può essere utilizzata come if is_ssh; then ...


1
non funziona nelle tmuxsessioni remote e presenta problemi anche se si accede tramite IPv6 e non esiste alcun nome inverso DNS.
Bene,

@bene: cosa non funziona? L'espressione regolare o who am inon mostra il tuo indirizzo IPv6?
marzo

1) who am inon restituisce nulla in una tmuxsessione remota . 2) L'indirizzo IPv6 potrebbe contenere due punti non consentiti dal regex. Questo potrebbe essere complicato poiché who am icontiene (:0.0)in X sessioni per me (xterm).
Bene,

@bene: la soluzione alternativa che ho appena aggiunto dovrebbe funzionare anche con IPv6. Non so di tmux, ma funziona anche in screen.
mivk,

7

Penso che le risposte di Gilles e Cakemox siano buone, ma solo per completezza ...

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

proviene da pam_lastlog1 .

È possibile stampare pam_lastloginformazioni utilizzando il comando lastlog2 , ad es

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

per un accesso locale, rispetto a

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

per un login SSH.

Sul mio sistema, questo funziona per estrarlo

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

laste wpotrebbe essere utile anche per esempio

$ 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 documentazione Linux / FreeBSD per pam_lastlog.
2 pagine man di Linux / FreeBSD lastlog(8) .


1

Inizia dando un'occhiata al tuo ambiente e trova l'opzione giusta

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

È possibile agganciare molte di queste variabili d'ambiente per attivare azioni specifiche in base alla loro presenza.


-1

Questo serve per controllare tutte le connessioni stabilite da altri utenti usando SSH

netstat | grep ssh

Questo non è affatto affidabile.
DannyNiu
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.