TL;DR
# Auto Start and/or Setup `ssh-agent`
# Usage (in `.bashrc`): `source $HOME/.ssh/chk_and_run_ssh_agent.sh`
if [ -z "$SSH_AUTH_SOCK" ]; then
# Check for a currently running instance of the agent
RUNNING_AGENT="$(ps -ax | grep 'ssh-agent -s' | grep -v grep | wc -l | tr -d '[:space:]')"
if [ "$RUNNING_AGENT" = "0" ]; then
# Launch a new instance of the agent
ssh-agent -s &> $HOME/.ssh/ssh-agent
fi
eval $(cat $HOME/.ssh/ssh-agent)
fi
【2020/09/17 追記・更新】
割と根本的な解決っぽいものを見つけたので大幅更新。
はじめに
これたぶん普通の使い方をしている人なら巡り逢わないトラブルじゃないかな、、、。
でも テレワーク(リモートワーク)が当たり前になりつつある昨今 、もしかしたら今後あなたも、このエラーに遭遇することがあるかもしれません。
ということでまずは、どのようなエラーが起きうるのか、それを示します。
Julia である特殊な条件下で、パッケージの更新(=Pkg REPL-mode で up
を実行)しようとしたとき、以下のようなエラーが出て失敗することがあります1(パス名やパッケージ名等は仮のものです):
$ julia
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.5.1 (2020-08-25)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |
(@v1.5) pkg> up
Updating registry at `~/.julia/registries/General`
Updating git-repo `git@github.com:JuliaRegistries/General.git`
Private key location for 'git@github.com': ~/.ssh/id_xxx_rsa
Private key location for 'git@github.com' [/path/to/userhome/.ssh/id_xxx_rsa]:
Private key location for 'git@github.com' [/path/to/userhome/.ssh/id_xxx_rsa]:
┌ Warning: Some registries failed to update:
│ — /path/to/userhome/.julia/registries/General — failed to fetch from repo
└ @ Pkg.Types /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/Types.jl:1122
Updating git-repo `https://github.com/someuser/OreorePkg.jl.git`
Private key location for 'git@github.com': ~/.ssh/id_xxx_rsa
Private key location for 'git@github.com' [/path/to/userhome/.ssh/id_xxx_rsa]:
Private key location for 'git@github.com' [/path/to/userhome/.ssh/id_xxx_rsa]:
ERROR: failed to fetch from https://github.com/someuser/OreorePkg.jl.git, error: GitError(Code:EAUTH, Class:Callback, Aborting, maximum number of prompts reached.)
起きていることを説明するとこんな感じ:
- パッケージを更新しようとしたら、ssh の private key2 の在処を聞かれた。
- ↑で正しいパス(この例だと
~/.ssh/id_xxx_rsa
)を入力しても繰り返し聞かれた。 - 挙げ句「更新に失敗した」「fetch 出来なかった」という警告やエラーが出て更新できなかった。
環境
- Linux/xxxux
- Ubuntu 19.04 で動作確認
- シェル:Bash
- 他でも同様
解決方法1
まずは冒頭に示したファイルを用意します(念のため↓に再掲)。
# Auto Start and/or Setup `ssh-agent`
# Usage (in `.bashrc`): `source $HOME/.ssh/chk_and_run_ssh_agent.sh`
if [ -z "$SSH_AUTH_SOCK" ]; then
# Check for a currently running instance of the agent
RUNNING_AGENT="$(ps -ax | grep 'ssh-agent -s' | grep -v grep | wc -l | tr -d '[:space:]')"
if [ "$RUNNING_AGENT" = "0" ]; then
# Launch a new instance of the agent
ssh-agent -s &> $HOME/.ssh/ssh-agent
fi
eval $(cat $HOME/.ssh/ssh-agent)
fi
2行目のコメントに書いた要領で、以下を .bashrc
に追記します3。他のログインシェルを利用している方は適宜読み替えたり上記ファイルも書き換えたりしてください。
# : 以下を末尾に追記
source $HOME/.ssh/chk_and_run_ssh_agent.sh
この状態でログインすると、以下のファイルが(存在しなければ自動で)作成されます(パス名・PID値等は仮です)。
SSH_AUTH_SOCK=/tmp/ssh-xxxxxxxxxxxx/agent.54320; export SSH_AUTH_SOCK;
SSH_AGENT_PID=54321; export SSH_AGENT_PID;
echo Agent pid 54321;
2つの環境変数が設定されていますが、最初の SSH_AUTH_SOCK
がポイント。これによって ssh-agent が正常に動いていてそれにアクセスする方法が提供されます4。
適切に設定できれば、そこにログインすれば普通にエラー無くJuliaでパッケージ更新できます。
実行例:
Julia側の追加対応
上記の通り、これでもう問題なく動くはずですが、場合によってはこれでも Julia でパッケージ更新しようとしたときに依然として同じエラーが出る可能性があります。
Julia 起動時に何らかの原因で SSH_AUTH_SOCK
環境変数が設定されなかった場合がそれに該当します。
でも環境変数が設定されていない状況で一度でもログインが出来ていれば、ssh-agent が起動しその情報を記したファイルが ~/.ssh/ssh-agent
にはできているはず。
なので、~/.julia/config/startup.jl
に以下の内容を記述(ファイルが存在しなければ作成)すればOK。
# :
ssh_agent_path = joinpath(homedir(), ".ssh", "ssh-agent")
if isfile(ssh_agent_path) && !haskey(ENV, "SSH_AUTH_SOCK")
open(ssh_agent_path, "r") do f
for line in eachline(f)
for sentence in split(line, ';')
if occursin('=', sentence)
key, value = strip.(split(sentence, '='))
ENV[key] = value
end
end
end
end
end
# :
解決方法2
【2020/09/17 補足追記】
以降は解決方法1を見つける以前の方法です。
暫定的な対処としては依然として有効なので、残しておきます。
このエラーに遭遇したら、パッケージ更新前にシェルで以下のような一連のコマンドを実行すればOKです:
eval $(ssh-agent) > /dev/null
ssh-add ~/.ssh/id_xxx_rsa
~/.ssh/id_xxx_rsa
の部分は先程例で示した private key のパスです。
このあと Julia の Pkg REPL で up
すれば何事もなかったようにエラー無く更新できます。
実行例5:
$ eval $(ssh-agent) > /dev/null
$ ssh-add -l # 登録されていないと↓のように表示される
The agent has no identities.
$ ssh-add ~/.ssh/id_xxx_rsa
Identity added: /path/to/userhome/.ssh/id_xxx_rsa (username@hostname)
$ ssh-add -l # 正常に登録されたら↓のように表示される
2048 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX username@hostname (RSA)
$ julia
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.4.0 (2020-03-21)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |
(@v1.4) pkg> up
Updating registry at `~/.julia/registries/General`
Updating git-repo `git@github.com:JuliaRegistries/General.git`
Updating git-repo `https://github.com/someuser/OreorePkg.jl.git`
Updating `~/.julia/environments/v1.4/Project.toml`
[no changes]
Updating `~/.julia/environments/v1.4/Manifest.toml`
[no changes]
(@v1.4) pkg>
更新時に private key location を聞かれることもなくなり、何の問題もなく更新できました!
解説
そもそもどういう状況のときになんでこんなエラーが発生するのか。
もし Julia が正しくセッティングされていれば、そもそもパッケージ更新時に ssh key を聞かれることすらありません。
このようなことが起きる条件・原因は、簡単にまとめると以下の通り:
- ssh 等でサーバや他のPCやVirtualBox等の上で動いているLinux(特に xubuntu 等 X Window System が動作している環境)に接続し、そこで Julia を実行している(※1)。
- Julia のパッケージ(またはパッケージレジストリ)が
https://github.com/〜
ではなくgit@github.com:〜
という ssh url でアクセスするよう設定されている(※2)。 -
ssh-agent
が起動していない、もしくは github にアクセスするための ssh private key がssh-add
で登録されていない。
※1 は、例えば Visual Studio Code の Remote Development プラグインで ssh 接続した先の Julia コードを開発・編集しようとしているときも当てはまります。
※2 がキーポイント。これは細かく言うとさらにいくつかのパターンがある6のですが、共通して言えることとして、以下の設定をした覚えがあるはずです:
-
ssh-keygen
コマンドで SSH Key を生成し、public key を github.com に登録した -
~/.ssh/config
に以下のような設定を記述した(多少の違いはあれど):
Host github github.com
HostName github.com
IdentityFile ~/.ssh/id_xxx_rsa
User git
この設定自体には問題がないのですが、Julia(の Pkg
モード)が github.com とやり取りする際、実はこのファイルを(直接は)参照していません。
git
コマンドを実行しているわけではなく LibGit2 というライブラリを介して Git 周りの処理をしているのですが、それが ~/.ssh/config
を見ておらず、ssh-agent というヘルパープログラムと鍵のやり取りをしているの(だそう)です。
ところが、X Window system の動いている Linux 環境に(ssh 等で)ログインした場合、そのシェル環境では ssh-agent が正常に動作していない、もしくは適切な private key が登録されていない状態になるのだそうです7。
それが原因となって、結果として Julia のパッケージの更新が失敗する、ということだそうです(ややこしい)。
ので、ssh-agent を適切に(自動)起動(させて ssh-add
コマンドで適切な private key を登録8)すれば動くようになる、ということです9。
別解
一応、もう1つ解決方法があります。
git で ssh の利用をやめる、という方法です。
そもそも github.com では実は ssh よりも https の利用を推奨 しています。
何らかの理由で「https プロトコルで git を利用できない(したくない)」ということでもなければ、ひょっとしたらその方が幸せになるかもです。
「リポジトリの remote url が ssh になっていたら https に変更する」「個人アクセストークンを取得する(オプション)」「.gitconfig
の設定を(再)編集する」等の作業は必要になってきます。
この記事の範囲を超えるので(実験もしてないので)興味のある方はご自分で試してみてください。
参考
- ssh-agent
- post #6 - Pkg.clone keeps asking for my SSH key
- Creating a personal access token for the command line - GitHub Help
- Setting up the SSH Agent - Visual Studio Code Remote Development Troubleshooting Tips and Tricks
-
Julia v1.5.1 での動作例を示しますが、Julia v1.x 全て同様です。 ↩
-
github.com に SSH Key を登録したときの、登録した public key じゃない方。「github.com に SSH Key を登録」の意味がわからない方はたぶんこの記事は意味を持たないと思います。 ↩
-
chk_and_run_ssh_agent.sh
の内容をそのまま.bashrc
に追記してももちろん構いません。あと 参考文献 では「.bash_profile
に追記する」とありますが、私が調査・実験した限りは.bashrc
の方がより適切に動作する模様です。 ↩ -
SSH_AGENT_PID
の方は読んで字の如く、今動いているssh-agent
のPIDです(それ以上の情報はありません(たぶん))。 ↩ -
julia コマンド実行前にシェル上で実行することが重要。なぜなら先述の通り「必要な環境変数が設定されること(された状態でパッケージの更新を行うこと)」が重要なので。記事修正前に 「Julia の shell mode(REPLで ;(セミコロン)キーを押す)で実行してもOK」 と書いてましたがウソでした💦 ↩
-
例えば、「1. オレオレパッケージ(公式パッケージレジストリに登録されていないパッケージ)を追加するときに、https ではなく
]add git@github.com:〜
のように ssh url で追加した場合」、「2. git で github.com にアクセスするときに 常に ssh url を使うよう設定されている場合(~/.gitconfig
で[url "git@github.com:"]
エントリを設定した場合)」など ↩ -
少し調べたところ、GUIでログインした場合には
/etc/X11/Xsession.d/90x11-common_ssh-agent
という初期化スクリプトが動いて適切な設定がされる(ので問題なく使える)ようです。そうでない場合はこれが動かず、他に適切に設定するスクリプトがない、ということのようです。 ↩ -
解決方法1では明示的に
ssh-add
コマンドを実行していません。本来はこれでOKで、gitクライアントがssh-agentにプライベートキーを要求したときに登録されていなければ自動で登録される仕組みになっています(はず)。 ↩ -
修正前に書いていた以下の脚注、自己解決しました(本記事の前半参照)→
ただ毎回これを実行するのはやや面倒ですよね…うまいこと自動化する方法があるんでしょうかね? セキュリティ的にも安心で良い自動化の方法があったらどなたか教えてください↩