リモートマシンにsshを実行し、そこで次のようなコマンドを実行するbashスクリプトがあります。
ssh -nxv user@remotehost echo "hello world"
コマンドラインからコマンドを実行すると正常に動作しますが、crontabの一部として実行すると失敗します(errorcode = 255-SSH接続を確立できません)。詳細:
...
Waiting for server public key.
Received server public key and Host key.
Host 'remotehost' is known and matches the XXX Host key.
...
Remote: Your Host key cannot be verified: unknown or invalid Host key.
Server refused our Host key.
Trying XXX authentication with key '...'
Server refused our key.
...
ローカルで実行する場合、私はrootとして機能し、crontabはrootとしても機能します。 crontabとコマンドラインから「id」を実行すると、まったく同じ結果が得られます。
$ id
> uid=0(root) gid=0(root) groups=0(root),...
ローカルマシンからcrondを実行しているマシンにsshを実行します。 crondマシンおよびスクリプトが接続するその他のマシンにsshするためのsshキーと資格情報があります。
PS。ルートとして何かを実行するのは悪い/間違っているなどと尋ねたり、不平を言ったり、コメントしたりしないでください。これはこの質問の目的ではありません。
通常、ローカルマシンからcrondを実行しているマシンにsshを実行すると、秘密鍵がssh-agentに読み込まれ、接続を介して転送されると思います。したがって、コマンドラインからコマンドを実行すると、ssh-agentで秘密鍵が検出され、それを使用してリモートマシンにログインします。
Crondがコマンドを実行すると、ssh-agentにアクセスできないため、秘密鍵を使用できません。
Crondを実行しているマシンでrootの新しい秘密鍵を作成し、その公開部分をcrondにログインさせたいリモートマシンの適切なauthorized_keys
ファイルにコピーする必要があります。
keychain
痛みのない方法でこれを解決します。これはDebian/Ubuntuのリポジトリにあります:
Sudo apt-get install keychain
そしておそらく他の多くのディストリビューション(Gentooから発信されたように見えます)。
このプログラムは、何も実行されていない場合はssh-agent
を開始し、source
dのシェルスクリプトを提供して、現在のシェルをこの特定のssh-agent
に接続します。
bash
の場合、id_rsa
という名前の秘密鍵を使用して、.profile
に以下を追加します。
keychain --nogui id_rsa
これにより、ssh-agent
が開始され、再起動後の最初のログイン時にid_rsa
キーが追加されます。キーがパスフレーズで保護されている場合は、パスフレーズも要求されます。 保護されていないキーを使用する必要はもうありません!以降のログインでは、エージェントがエージェントを認識し、パスフレーズを再度要求することはありません。
また、.bashrc
の最後の行として次を追加します。
. ~/.keychain/$HOSTNAME-sh
これにより、シェルはkeychain
によって管理されているSSHエージェントに到達する場所を知ることができます。 .bashrc
が.profile
から供給されていることを確認してください。
ただし、cron
ジョブはまだこれを認識していないようです。解決策として、実際のコマンドの直前のcrontab
に上記の行を含めます。
* * * * * . ~/.keychain/$HOSTNAME-sh; your-actual-command
パスフレーズなしでSSHキーを公開しないでください。代わりに ssh-cron を使用してください。これにより、SSHエージェントを使用してタスクをスケジュールできます。
だから私も同様の問題を抱えていました。私はここに来てさまざまな答えを見ましたが、ここでいくつかの実験を行って、パスフレーズ、ssh-agent、およびcronを使用してsshkeyで動作させる方法を説明します。
まず、私のsshセットアップでは、bashinitスクリプトで次のスクリプトを使用します。
# JFD Added this for ssh
SSH_ENV=$HOME/.ssh/environment
# start the ssh-agent
function start_agent {
echo "Initializing new SSH agent..."
# spawn ssh-agent
/usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
echo succeeded
chmod 600 "${SSH_ENV}"
. "${SSH_ENV}" > /dev/null
/usr/bin/ssh-add
}
if [ -f "${SSH_ENV}" ]; then
. "${SSH_ENV}" > /dev/null
ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
start_agent;
}
else
start_agent;
fi
ログインするときにパスフレーズを1回入力すると、それ以降、ssh-agentを使用して自動的に認証されます。
Ssh-agentの詳細は.ssh/environmentに保持されます。そのスクリプトは次のようになります。
SSH_AUTH_SOCK=/tmp/ssh-v3Tbd2Hjw3n9/agent.2089; export SSH_AUTH_SOCK;
SSH_AGENT_PID=2091; export SSH_AGENT_PID;
#echo Agent pid 2091;
Cronに関しては、さまざまな方法で通常のユーザーとしてジョブを設定できます。 rootユーザーとしてcrontab-eを実行すると、rootユーザーのcronがセットアップされます。 crontab -u davis -eとして実行すると、ユーザーIDdavisとしてcronジョブが追加されます。同様に、ユーザーdavisとして実行し、crontab -eを実行すると、ユーザーIDdavisとして実行されるcronジョブが作成されます。これは、次のエントリで確認できます。
30 * * * * /usr/bin/whoami
これにより、whoamiの結果が30分ごとにユーザーdavisにメールで送信されます。 (私はユーザーdavisとしてcrontabe -eを実行しました。)
ユーザーdavisとして使用されているキーを確認しようとする場合は、次のようにします。
36 * * * * /usr/bin/ssh-add -l
それは失敗します、メールで送られたログは言うでしょう
To: [email protected]
Subject: Cron <davis@hostyyy> /usr/bin/ssh-add -l
Could not open a connection to your authentication agent.
解決策は、上記のssh-agentのenvスクリプトを入手することです。結果のcronエントリは次のとおりです。
55 10 * * * . /home/davis/.ssh/environment; /home/davis/bin/domythingwhichusesgit.sh
これにより、10:55にスクリプトが実行されます。先頭に注意してください。スクリプト内。 .bash initスクリプトと同様に、このスクリプトを私の環境で実行するように指示されています。