scpでファイル(ディレクトリ)名補完

sftpで補完が効かないと言っていたところ、scpでならできると教えてもらった。
調べてみると、秘密鍵を使ってやればできる様子。

実際に補完が効いているところ


$ scp HOST1:
Desktop/ SCRIPT/ documents/ public_html/ tmp/

秘密鍵について

ssh接続で使える認証方法の1つで、通常(?)はID名とパスワードを入力してログインするが、
秘密鍵を使う方法では、事前に公開鍵と秘密鍵のペアを作成しておき、リモートホストとローカルホストの公開鍵と秘密鍵が一致したらログインできるというもの。
普通にIDとパスワードで認証する方式より、秘密鍵を使う認証方式の方がセキュリテイ的に安全なものらしい。

秘密鍵パスフレーズについて

秘密鍵を作成するときに、パスフレーズを設定することができる。
パスフレーズを設定すれば、秘密鍵を使う際にパスフレーズが要求され、パスフレーズが一致しなければ、秘密鍵を使うことができない。
万が一秘密鍵が誰かに盗まれてしまった場合、パスフレーズが設定されていれば、秘密鍵を使うことができず、悪用されない。なので、パスフレーズを付けておいたほうがいいとのこと。
(パスフレーズはパスワードと同じもの。# パスフレーズの方がセキュリティ的に高いらしいが…よくわかってない)

ところで…、ちょこっと問題がある。
scpコマンドを使ったことがあればわかると思うが、
リモートホストで認証されるタイミングはscpコマンドを実行後である。
が、scpで補完が聞いて欲しいのは実行後でなく、実行前(入力中)である。

今回の秘密鍵を使う方法で、この問題を解決する方法は2つ。

1つ目のパスフレーズを設定しないのが一番簡単ではある。
セキュリティを考えるとよろしくないが…

2つ目のssh-agentを使う方法では、秘密鍵パスフレーズが設定してあっても大丈夫。
ssh-agentは秘密鍵パスフレーズを、ssh-agentを終了するまで預かってくれる。
ssh接続やscp,sftpなどで認証が必要になるとssh-agentが代わりに認証作業を行なってくれるため、パスワード、パスフレーズなどを入力することなく接続ができる。
秘密鍵よりも必要な操作は増えるが、一旦ssh-agentを起動すると終了するまでは秘密鍵パスフレーズを設定しなかったときと同じように扱える。
なので、セキュリティが気になる環境だったり、気になる人はこちらを使うほうがいいかもしれない。

秘密鍵の作成

秘密鍵を作成してから、秘密鍵を利用してログインできるようにする手順は

  • 秘密鍵の作成
  • 接続先ホストへ公開鍵を渡し、authorized_keysに追加
  • 秘密鍵を利用してログイン

となる。
秘密鍵パスフレーズを設定し、ssh-agentを使う場合は

というのが、秘密鍵を利用してログインの前に入る。

さて、
秘密鍵の作成には、ssh-keygenコマンドを使用する。

RSA暗号方式を使う場合は

$ ssh-keygen -t rsa
DSA暗号方式を使う場合は
$ sshkeygen -t dsa
作る鍵にコメントを付けることもできる、RSAとDSAと両方のケースを示しておく。

$ ssh-keygen -t rsa -C "comment" # commentがコメント部分
$ ssh-keygen -t dsa -C "comment" # C は大文字
RSAとDSAの違いはよくわかっていないので気になる場合は調べてください。

以下、RSA暗号方式を使って進めます。


$ ssh-keygen -t rsa
Enter file in which to save the key (/home/user01/.ssh/id_dsa): # 作成する鍵の名前、保存する場所についての指定。 指定しなければ()内のものになる
Enter passphrase (empty for no passphrase): # パスフレーズなしで使う場合は、なにも入力せずEnter
Enter same passphrase again: # パスフレーズの確認で再度同じものを入力
鍵を保存する場所は~/.ssh/の下のままの方が良さそう。
ここだと特別設定なしで秘密鍵を見つけてくれる。
それ以外の場所にすると、使うときに自分で秘密鍵の在り処を指定しないといけなくなるはず。
パスフレーズを設定する場合は5文字以上でないといけない様子。
4文字だと短いって怒られました。

きちんと作成できれば、~/.sshに<指定した名前>のファイル(秘密鍵)と<指定した名前>.pub(公開鍵)ができているはずです。


$ cd ~/.ssh
$ ls
出来ていない場合は、作成すディレクトリの指定を間違えたとかで失敗していると思うので確認する。
公開鍵はscpの接続先ホストに置くものなので、置きに行く。

$ sftp HOST1 # ここでは一旦IDとパスワードの認証…
$ cd .ssh
$ put <指定した名前>.pub # 自分で作成した鍵の名前で読み替えて下さい(念の為)
次にsshで接続先ホストに再度接続する

$ ssh HOST1
$ cd .ssh
$ cat <指定した名前>.pub >> authorized_keys # 利用していい公開鍵のリストに作成した鍵を追加する

ssh-agentを使う

秘密鍵パスフレーズを設定しなかった場合はここを飛ばして、次のscpでの補完をやってみるのところまで進んでください。

ssh-agentを起動して、秘密鍵パスフレーズを渡してあげましょう


$ exec ssh-agent $SHELL
$ ssh-add ~/.ssh/<作成した秘密鍵>
Enter passphrase for /home/user01/.ssh/<作成した秘密鍵>: # 設定したパスフレーズ
これでssh-agentに鍵をパスフレーズを渡すことができた。

scpでの補完をやってみる

さて、実際に補完が効くか試してみる。
…その前にssh接続が出来るかどうか試してみる。もちろんIDやパスワード、パスフレーズが要求されず、ログインできれば成功。


$ ssh HOST1
出来ただろうか。
出来たなら次が本題scpで補完が効くか試してみよう。

$ scp HOST1:[tab] # [tab]の位置でタブキーを押す
使用しているシェルによっては2回タブキーを押す必要がある。(bashとか)
接続先ホストのホームディレクトリにあるファイルが補完対象として表示されれば成功。

これで補完を使いながら、別ホストのファイルを移動してくることができる。
さらに、もともとsftpを使っていたのなら


$ scp -r HOST1:<ディレクトリ> .
のように、-r オプションを付けることで、再帰的にディレクトリをコピー(指定したディレクトリの中身全部をコピー)できる。