rcmdnk's blog

Permission: A Guide to Generating More Ideas, Being More of Yourself and Having More Fun at Work

以前、Macでのcronジョブや外部からsshでログインして作業してる時に、 直接Macで作業を行うときと外部からログインした時等で違いがあって困ったことがあって、 その時はMacでssh時の’Permission denied (publickey).’の解決法 に在る方法で解決しました。

Yosemiteにアップデート後は初めて外からログインして作業してみようとした所、 上で使ってるディレクトリが無いと言って設定が出来ませんでした。

Yosemiteへのアップデートで少しその辺のディレクトリの作り方が変わった模様です。

Mavericks以前で使えた方法

問題は、Macでは一度通常どおり端末でログインを行うと、 ssh-agentがlaunchd1 によって立ち上げられ、ssh鍵のパスフレーズによる認証などを管理してくれます。

さらにMacではそのパスフレーズをKeyChainで管理してくれるため、 一度パスフレーズを入力すると、その後Mac自体を再起動したりしても ずっとパスフレーズを打たずに鍵を使える様になります。

ただし、これらはcronジョブや外部からsshでログインした場合には使えません。

その原因は

SSH_AUTH_SOCK

という環境変数がMacで直接ターミナルを立ち上げた時だけ設定されるからです。

このSSH_AUTH_SOCKはMavericksまでは

/tmp/launch-XXXXXXXXXX/Listeners

といったファイルが指定されていました(XXXXXXXXXXはランダムな文字列)。

Macでssh時の’Permission denied (publickey).’の解決法 に書いてありますが、 この環境変数さえ正しく設定すればssh-agentを使ってパスフレーズなどを 解決してくれることがわかったので、 後はログイン時にこれを正しく設定できる様になれば良いだけです。

launch-XXXXXXXXXXと言ったディレクトリはLaunchdによってプロセスを立ち上げる度に それぞれ毎に作られるので 複数存在してる時もあります。

また、たまにListenersのあるディレクトリも複数あったり。 (クラッシュした時に残ってたとか?かもしれません。)

いずれにしろ正しく設定できたかどうかはssh-add -lで確かめられるので、 これを使って古いものがあっても正しく今動いてるssh-agentに対応する 物を取ってくるようにします。

ssh-add -lはssh-agentに登録されてる認証の一覧を表示するもので、 もしSSH_AUTH_SOCKが正しく設定されていると 鍵があれば鍵を表示して返り値0、 鍵がないとThe agent has no identities.と言って 1を返します。

一方、SSH_AUTH_SOCKが正しく設定されてないと

Could not open a connection to your authentication agent.

と言って2を返すので、これを使います2

obsolete SSH_AUTH_SOCK setting
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# SSH_AUTH_SOCK
if [ "$SSH_AUTH_SOCK" = "" ];then
  sock_tmp=(`ls -t /tmp/launchd*/Listeners`)
  for s in ${sock_tmp[@]};do
    export SSH_AUTH_SOCK=$s
    ssh-add -l >& /dev/null
    ret=$?
    if [ $ret -eq 0 -o $ret -eq 1 ];then
      break
    fi
    unset SSH_AUTH_SOCK
  done
  unset sock_tmp
fi

これを.bashrc等に書いておくと外からログインした時やCronジョブの時でも きちんと設定してくれます。

ただし、Macをリモートで立ち上げて一度も直接ログインしてないと使えません。 ただ、Macをサーバーとして使わない限りそんなことは無いのでこの程度で。 Macを完全にサーバーっぽく使う場合には前に書いたページにあるように 自分でssh-agentを起動させてあげる必要が有ります。 (ssh-agentを余計に起動させない様にしたりきちんと消したり管理するのがちょっと面倒。)

Yosemite以降で以使う方法

上のスクリプトを設定したままで外からログインしてみたところ、

ls: /tmp/launchd*/Listeners: No such file or directory

みたいなエラーがログインするたびに出るようになってしまいました。

見てみると、/tmp/launchd-XXXXXXXXXX/というディレクトリは無くなって、 代わりに/tmp/com.apple.launchd.XXXXXXXXXX/というディレクトリが出来ていました。 その内の1つにListenersもあります。

どうもLaunchdが作るテンポラリーなディレクトリの名前を変えたようで、 これに合わせてスクリプトをアップデートしてあげる必要が有ります。

SSH_AUTH_SOCK setting for Yosemite or later
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# SSH_AUTH_SOCK
if [ "$SSH_AUTH_SOCK" = "" ];then
  sock_tmp=(`ls -t /tmp/com.apple.launchd.*/Listeners 2>/dev/null`)
  if [ ${#sock_tmp[@]} -eq 0 ];then
    # For Mavericks or older OS X
    sock_tmp=(`ls -t /tmp/launchd-*/Listeners 2>/dev/null`)
  fi
  for s in ${sock_tmp[@]};do
    export SSH_AUTH_SOCK=$s
    ssh-add -l >& /dev/null
    ret=$?
    if [ $ret -eq 0 -o $ret -eq 1 ];then
      break
    fi
    unset SSH_AUTH_SOCK
  done
  unset sock_tmp
fi

とこんな感じでcom.apple.launchd.XXXXXXXXXX/を見に行けば良いだけ。 古いMacでも使うかもしれないので、 互換性のためそこになければ/tmp/launchd-XXXXXXXXXX/も見るようにしています。

これを.bashrcから呼ぶ様にしてあげたらYosemiteでも上手く行くようになりました。

Sponsored Links
  1. launchd - Wikipedia

    Diversion into MacOSX launchd & ssh-agent : The Grumpy Troll: http://bridge.grumpy-troll.org/2011/07/diversion-into-macosx-launchd–ssh-agent/

  2. 前に書いた時は単に0の時だけ取ってきてましたが、 これでも鍵がない時には設定しない、ということなので、 外からログインして居る時に鍵を新たに追加したい、とかしない限りは 問題ありません。

    でも、そういうこともあるかもしれないのできちんとアップデート。

Sponsored Links

« YosemiteからRuby1.8が削除されたのでAppleScriptでのウィンドウのサインズ変更の取り扱いを変更した cVim: Google ChromeのVimperatorみたいな拡張 »

}