web-dev-qa-db-ja.com

既存の画面に再接続するときに、どのようにして画面を現在のssh-agentに自動的に接続しますか?

Ssh-agentの実行中に(ssh -Aエージェント転送から)screenセッションを開始した場合、ssh-agentへのアクセスは正常に機能します。ただし、そのセッションから切断し、ログアウトしてから再度ログインし(ssh-agent転送を使用)、screenセッションに再接続すると、ssh-agentアクセスは機能しません。

これをどのように修正できますか?

52
apinstein

1)SSH rcスクリプト(〜/ .ssh/rc)で、正規の場所から「現在の」SSH_AUTH_SOCKへのシンボリックリンクを設定します。これがbashでそれを行う方法です(〜/ .ssh/rcの内容):

#!/bin/bash
if test "$SSH_AUTH_SOCK" ; then
    ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
fi

(そしてchmod 755〜/ .ssh/rcを必ず確認してください)。 「テスト」は、ssh-agentを実行していない場合(つまり、-Aなしでsshを実行した場合)にエラーが表示されないようにするためのものです。そのコマンドの後半では、ログイン時に自分自身を「実際の」SSH_AUTH_SOCKに更新する正規の場所にシンボリックリンクを設定します。これは、sshでシェルを使用したり、コマンドを直接呼び出したりすることとは関係なく、「ssh -t screen -RRD」でも機能します。

注:〜/ .ssh/rcの存在はsshdの動作を変更します。特に、xauthは呼び出されません。詳細および修正方法については、man sshdを参照してください。

また、次の診断でrsync-over-sshが壊れるので、lnで「-v」を使用しないでください。

$ rsync -n addr.maps.dev.yandex.net: .
protocol version mismatch -- is your Shell clean?
(see the rsync man page for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(173) [Receiver=3.0.7]

2).screenrcで、SSH_AUTH_SOCKを正規の場所にオーバーライドするだけです。

setenv SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock

どのシェルを使用しても、setenvを使用することに注意してください。 setenvはシェルではなく画面構文だと思います。

この投稿 から元々適応されたソリューションは機能しませんが、正しい考えを持っています。

41
apinstein

これは@ sandip-bhattacharyaの答えを単純化したものだと思います。これを~/.bashrcファイルを作成し、現在実行中のスクリーンセッションでエクスポートコマンドを実行します。

if [ -S "$SSH_AUTH_SOCK" ] && [ ! -h "$SSH_AUTH_SOCK" ]; then
    ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock

それは「もし$SSH_AUTH_SOCKはソケット(-S)であり、シンボリックリンクではありません(! -h)、既知のパスに新しいシンボリックリンクを作成します。すべての場合において、SSH_AUTH_SOCKは既知のパスを指します。

! -hこれを複数回実行すると、循環参照の作成が回避されます。

また、byobuを使用すると、設定ファイルを編集する必要なく、これが自動的に行われます。

私がこれで見つけた唯一のバグ(byobuにもあります)は、2番目のssh -AまたはForwardAgent接続すると、最初のソケットが上書きされ、最初の接続の前に2番目の接続を閉じると、正常なソケットだけが失われます。

25
Collin Anderson

「ssh -t some.machine screen -R」はbashを実行しないため、シンボリックリンクが作成されている.bash_profileスクリプトは実行されません。

あなたは試すことができます:ssh -t some.machine bash -c "screen -R"

(もちろん、シェルとしてbashを使用していると仮定します)

編集:その「答え」は実際には 上記の最初の答え へのコメントです:)

4
blop

Autosshが必要だと思います。私はこれを何年も使用しており、画面と組み合わせることで、すべての端末セッションを完全にポータブルで透過的にします。 Lappyを閉じて新しい場所に移動し、Lappyを開くと、すべての画面とネストされた画面が自動的に接続されます。私はそれについてもう考えていません。

http://www.linux.com/archive/feature/1341

基本です...私は、指定されたホストの.screenrcでプロセスを自動化するために、lilスクリプトをRubyで作成しました。 (私のssh転送も行うので、これらすべての異なる場所で、サーバーを介して接続をトンネルできます)

autosshディストリビューションには、rscreenと呼ばれるプログラムがあるはずです(そして..あります!)

