暗号化の通信のできるSSHのプロトコルを使ってリモートサーバに接続するコマンド。
同様にSSHプロトコルを使うコマンドとしてはmosh,sshfs,rsync などがある。
$ ssh <user>@<hostname>
ちなみに似たようなコマンドとして、moshは
$ mosh <user>@<hostname>
<hostname>
と書いてある箇所はホスト名でもIPでも可。
<user>@
の部分はローカルホストのログインユーザ名と同じであるか、~/.ssh/config
にユーザ名が指定してあれば、省略可。~/.ssh/config
はssh
だけでなく、mosh
,sshfs
,rsync
コマンドからも参照される。
ssh
コマンドは、後ろにパラメータとしてコマンドを書けば、リモートでコマンドを実行してコマンドが終わったらすぐにSSHを切断させることもできる。リモートへの接続をそれほど意識せずに、実行したいコマンドの先頭にssh foohost
などと付けるだけでリモートでのコマンド実行に置き換わるイメージ。
## リモートのホームディレクトリで ls -al を実行$ ssh foohost ls -al## リモートの特定のディレクトリに移動してからで find を実行$ ssh foohost 'cd ~/foo/bar; find .'## リモートとローカルとでマシンが刻んでいる時間のずれを大雑把に確認$ ssh foohost date; date
リモートで実行したコマンドが終了コード0以外を返せば、sshコマンド自体もその終了コードを返す。でも、リモートで実行したコマンドが標準出力と標準エラー出力をしていると、それらは一緒くたになってローカルの端末に対して標準出力される。
$ ssh -p <port> <user>@<hostname>
ssh -i <private_key_file> <user>@<hostname>
moshは
mosh --ssh="ssh -i <private_key_file>" <user>@<hostname>
sshfsは
sshfs -oIdentityFile=<private_key_file> <user>@<hostname>:<remote_path> <local_path>
rsyncは
rsync -e "ssh -i <private_key_file>" <user>@<hostname>:<remote_path> <local_path>
以下のコマンドで作れる。
$ ssh-keygen -t rsa -b 4096 -C 'your_email@example.com'
保存先などを質問されるので、答えていく。保存先のデフォルトは~/.ssh/id_rsa
,~/.ssh/id_rsa.pub
になる。
cat ~/.ssh/id_rsa.pub | ssh <user>@<hostname> "bash -c \"if [ ! -d ~/.ssh ] ; then mkdir ~/.ssh; fi; if [ -f ~/.ssh/authorized_keys ] ; then cat >> ~/.ssh/authorized_keys; else cat >> ~/.ssh/authorized_keys2; fi\""
このコマンドを実行すると、公開鍵がリモートのサーバに設置される。リモートのサーバにとって初めての公開鍵であれば、パーミッションとかを調整する必要があるかもしれない。ファイル名がauthorized_keys
だったりauthorized_keys2
だったりするのはよくわからない。
ssh
のオプションの中でbash
を起動しているのは、FreeBSDのサーバなどでデフォルトのシェルがcshの場合に、if
の構文が違っていて動かないので、bashを強制するため。
sshコマンドでは、エンターを押した直後に~.
と入力と切断される。エンターを押した直後の~
はssh接続自体へのコマンドのプレフィックスとなる。エンターの直後に~
自体を端末に入力するには~~
と2回入力する。
moshコマンドでは、Ctrl+^ .
と入れると、エンターの直後でなくても強制切断される。
クライアント側(接続元)の~/.ssh/config
に以下を記述する。
Host * ServerAliveInterval 60
ポートを待ち受ける方のホストの/etc/ssh/sshd_config
に以下を書いておく。
GatewayPorts yes
外部からファイアウォールの内側にあるローカルホストの22番に接続できるようにしようと思って、以下のコマンドを実行しても、上記の設定がリモートホスト(remoteA)にないと、8022番ポートに接続できるのは、リモートホスト(remoteA)の中からのみで、第三のホスト(remoteB)からはremoteAの8022番ポートに接続できない。
ssh -R 8022:localhost:22 remoteA
イメージ図
/------------\ /-----------\| remoteA | | remoteB || | | || port:8022 | | |\-----||-----/ \-----------/ || ||/-----||-----\| port:22 || || Local |\------------/
iptablesなどでポートが閉じられていたら当然外部からは接続できないので、iptablesの設定も合わせて確認しておくこと。
-L
を使う場合は、上記を設定しても外部からローカルの待受ポートに接続できない。ローカルの待受ポートはデフォルトではローカルからしか接続できないようになっている。外部からも接続できるようにするには、上記設定に加え、sshコマンドのオプションに-g
を付ける必要がある。さらに
ssh -L 8022:localhost:22 -g remoteA
sshfs
コマンドを使う。このコマンドはリモートのファイルシステムのルートまたは特定のディレクトリ配下を、ローカルの任意の場所にマウントする。例えば、リモートのファイルをいちいちダウンロード・アップロードしなくても直接ローカルのエディタで編集することできたりする。
ssh
コマンドの最後にコマンドを書けばよい。
$ ssh <user>@<hostname> ls -al
複数のコマンドを使ったり、パイプを使ったりしたければ、コマンド全体をシングルクオートかダブルクオートで囲む。
## リモートの result.txt に結果を保存$ ssh <user>@<hostname> "foo | bar > result.txt"## ローカルの result.txt に結果を保存$ ssh <user>@<hostname> "foo | bar" > result.txt
$ ssh <user>@<hostname> tar cvzf - <target remote directory> > <local tar file name>
リモートでtarを実行してファイルに書き出すのではなく標準出力に出して、それをsshでそのままローカルに転送し、ローカルでファイルに書き出している。
$ tar czf - <target local directory> | ssh <user>@<hostname> "cat > <remote tar file name>"
途中で途切れてしまった場合に中途半端なアーカイブファイルがリモートに残ってしまうので、いったん一時ファイルに書き出してからリネームしたほうがいいかもしれない。
$ tar czf - ローカルのバックアップ対象ディレクトリ | ssh リモートホスト名 "cat > リモートの一時ファイル名 && mv リモートの一時ファイル名 リモートの保存先tarファイル名"
リモートのファイルの存在確認をするとりあえずの方法の例
if ssh REMOTE_HOST test -e REMOTE_TARGET_FILE_PATH; then # ファイルが存在する場合の処理fi
ただ、これだとssh接続に失敗した場合には存在しない扱いになってしまう。
sshセッションが切れたときに自動で再接続してくれるツール。moshを使っていれば問題ないが、SSH port forwarding を使っている場合は、moshが対応していないので、このツールが便利かもしれない。
モバイル環境に強くしたssh。
mosh
参照。