SSH経由でログインしているかどうかを確認する方法は?


17

私は現在、複数のマシンで使用されるかなり複雑なbash構成をセットアップしています。SSH経由でログインしているか、ローカルマシンにログインしているかを判断できるかどうかを確認しようとしています。このようにして、たとえば、その事実に応じていくつかのエイリアスを設定できます。リモートサーバーを停止することは、最善の方法ではない可能性があるhaltためrestart、エイリアシングのようなものです。

私がこれまでに知っていることは、SSH_CLIENTssh経由でログインしたときに環境変数が設定されるということです。残念ながら、スーパーユーザーシェルをで起動すると、この変数は破棄されsudo -sます。また、sudoにすべての環境変数を新しいシェル環境にコピーするように指示するパラメーターをsudoに渡すことができることも知っていますが、これを行いたくない場合、他の方法はありますか?

回答:


14

「w」または「who」コマンド出力を使用できます。sshを介して接続すると、ソースIPが表示されます。


1
経験に基づいた推測を行います。たとえば、実行するps afxと、実行されていないシェルのTTY psが他のログインになります。
ワーナー

6
を使用しwho am iます。
ポールトムブリン

1
「uname -n」はホスト名を提供します
Hubert Kario

1
質問はから抽出することに関連しているように見えるwho am iため、SSHを使用しているかどうかをそこから判断できます。この作品:hostname=$(who am i | cut -f2 -d\( | cut -f1 -d:)
blueyed

4
@PaulTomblin実際には、who2つの追加の引数を使用できます。who am i同じであるwho is meか、who is awesomeまたはwho potato potato。実際、私は少し面白かった。
kirkpatt

9

ここにunix.stackexchangeで見つけた素晴らしい答えがあります:


  • 変数SSH_CLIENTまたはのいずれかSSH_TTYが定義されている場合、それはsshセッションです。
  • ログインシェルの親プロセスはで確認できますps -o comm= -p $PPID。の場合、それはsshdsshセッションです。
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では機能しません
マット


4

bashシェルが直接sshdの子プロセス(n> 1層ではない)かどうかを知りたい場合は、

cat / proc / $ PPID / status | ヘッド-1 | カット-f2

これはsshd、現在のシェルの親プロセス名または何でも提供する必要があります。


sudo -sでは機能しません
マット

ps -o cmd= $PPIDまたはawk '/^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
ホスト名にすることもできます。
ブルーイング

ホスト名に数字が含まれていると機能しません。
YoYoYonnY

1

ここで他の人からのヒントに基づいて、私は次を思いつきました。

キャッシングに変数を使用します-シェルテーマで使用しています。

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

シェルの親コマンドラインを探して再帰します。次のようなものかもしれません:

#!/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」)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.