#!/bin/sh                                                                       
#
# sample script to use autossh to open up a remote screen
# session, or reconnect to an existing one. 
#
# $Id: rscreen,v 1.4 2002/05/07 17:54:13 harding Exp $
#
if [ "X$1" = "X" ]; then
    echo "usage: `basename $0` <Host>"
    exit 1
fi

if [ "X$SSH_AUTH_SOCK" = "X" ]; then
    eval `ssh-agent -s`
    ssh-add $HOME/.ssh/id_rsa
fi

#AUTOSSH_POLL=600
#AUTOSSH_PORT=20000
#AUTOSSH_GATETIME=30
#AUTOSSH_LOGFILE=$Host.log
#AUTOSSH_DEBUG=yes 
#AUTOSSH_PATH=/usr/local/bin/ssh
export AUTOSSH_POLL AUTOSSH_LOGFILE AUTOSSH_DEBUG AUTOSSH_PATH AUTOSSH_GATETIME 

autossh -M 20004 -t $1 "screen -e^Zz -D -R"

これは、ssh /画面の問題に役立ちます

最後に、ssh-agentを実行し続けるために、私はシェルヘッドの一種なので、キーチェーンを使用します... OSXには、エージェントを維持するために利用できるものがあると思います...

3
chiggsy

これが私が使う方法です:

SOCK=$(Sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep SSH_AUTH_SOCK) ; eval $SOCK ; export SSH_AUTH_SOCK
DISP=$(Sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep DISPLAY) ; eval $DISP ; export DISP

私は通常、これらのコマンドでエイリアスまたはシェル関数を設定します。

function ssh-screen-auth() {
  SOCK=$(Sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep SSH_AUTH_SOCK)
  eval $SOCK
  export SSH_AUTH_SOCK
  DISP=$(Sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep DISPLAY)
  eval $DISP
  export DISPLAY
}

正規表現 'screenr | DR)'を、画面を再接続するために使用する正確なコマンドに適合させる必要がある場合があります。

  • 最初の行は、入力した「screen -r」コマンドのプロセス空間にある---(SSH_AUTH_SOCK環境変数を読み取り、更新します現在のシェルの値。
  • ssh -X」を使用してX11接続を転送する場合、2行目が必要です。これは[〜#〜] display [を更新します〜#〜]同じように変数。

私の方法の警告:コンピューターで実行中の別の "screen"コマンドがある場合、問題が発生する可能性があります。

3
Farzy

@apinsteinが。bashrcに使用しているバリエーションを使用しています。

case "$TERM" in
    screen)
           export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
        ;;
         *)
           if [[ -n "$SSH_AUTH_SOCK" ]]; then
               ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
           fi
        ;;
esac

これは、スクリーンセッションで実行されているすべてのアプリで機能します。これは、スクリーンセッションのすべての新しいシェルで機能します。既存のシェルの場合は、ホストシェルでexport SSH_AUTH_SOCK=~/.ssh/ssh_auth_sockを実行して動作させる必要があります。

追伸これを独立した回答として追加して申し訳ありませんが、@ apinsteinの回答に基づいています。 stackoverflowのコメントはコードブロックをサポートしないため、これを行う必要がありました。

1

私は通常、職場のさまざまなサーバーで長期間(6か月以上)のセッションを実行し続けます。したがって、繰り返し再接続して実行可能なssh転送エージェントを使用することには問題があります。これは私が私のシステムで設定したものです:

if [ -z "${STY}" -a -t 0 -a X${USER} = Xmyusername ]; then
    reattach () {
        if [ -n "${SSH_AUTH_SOCK}" ]; then
            ln -snf "${SSH_AUTH_SOCK}" "${HOME}/.ssh/agent-screen"
            SSH_AUTH_SOCK="${HOME}/.ssh/agent-screen" export SSH_AUTH_SOCK
        fi
        exec screen -A -D -RR ${1:+"$@"} ;
    }

    screen -wipe
    echo 'starting screen... (type Cntl-C to abort)'
    sleep 5 && reattach
fi

画面を開始/再接続せずにリモートサーバーにログインするだけの場合、2つの「ソケット」があり、1つはscreenで使用され、もう1つは新しいシェルで使用されます。 「スタートアップ」セッションは2つにすべきではありませんが、2番目のセッションはreattach -S newを使用して開始できます。この状況では、エージェントは~/.ssh/agent-screen値と共有されます。機能している転送エージェントを元に戻すには、デタッチし、再度ログインします。X${USER} = Xmyusernameは、同じサーバーのSudoを通じてコードが呼び出されないようにします。

