Dec 24, 2016
GitHubが落ちてても慌てずに済む、SSHとGitだけでのPush/Pull
このエントリはGit Advent Calendarとのクロスポストです。(→Qiitaの方の投稿)
今日の記事では、「SSHって何?」や「SSHは知ってるし時々使うけど、普段そんなに使う機会は無い」くらいのレベルの方を対象に、SSHとGitの組み合わせだけでこんな事もできるんですよ!という事をご紹介します。アドベントカレンダー的には最後の方の日なのに初心者向けの話で恐縮ですが、まあせっかくなのでおつきあい下さい。
GitHubが落ちて困った!
日頃Twitterを見ていると、GitHubのサービスが停止する度に阿鼻叫喚の地獄絵図が繰り広げられている印象があります。
「デプロイしたいプロダクトの依存ライブラリがGitHubにあるのでデプロイできない」とか、「GitHub上のIssueでタスク管理をしているのでタスクを確認できない」とか、そういう事については確かにどうしようもないです。
が、単に「中央リポジトリがGitHubにあるせいでPushもPullもできない」という話なら、わざわざ自分でGitLabを立てたりBitBuckets等に引っ越したりしなくても、お互いのコンピューターやあるいはどこかのサーバーにSSH接続さえできれば充分だったりします。
SSH越しにお互いにPullしあってみよう
筆者が東京に来てすぐの頃、会社の事務所のインターネット回線がまだ不通なせいで、メンバーみんながウィルコムの回線1本にぶら下がって帯域をシェアするという事をしていました。そんな状況では、とてもじゃないですがインターネット越しの中央リポジトリの利用なんて無理でした。GitHubが落ちた!という時に状況としては似ています。
こういう状況でも、幸いなことに我々はお互いの作業の成果を共有しながら開発を進めらました。何故かというと、各人の作業環境でsshdを立てて、お互いのPCにリモートログインし合うことができたからです。
SSHって?
SSHは「Secure Shell」の略で、ネットワーク越しに別のコンピュータに接続してログインし、主にコマンド操作でそのコンピュータをリモート操作するという仕組みです。主にサーバーを操作するために使われる事が多いです。
とはいえサーバー操作の専用の物というわけではなく、手元のPCにSSHサーバーをインストールして起動しておけば、別のPCからあなたの手元のPCにログインしてリモート操作してもらうということもできます。
SSHクライアントの入れ方
Webページを見るのにWebブラウザが必要なように、SSHで他のコンピュータをリモート操作するにはSSHクライアントというソフトウェアが必要になります。
- Windows用のSSHクライアントはTera Termが有名ですが、これはGUIから起動して他のコンピュータを操作することに特化しています。今回は手元のPC上での操作が必要なので、Git for Windowsを使うことを想定します。これによりインストールされる「Git Bash」を起動して
ssh
コマンドを実行すれば、SSHクライアントを起動できます。 - macOS(OS X)は、初期状態でSSHクライアントがインストールされています。「Terminal」を起動して
ssh
コマンドを実行すれば、SSHクライアントを起動できます。 - Linuxの場合、
ssh
コマンドは初期状態で利用できる場合が多いのですが、もし入っていない場合は「GNOME端末」あたりを起動してsudo apt insntall openssh
(Debian系ディストリビューション)やyum install openssh
、dnf install openssh
などとしてインストールします。ssh
コマンドを実行すれば、SSHクライアントを起動できます。
SSHサーバー(sshd)の入れ方
Webページを公開するのにApacheなどのサーバーソフトウェアが必要なように、SSHで他のコンピュータからのリモート操作を受け付けるにはSSHサーバー(SSHデーモン、あるいはsshd)というソフトウェアが必要になります。
- Windows用にはMicrosoftが開発者向けにOpenSSHを提供しているようです。残念ながら筆者はWindowsでsshdを立てたことがないので、詳しくはリンク先の記事を参照して下さい(すみません……)。
- macOS(OS X)の場合、初期状態でsshdがインストールされています。「システム環境設定」→「共有」→「リモートログイン」にチェックを入れると、それだけでsshdが起動した状態になります。
- Linuxの場合、まず
sudo apt insntall openssh-server
(Debian系ディストリビューション)やyum install openssh-server
、dnf install openssh-server
などとしてsshdをインストールします。インストールできたら、systemdが使われている環境(CentOS 7など)ではsudo systemctl start sshd.service
、Initスクリプトが使われている環境ではsudo service ssh start
とすればsshdが起動します。
リモート操作を受け付けるようにするという性質上、sshdの運用には色々と注意が必要です。一般的には、管理者ユーザ(root)ではログインできないようにしたり、脆弱なパスワード認証ではなく安全な公開鍵認証のみを使うようにしたりといった形で。安全側に倒した設定で運用するのが定番です。詳しいことは「sshd 設定」や「SSH サーバー 設定」などのキーワードで検索してみて下さい。
Gitの入れ方
もちろんGitもインストールが必要です。GUIのGitクライアントを使っている場合でもこの記事で解説するようなことはできるはずですが、実際のやり方はクライアントに依存するため、この記事では一律にgit
コマンドを使う方法を解説します。
- Windows用のGitクライアントにもいくつか種類がありますが、ここでは前述したGit for Windowsを使うことを想定します。「Git Bash」を起動して
git
コマンドを実行すれば、Gitリポジトリをコマンドで操作できます。 - macOSの場合、XcodeのCommand Line ToolsをインストールするとGitも利用できるようになります。インストール完了後は、「Terminal」を起動して
git
コマンドを実行すれば、Gitリポジトリをコマンドで操作できます。 - Linuxの場合、
sudo apt insntall git
(Debian系ディストリビューション)やyum install git
、dnf install git
などとしてGitをインストールします。インストール後はgit
コマンドでGitリポジトリを操作できるようになります。
SSH越しにPull
ここでは例として、同じLANにある以下の2台のコンピュータ同士の間でSSH越しに直接Pullする場合の手順を解説します。
- Pullする側(自分)
- Windows PC
- IPアドレスは
192.168.1.10
。 - ユーザー名は
mint
。 - リポジトリはGit Bashで見た時の
/home/mint/ourrepo
の位置にclone済み。 - 作業しているのは
master
ブランチ。
- Pullされる側(相手)
- Linux PC
- IPアドレスは
192.168.1.20
。 - リポジトリは
/var/ourrepo
の位置にclone済みで、所有者以外でも読めるようパーミッションを設定済み。
まず、Pullする人がPullされる人のPCにSSHでログインできるようになっている必要があります。Pullされる側のPCにmint
ユーザーを作成するか、Pull操作専用のユーザーを作成しておきましょう。
SSHでログインできる状態になったら、Pullする側はGit Bash(macOSならTerminal、LinuxならGNOME端末)で以下のようにgit pull
を実行しますす。
$ git pull ssh://mint@192.168.1.20:22/var/ourrepo master
█
普通だとリモートリポジトリの位置はgit pull origin master
とかgit pull https://github.com/****/*****.git master
とかgit pull git@github.com:****/*****.git master
といった形で指定しますが、SSHでログインできる先のコンピューター上のリポジトリはssh://(ログインに使うユーザー名)@(ホスト名またはIPアドレス):(sshdが接続を受けているポート番号)(リポジトリのフルパス)
という書き方で指定します。
すると、Gitが内部的にSSHクライアントを起動して相手のPCにSSHで接続し、相手の側のリポジトリに加えられた変更をfetch
してくれます。やりましたね!
なお、sshdのポート番号が既定の22番である場合は、省略記法として以下のような書き方もできます。
$ git pull mint@192.168.1.20:/var/ourrepo master
█
おや、どこかで見たような形ですね。実はGitHubでよく見るgit@github.com:****/*****.git
というリモートリポジトリの指定は、git
という名前のユーザとしてSSH接続する指定だったのでした。
SSH越しにPushできる共有リポジトリを作ってみよう
PullができるならPushもしたくなりますよね。しかし、単純に以下のようにするとエラーになってしまいます。
$ git push mint@192.168.1.20:/var/ourrepo master
█
これは何故かというと、Pushしようとした先が通常のGitリポジトリだからです。Pushを受け付けるためには、bareリポジトリという物を用意しないといけません。
bareリポジトリは作業ファイルを伴わない、純粋に情報を溜め込む事に特化したリポジトリです。git clone
する時に--bare
というオプションを付け、Clone先のディレクトリ名に.git
を付けると、bareリポジトリを作る事ができます。例えば以下の要領です。
$ cd /var/
$ git clone --bare ./ourrepo ./ourrepo.git
█
ということで、Pushを受け付けたい側のPCにはあらかじめbareリポジトリを用意しておきましょう。
先程と同様、同じLANにある以下の2台のコンピュータ同士の間でSSH越しに直接Pushする場合を例として解説します。
- Pushする側(自分)
- Windows PC
- IPアドレスは
192.168.1.10
。 - ユーザー名は
mint
。 - リポジトリはGit Bashで見た時の
/home/mint/ourrepo
の位置にclone済み。 - 作業しているのは
master
ブランチ。
- Pushされる側(相手)
- Linux PC
- IPアドレスは
192.168.1.20
。 mint
ユーザでSSHログイン可能。- bareリポジトリは
/var/ourrepo.git
の位置にあり、所有者以外でも読み書きできるようパーミッションを設定済み。
とはいえ手順としては単純で、リモートリポジトリの指定をbareリポジトリの方にするだけです。
$ git push ssh://mint@192.168.1.20:22/var/ourrepo.git master
█
省略記法を使えばこうですね。
$ git push mint@192.168.1.20:/var/ourrepo.git master
█
これもまた、なんだか見慣れた形です。これを見ると分かるとおり、GitHubはgit
という名前のユーザでSSH接続して、用意しておいたbareリポジトリを相手にPushやPullを行っているわけです。
SSHとコマンド操作を恐れなければ、世界は思ったより広くて自由!
ということで、わざわざGitLabを立てたりしなくてもSSHさえ使えるならコンピュータ同士の間で直接PushやPullができる、というお話でした。
これを応用すると、Gitを使った簡単なデプロイが可能になります。実際に、筆者は自分の個人Webサイトの静的なソースを自宅にあるファイルサーバー上にGitリポジトリの形で置いており、作業用PCとレンタルサーバー上の公開ディレクトリの2箇所にリポジトリをCloneしています。作業環境でソースに手を入れた場合はそれを自宅サーバー上のリポジトリにPushして、その後レンタルサーバー上のリポジトリでPullするだけでもうデプロイ完了です。
この運用にはサーバー上で行った緊急の修正を共有しやすいという利点もあります。サーバー上で急遽ミスを修正したり暫定的な対応を取ったりした後は、git push
すれば自宅サーバーのリポジトリに変更が反映されます。後はまたそれを作業環境の方でPullするだけで、緊急で行った修正の内容を損なうことなく次の作業ができるというわけです。
また、別の応用の仕方として、仮想マシンの中と外でのファイルのやり取りに使うという事もできます。つい先日、とあるRailsアプリの検証用実行環境としてVagrantで管理されるVirtualBox VMを用意したのですが、そのRailsアプリはデプロイ方法が独特でvagrant
ユーザではない特定の名前のユーザのhome以下にファイルを設置する必要があり、「/vagrant
にマウントされるディレクトリ以下にファイルを置いて、VM外でファイルを編集してVM内で即動作を確認」ということができませんでした。そこで、vagrant ssh
によるSSHポート転送でトンネルを掘り、そこを通す形で特定ユーザのホーム以下に置かれたリポジトリとVM外のリポジトリの間でPullし合って、細かい変更を随時反映するという使い方をしました。
端末を使ったSSH越しのリモート操作は、勝手が掴めていないと目隠しをしてスイカ割りをするような不安やもどかしさがあり、つい苦手意識を持って避けてしまいがちでしょう。でも、「自分がコマンドを実行したとき、この端末の黒い画面の向こうで一体何が起こっているのか」をきちんと把握できるようになれば、そこにはお仕着せのツール越しに見ていたのとは全く違う自由な世界が広がってますよ!
ところで、自分は2011年から日経Linux誌上で「シス管系女子」というケーススタディ形式の解説マンガ記事を連載させて頂いています。主に「SSHでサーバーをリモート操作する」というシチュエーションでの「あーこういうのあるある」事例を取り上げて、その時何が起こっているのか・どうすれば悩みを解決できるのかを絵解き解説するという内容です。
筆者自身、元々クライアントサイドの開発が主な活動分野だったため、サーバ操作は非常に苦手だったのですが、業務の中でWebサービスの運用に関わる中で少しずつ要領が分かってきたという経緯がありました。本連載にはその経験がふんだんにフィードバックされていますので、普通に体系的にコマンド操作のことを学ぼうとして挫折した方にこそオススメな内容となっています。もし良かったら、お近くの大きめの書店でシス管系女子の本や掲載誌を手に取ってチラ見して頂けましたら幸いです。
あと、Twitterのみんとちゃんbotアカウントでイラストや本編に入りきらなかった小ネタを流したり、Webサイトの方にも連載や本では扱わなかったもっと基礎的な話の特別編を置いていたりします。「シス管系女子」をテーマにしたAdvent Calendarも公開中です。
マンガでわかるGitでGitの仕組みや使い方を覚えた方は、その勢いでLinuxのコマンド操作もマンガで覚えてみませんか?
ということで、Git以外の話ばかりでしたがGit Advent Calendarの24日目でした。最後の25日目はliubinさんによるお話です。お楽しみに!
wikieditish message: Ready to edit this entry.