非常に奇妙な問題が発生しています。SSH (公開鍵認証を使用) 経由でリモート ホスト上でコマンドを実行する小さな bash スクリプトを作成しました。
このスクリプトをコマンドラインから手動で実行すると正常に動作しますが、/etc/cron.hourly に配置するとPermission denied, please try again.
エラーが発生して失敗します。
- スクリプト内でキーを明示的に設定します
ssh -i /root/.ssh/id_rsa user@remote "command"
。 - スクリプトはルートとして実行されています(
echo `id` > /tmp/whoami.log
再確認のために を追加しました)。 - SSH キーはパスワードで保護されていません...
システムは Ubuntu 12.04 サーバーであり、トラブルシューティングのためにリモート側にアクセスする余地はあまりありませんが、前述したように、ssh を手動で実行するか、コマンドラインから同じ bash スクリプトを実行すると機能します。
なぜこのようなことが起こるのか、またはこれを修正するにはどうすればよいのか、何かご存知ですか?
アップデート
結局私は間違っていたようで、SSHキーはだったパスワードで保護されているため (キーチェーンで ssh-agent をロード)、スクリプトからは失敗しますが、bash セッションから実行すると失敗しません。. ~/.keychain/$HOSTNAME-sh
スクリプトに追加することで、問題は解決しました (正しい方向を示し、包括的な回答を提供してくれた @grawity に感謝します)。
答え1
対話型コマンドとcronジョブは異なる環境で実行されます。特に、対話型セッションでは、SSH エージェントが実行されているか、Kerberos TGT が保存されている可能性があります。ssh
注文の認証方法により、できないオプションを追加したからといって、キーが使用されるわけではないことに注意してください-i
。
SSHエージェントが実行中の場合、
ssh
クライアントは常にエージェントキーを試します前に明示的に指定されたキーを使用します。ネットワークがKerberosを使用しており、Kerberos TGTが存在する場合、OpenSSHはそれを使用します。前に公開鍵認証を試行します。
あなたの環境については何も知りませんが、これらの可能性は両方とも簡単に確認できます。
コマンドの前に
unset SSH_AUTH_SOCK
と を追加し、unset KRB5CCNAME
ssh
それから変更したスクリプトを手動で実行します。これにより、スクリプトはエージェントまたは Kerberos チケットを参照できなくなり、明示的に指定されたキーのみが使用されます。
-v
オプションを に追加しますssh
。これにより、認証がどのように行われるかについての詳細が表示されます。
-oIdentitiesOnly=yes
コマンドに以下を追加することもできますssh
。指定されたキーを使用するように強制する。
cronからエージェントにアクセスするヒントを追加するとさらに良いでしょう
エージェントは通常、対話型ログイン セッションと密接に結びついているため、これは一般的には推奨されません。特に、エージェントはログイン時にのみ起動され、ログアウト時に強制終了されます。また、SSH キーを実際にロック解除するにはパスワードが必要です (パスワードで保護されている場合)。
「キーチェーン」について言及されていますが、これはOS Xのプログラムですか、それともLinuxのスクリプトですか?(Mac OS Xのアーキテクチャについてはあまり詳しくありませんが、私の知る限りでは、多くのcronjob からユーザーの ssh-agent にアクセスするのが難しくなります...)
答え2
この問題の別の回避策は、ローカルの絶対パスでファイルまたはコマンドを実行する代わりに、ローカル ボックスに ssh するように cron を設定し、ssh コマンドを実行することです。これにより、KRB5CCNAME がキャッシュされ、/path/command が機能しない場合でも機能します。
# Fails:
0 * * * * /home/user/sshscript.sh
# Works:
0 * * * * /usr/bin/ssh user@localhost /home/user/sshscript.sh
#!/bin/bash
# Works:
unset SSH_AUTH_SOCK
unset KRB5CCNAME
/usr/bin/ssh user@localhost /home/user/sshscript.sh
答え3
使用できますssh-cronSSH エージェントを使用して、SSH キーを公開せずにサーバーを保護するためのスケジュールされた SSH 接続を設定します。
答え4
次のように crontab でスクリプトまたはコマンドを実行できます。
0 * * * * bash -c -l "/home/user/sshscript.sh"
または
0 * * * * bash -c -l "ssh root@yourhost 'echo $HOSTNAME'"