はじめに
- 接続先サーバ側を変更できるのであれば公開鍵認証方式をおとなしく使いましょう。
- どうしてもパスワード認証方式を使わないといけない場合は、接続クライアント側にソフトウェアをインストール可能ならSSHPassを使いましょう。巷にはexpectコマンドを使った方法があふれていますが、インストール可能な環境ならSSHPassのほうが良い (参考: sshにパスワードで自動ログインするならexpectよりもsshpassを使おう
- サーバ側もクライアント側も変更がどうしてもできない…残念ながら大人な事情でそういうこともあります。そんな時は本記事が参考になるかと思います。
実現方式
sshにはSSH_ASKPASSという仕組みがあります。以下、引用。
SSH_ASKPASS
パスフレーズを入力する際、ssh が端末から起動されているとssh はパスフレーズをその端末から要求します。ssh が制御できる端末を持っておらず、環境変数DISPLAY およびSSH_ASKPASS が設定されている場合、ssh はSSH_ASKPASS によって指定されるプログラムを起動し、X11 ウインドウを使ってパスフレーズを要求します。これはssh を.xsessionやそれに類するスクリプトから呼び出す際にとくに役に立ちます。(マシンによっては、これがうまく動くためには標準入力を/dev/nullにリダイレクトする必要があるかもしれません)
これはGUIからSSH接続のパスワードを入力させてそれを受け取ることを想定した仕組みですが、これを利用してパスワードをシェルから渡すこともできるわけです。
具体的には環境変数 SSH_ASKPASSに、パスワードを返すプログラム(シェルスクリプト)を設定すればOK。また、環境変数 DISPLAYにはダミーの値を設定しておけばOKです。
具体的な実装例
SSHで接続してls -al
を実行するだけの例です。
#!/bin/bash
# 接続先情報
SSH_USER=test
SSH_PASS=mypass
SSH_HOST=your_ssh_server
REMOTE_CMD="ls -al"
# 後述のSSH_ASKPASSで設定したプログラム(本ファイル自身)が返す内容
if [ -n "$PASSWORD" ]; then
cat <<< "$PASSWORD"
exit 0
fi
# SSH_ASKPASSで呼ばれるシェルにパスワードを渡すために変数を設定
export PASSWORD=$SSH_PASS
# SSH_ASKPASSに本ファイルを設定
export SSH_ASKPASS=$0
# ダミーを設定
export DISPLAY=dummy:0
# SSH接続 & リモートコマンド実行
exec setsid ssh $SSH_USER@$SSH_HOST $REMOTE_CMD
[root@6a6d8eb6ad44 ~]# ./sshauto.sh
[root@6a6d8eb6ad44 ~]# total 12
drwxr-sr-x 2 test test 4096 Jan 23 16:51 .
drwxr-xr-x 3 root root 4096 Jan 23 16:51 ..
-rw------- 1 test test 24 Jan 23 16:51 .ash_history
上記の実装例では、SSH_ASKPASS に設定するプログラムを$0
で自分自身を設定することで1ファイルで完結していますが、別のファイルでももちろん構わないです。
最後にもう一度書きますが、できるなら公開鍵認証方式をおとなしく使いましょう!!。