1
Arcege

これらはすべて本当に良い答えです。新しいsshセッションを開始して画面を再接続した後、ルートbash環境の内容に基づいてSSH_AUTH_SOCK環境変数をリセットします。私はsvnを使用しているときにssh-agentへのアクセスのみを必要とするため、これらのシェルで必要に応じてSSH_AUTH_SOCKをリセットするだけです。

これはprocファイルシステムを使用するため、Linux固有です。私は、自分だけがアクセスできるヘッドレスLinuxボックスでのみこれをテストしました。他の環境で動作させるには、多少の調整が必要になる場合があります。

SSH_AUTH_SOCKをリセットするには(これはエイリアスにすることができます)。

$ . ~/bin/screen_auth.sh

screen_auth.shは次のようになります

# Find the pid of PuTTY's bash Shell
tty=`who | awk '/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ { print substr($2, 5) }'`
pid=`ps -t $tty | grep bash | awk '{print $1}'`
# Find the SSH_AUTH_SOCK variable in its enviornment
auth_sock=`xargs --null --max-args=1 echo < /proc/$pid/environ | grep SSH_AUTH_SOCK`
eval "export $auth_sock"
0
iain

私は他の答えをざっと見て、私のものを見つけることができませんでした。これが私が使うものです。次の内容のファイル~/.screenrc-wrapperを作成します。

escape ^xx
bindkey ^Ad detach

そして、これを~/.bashrc(または、使用する場合は~/.zshrc)に追加します。

  if echo $TERM | grep -v 'screen' && ! screen -x -SU wrapper; then
      if echo $TERM | grep -v 'screen' && ! screen -x -SU main; then
      screen -c ~/.screenrc-wrapper -SU wrapper ssh-agent screen -SU main
      fi
  fi

この方法では、2つのスクリーンセッションを使用します。1つは「ラッパー」で、もう1つは内部です。これにより、ログアウトした場合でも後者が存続し、ssh-agentがオンのままになります。もう1つの素晴らしい機能は、ウィンドウの設定を記憶することです。分割ウィンドウを使用する場合、非常に便利です。

この機能のコンテキストは、my dotfiles にあります。

0
d33tah

画面とssh-agentの友達を作ろう で提案されているように、このシンプルな1ライナーを試してみました。

Targetへの初回ログイン。1回だけ実行する必要があります。

ssh -o StrictHostKeyChecking=no -C <userid>@<server>

初回起動画面..一度だけ実行する必要があります。

eval `ssh-agent`; /usr/bin/screen -D -R -h 10000
ssh-add

デタッチまたは切断されている場合は、このコマンドを使用してログインし、終了画面に接続します。

ssh -o StrictHostKeyChecking=no -C -t <userid>@<server> ssh-agent /usr/bin/screen -D -R -h 10000
0
Sharjeel

上記のすべてのソリューションは、(複数のSCREENセッションまたは複数のSSH接続のいずれかで)競合状態に悩まされています。私が考えることができる唯一の普遍的なソリューションは、最初にSSH_AUTH_SOCKをscreen -rのSCREENサーバープロセスにプッシュしてから、各対話型の非組み込みコマンドの前にBASHセッション内にプルすることです。残念ながら、SCREENとBASHはそのような種類の問題を認識せずに設計されているため、適切に実装するのはかなり困難です(ただし、両方のプロジェクトに機能のリクエストを投稿するのが遅くなることは決してありません)。私の試みは、ここにあるBASHセッションのこの問題を克服するために行われました:

インストールするには:

  1. 両方のスクリプトを$HOME/binに入れ、実行可能ビットを追加します。
  2. pATHで$HOME/bin/usr/binの前にあることを確認してください:

    PATH = $ HOME/bin:$ PATH

  3. これを.bashrcに追加してください:

    ソース$ HOME/bin/screen-helperセットアップ

これで、SSHセッション内でSCREENセッションを作成し、切断、切断、接続、再接続を試行できます。うまくいけば、ssh-add -lがキーを正しく表示するはずです。

0
midenok