仙石浩明の日記

2006年9月27日

ssh-agent を screen の中から使う方法

GNU screenバグ報告を行なう ついでに screen-devel ML に参加したら、 次のようなメールが ML に流れてきた:

There is a much simpler solution
http://www.2701.org/archive/200406150000.html

The key is that SSH_AGENT need not point to a socket, it can point to a symbolic link to a socket.

なるほど~

ssh-agent と通信するための UNIX ドメイン ソケット を指す (パス名固定の) シンボリック リンクを作るようにしておけば、 環境変数 SSH_AUTH_SOCK には、そのシンボリック リンクのパス名を 設定しておけば済むので screen の中で ssh を使うとき便利、 というわけである。 つまり、

senri:/home/sengoku % ssh asao
Last login: Sun Sep 10 08:24:20 2006 from senri.flets.gcd.org
Linux 2.6.16.28.

asao:/home/sengoku % echo $SSH_AUTH_SOCK
/tmp/ssh-chKJY25976/agent.25976
asao:/home/sengoku % screen -r

senri で ssh-agent を走らせておいて、 asao へ ssh でログインするさいに、 ForwardAgent を有効にしておくと、 上の実行例のように、SSH_AUTH_SOCK に UNIX ドメイン ソケットの パス名が設定され、このソケットを介して senri の ssh-agent と通信ができる。

ところが、前回のログイン時に使っていた screen を reattach すると、 screen の中では、SSH_AUTH_SOCK の値は、 前回のログイン時のパス名のままである:

asao:/home/sengoku % echo $SSH_AUTH_SOCK
/tmp/ssh-ptnuvb3346/agent.3346

ForwardAgent はログアウトと共に終了するので、 screen の中の SSH_AUTH_SOCK の値は、 ログインするごとに設定し直す必要がある。 これはとてもメンドクサイ。

ログインし直すたびに SSH_AUTH_SOCK の値が変化するから、 このような問題が起きるわけで、 SSH_AUTH_SOCK の値が常に同じなら、 reattach した screen の中でも同じ SSH_AUTH_SOCK の値を使い続けることができる。

すなわち、 SSH_AUTH_SOCK が直接 UNIX ドメイン ソケットを指し示すのではなく、 UNIX ドメイン ソケットを指し示すシンボリック リンクを作成しておいて、 SSH_AUTH_SOCK にはこのシンボリック リンクのパス名を設定しておけばよい。

さっそく ~/.cshrc に次の行を追加した:

set agent = "$HOME/tmp/ssh-agent-$USER"
if ($?SSH_AUTH_SOCK) then
	if (! -S $SSH_AUTH_SOCK) unsetenv SSH_AUTH_SOCK
endif
if ($?SSH_AUTH_SOCK) then
	if ($SSH_AUTH_SOCK =~ /tmp/*/agent.[0-9]*) then
		ln -snf "$SSH_AUTH_SOCK" $agent && setenv SSH_AUTH_SOCK $agent
	endif
else if (-S $agent) then
	setenv SSH_AUTH_SOCK $agent
else
	echo "no ssh-agent"
endif
unset agent

私は、かれこれ 20年近く csh をログイン シェルとして使い続けてきているので、 ~/.cshrc なのだが、今となっては (極めて?) 少数派だろう。 bash など、sh 系をログイン シェルとして使っている場合は、 ~/.profile などに

agent="$HOME/tmp/ssh-agent-$USER"
if [ -S "$SSH_AUTH_SOCK" ]; then
	case $SSH_AUTH_SOCK in
	/tmp/*/agent.[0-9]*)
		ln -snf "$SSH_AUTH_SOCK" $agent && export SSH_AUTH_SOCK=$agent
	esac
elif [ -S $agent ]; then
	export SSH_AUTH_SOCK=$agent
else
	echo "no ssh-agent"
fi

などと書いておけばよいだろう。

Filed under: プログラミングと開発環境 — hiroaki_sengoku @ 07:56

2件のコメント »

  1. ssh-agentを複数の仮想端末から使う方法

    「ssh-agent を screen の中から使う方法」にインスパイヤされた話。僕が家で使っているPCはWindowsで動いていまして、 Cygwin, CygTerm, PuTTY日本語版, zshを使っています。 SSHでサーバに接続したときは接続先でscreenを動かすんですけど、ローカルでは複数のPuTTYを動か…

    コメント by blog.fuktommy.com — 2006年9月28日 @ 00:30

  2. 二重login shell対策の/tmp/*チェックだと思いますが、それだとシステム構成に影響されるので、私は
    test ! -L “$SSH_AUTH_SOCK” -a -S “$SSH_AUTH_SOCK” && ln …
    としています。
    あと、二回ログインして後から入った方で抜けると壊れるため、netstat -lnx からソケットを拾いなおして再リンクするスクリプトを作っておくと重宝します(よくやってしまう)。

    コメント by tai — 2006年9月28日 @ 15:02

この投稿へのコメントの RSS フィード。

コメントする