最初はsphinxにしようと思っていたがいつのまにかPandocになっていたんだ。

多様なフォーマットに対応!ドキュメント変換ツールPandocを知ろう

Tex Wiki - MacTeX インストールの概略 -

Pandocのインストール

pandocをbrew caskでインストール

1
2
3
brew update
brew install caskroom/cask/brew-cask
brew cask install pandoc

試しにHTMLを生成してみる

1
2
3
4
5
6
mkdir ~/pandoc
cd ~/pandoc

curl -O http://johnmacfarlane.net/pandoc/demo/README
mv READEME input.md
pandoc input.md -s -o output.html && open output.html

MarkDown <---> reStructuredText

1
2
3
4
5
### .md to .rst
pandoc input.md -s -o input.rst

### .rst to .md
pandoc input.rst -s -o input.md

入力形式・出力形式を明示的に指定

1
pandoc -f markdown -t html input.md -s -o output.html

MaxTexのインストール

MaxTex.pkgをミラーサイトからダウンロード

例えば http://oku.edu.mie-u.ac.jp/~okumura/texwiki/?Mac#mactex からMacTex.pkgをダウンロード。

2.3Gもある…

インストールウィザードからインストール

ダブルクリック→ウィザードに従ってインストール 環境変数も自動で設定される。

作業中のシェルには反映されない。 /etc/paths.dでPATHへの判定は何かしている模様。

1
2
source /etc/profile
echo $PATH

/usr/texbinがPATHに存在することを確認。

環境設定

1
sudo tlmgr update --self --all

このアップデートもけっこう時間かかった。

あとはWikiに従って設定していき、

1
sudo vi /usr/local/texlive/texmf-local/web2c/texmf.cnf
1
2
3
4
5
6
shell_escape_commands = \
bibtex,bibtex8,bibtexu,upbibtex,biber,\
kpsewhich,\
makeindex,mendex,texindy,xindy,\
mpost,upmpost,\
repstopdf,epspdf,extractbb
1
sudo mktexlsr
1
2
3
4
5
6
7
8
9
sudo mkdir -p /usr/local/texlive/texmf-local/fonts/opentype/hiragino/
cd /usr/local/texlive/texmf-local/fonts/opentype/hiragino/
sudo ln -fs "/Library/Fonts/ヒラギノ明朝 Pro W3.otf" ./HiraMinPro-W3.otf
sudo ln -fs "/Library/Fonts/ヒラギノ明朝 Pro W6.otf" ./HiraMinPro-W6.otf
sudo ln -fs "/Library/Fonts/ヒラギノ丸ゴ Pro W4.otf" ./HiraMaruPro-W4.otf
sudo ln -fs "/Library/Fonts/ヒラギノ角ゴ Pro W3.otf" ./HiraKakuPro-W3.otf
sudo ln -fs "/Library/Fonts/ヒラギノ角ゴ Pro W6.otf" ./HiraKakuPro-W6.otf
sudo ln -fs "/Library/Fonts/ヒラギノ角ゴ Std W8.otf" ./HiraKakuStd-W8.otf
sudo mktexlsr

PDF作成

実際にPDFができましたとさ。

1
iconv -f UTF-8-MAC -t UTF-8 input.md | pandoc -f markdown -o output.pdf -V documentclass=ltjarticle --latex-engine=lualatex

長いのであとでaliasの設定をしておきたいところ。

以上。

Elasticsearch referenceの学習ノート.

getting started

Elasticsearchはハイスケーラブルな全文検索エンジンで大規模なデータを リアルタイムに近い速度で検索できる

index/type/document

what is an elasticsearch index?

MySQL => Databases => Tables => Columns/Rows
Elasticsearch => Indices => Types => Documents with Properties

cluster&node, shards&replicasedit

single nodeでちょっと遊んでみるだけなので必要に迫られたら

インストール

1.4の場合、java7以上Oracle JDK version 1.8.0_25推奨とのこと

1
2
3
4
5
6
7
8
curl -L -O https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.4.2.tar.gz
tar -xvf elasticsearch-1.4.2.tar.gz
cd elasticsearch-1.4.2/bin
./elasticsearch
[2014-12-22 11:56:19,921][INFO ][node                     ] [Sunstreak] version[1.4.2], pid[15416], build[927caff/2014-12-16T14:11:12Z]
[2014-12-22 11:56:19,922][INFO ][node                     ] [Sunstreak] initializing ...
[2014-12-22 11:56:19,927][INFO ][plugins                  ] [Sunstreak] loaded [], sites []
...

起動するときにclusterとnode名を指定する場合は以下

1
./elasticsearch --cluster.name my_cluster_name --node.name my_node_name

今はsingle nodeでやっているのでcluster.nameはデフォルトのelasticsearch

REST APIs

  • Check your cluster, node, and index health, status, and statistics
  • Administer your cluster, node, and index data and metadata
  • Perform CRUD (Create, Read, Update, and Delete) and search operations against your indexes
  • Execute advanced search operations such as paging, sorting, filtering, scripting, faceting, aggregations, and many others

ヘルスチェックAPI

statusがgreenなら全機能正常レプリカ割当済
yellowの場合は全機能正常レプリカ未割当

1
2
3
curl 'localhost:9200/_cat/health?v'
epoch      timestamp cluster       status node.total node.data shards pri relo init unassign
1419226053 14:27:33  elasticsearch green           1         1      0   0    0    0        0

clusterのnode一覧

1
2
3
curl 'localhost:9200/_cat/nodes?v'
host           ip           heap.percent ram.percent load node.role master name
local 192.168.11.2            1          67 1.88 d         *      Sunstreak

CRUD API

index一覧

まだ作成されていない状況

1
2
curl 'localhost:9200/_cat/indices?v'
health index pri rep docs.count docs.deleted store.size pri.store.size

index作成

PUTでcustomerというindexを作成
prettyでレスポンスのJSONを綺麗にフォーマットして表示

1
2
3
4
curl -XPUT 'localhost:9200/customer?pretty'
{
  "acknowledged" : true
}

デフォルトではprimary shards : 5, replica : 1で作成される

1
2
3
curl 'localhost:9200/_cat/indices?v'
health status index    pri rep docs.count docs.deleted store.size pri.store.size
yellow open   customer   5   1          0            0       575b           575b

statusがyellowなのはnode数が1のためレプリカ割当がされていないため

Document作成

customerのindexにexternalのtypeid=1としてdocumentを作成する
前節のようにindexをあらかじめ作成しておかなくても自動で作成される

1
2
3
4
5
6
7
8
9
10
11
curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
{
   "name": "John Doe"
}'
  {
    "_index" : "customer",
    "_type" : "external",
    "_id" : "1",
    "_version" : 1,
    "created" : true
  }

GETで作成したドキュメントを取得できる
_sourceには上記で追加したJSONが格納される

1
2
3
4
5
6
7
8
9
10
11
12
curl -XGET 'localhost:9200/customer/external/1?pretty'
{
  "_index" : "customer",
  "_type" : "external",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source":
  {
    "name": "John Doe"
  }
}

index削除

1
2
3
4
5
6
curl -XDELETE 'localhost:9200/customer?pretty'
{
  "acknowledged" : true
}
curl 'localhost:9200/_cat/indices?v'
health status index pri rep docs.count docs.deleted store.size pri.store.size
1
2
3
4
5
6
7
curl -XPUT 'localhost:9200/customer'
curl -XPUT 'localhost:9200/customer/external/1' -d '
{
  "name": "John Doe"
  }'
curl 'localhost:9200/customer/external/1'
curl -XDELETE 'localhost:9200/customer'

REST ApiのURLパターンは以下のようになっている

1
curl -X<REST Verb> <Node>:<Port>/<Index>/<Type>/<ID>

データの追加・変更・置換

前節のようにid: 1のドキュメントを追加し

1
2
3
4
5
6
7
8
9
10
11
curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
{
  "name": "John Doe"
}'
{
  "_index" : "customer",
  "_type" : "external",
  "_id" : "1",
  "_version" : 1,
  "created" : true
}

同一idに対してPUTしたところ、 _versionがインクリメントされ、 created : falseでレスポンスが返却された

1
2
3
4
5
6
7
8
9
10
11
curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
{
  "name": "Jane Doe"
}'
{
  "_index" : "customer",
  "_type" : "external",
  "_id" : "1",
  "_version" : 2,
  "created" : false
}

idを指定しない場合はPUT``POSTメソッドを利用する (ランダムのidが付与される)

1
2
3
4
5
6
7
8
9
10
11
curl -XPOST 'localhost:9200/customer/external?pretty' -d '
{
  "name": "Jane Doe"
}'
{
  "_index" : "customer",
  "_type" : "external",
  "_id" : "AUpxBPlH-CO8AzdI6K3A",
  "_version" : 1,
  "created" : true
}

ドキュメントの修正

前節がレコードの登録に関する操作とすると、こちらはフィールド値の更新操作に値する

1
2
3
4
curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
{
  "doc": { "name": "Jane Doe" }
}'

ctx._sourceで自身のフィールド値を利用することができる

1
2
3
4
curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
{
  "script" : "ctx._source.age += 5"
}'

以下のようにupdateは現在のところ単一行への操作しかできない模様

Note that as of this writing, updates can only be performed on a single document at a time. In the future, Elasticsearch will provide the ability to update multiple documents given a query condition (like an SQL UPDATE-WHERE statement).

ドキュメントの削除

特に違和感なく、GETの要領で削除できる

1
2
3
4
5
6
7
8
curl -XDELETE 'localhost:9200/customer/external/2?pretty'
{
  "found" : false,
  "_index" : "customer",
  "_type" : "external",
  "_id" : "2",
  "_version" : 1
}

/_queryで条件を利用できる(取得時の条件指定は後述?)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
curl -XDELETE 'localhost:9200/customer/external/_query?pretty' -d '
{
  "query": { "match": { "name": "John" } }
}'
{
  "_indices" : {
    "customer" : {
      "_shards" : {
        "total" : 5,
        "successful" : 5,
        "failed" : 0
      }
    }
  }
}

Bulk API

一括処理のAPIを利用することでネットワークのラウンドトリップを小さくできる

ドキュメントの一括追加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
'
{
  "took" : 6,
  "errors" : false,
  "items" : [ {
    "index" : {
      "_index" : "customer",
      "_type" : "external",
      "_id" : "1",
      "_version" : 6,
      "status" : 200
    }
    }, {
      "index" : {
        "_index" : "customer",
        "_type" : "external",
        "_id" : "2",
        "_version" : 1,
        "status" : 201
      }
      } ]
    }

ドキュメントの修正と削除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
{"update":{"_id":"1"}}
{"doc": { "name": "John Doe becomes Jane Doe" } }
{"delete":{"_id":"2"}}
'
{
  "took" : 11,
  "errors" : false,
  "items" : [ {
    "update" : {
      "_index" : "customer",
      "_type" : "external",
      "_id" : "1",
      "_version" : 7,
      "status" : 200
    }
    }, {
      "delete" : {
        "_index" : "customer",
        "_type" : "external",
        "_id" : "2",
        "_version" : 2,
        "status" : 200,
        "found" : true
      }
      } ]
    }

追加と修正時には引数にドキュメント内容が、削除の場合は引数なしで操作する

一括操作は上から順に行われ、ひとつひとつの操作が正常に終了したかどうかは レスポンスのstatusで確認できる

検索API

JSONファイルから取り込み

サンプルデータの一括登録

1
2
3
4
curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @accounts.json
curl 'localhost:9200/_cat/indices?v'
health status index pri rep docs.count docs.deleted store.size pri.store.size
yellow open   bank    5   1       1000            0    418.2kb        418.2kb

search api

いずれかの形式で利用できるが、bodyを利用するとより表現が豊か

  • REST request URI
  • REST request body

REST request URI

q=*のURLパラメータでクエリ指定する(*ではすべてのindexを取得する)

1
curl 'localhost:9200/bank/_search?q=*&pretty'

REST request body

上記の*に相当するmatch_allの表現

1
2
3
4
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_all": {} }
}'

response data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
  "took" : 63,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
    },
    "hits" : {
      "total" : 1000,
      "max_score" : 1.0,
      "hits" : [ {
        "_index" : "bank",
        "_type" : "account",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "account_number":1,"
took
検索に要した時間(ms)
timed_out
検索がタイムアウトしたかどうか
_shards
検索したshardの数
hits
検索結果
hits.total
結果件数
hits.hits
検索されたドキュメント(デフォルトでは10件取得)
hits.hits._score, hits.max_score
今の所は忘れておく

検索結果について

一度検索結果が返却されたのちはサーバーサイドではリソースを使っていないので 少しずつフェッチしてデータを取得するようなことはできない

その他修飾句

  • from n
  • size n
  • sort { “sorted_field” : {“order” : “asc”/“desc”} }

searches

フィールド名自体で検索

1
"_source : [ fields...]"

フィールド値で検索

1
2
3
"query" : { "match_all" : {}}
"query" : { "match" : { "account_number" : 20 }}
"query" : { "match" : { "address": "mill lane" }} # mill or lane

条件句のAND/OR/NOR

1
2
3
4
5
6
7
8
"query": {
  "bool": {
    "must": # should/must_not
    { "match": { "address": "mill" } },
    { "match": { "address": "lane" } }
    ]
  }
}

filters

前節にあった_scoreはクエリとのマッチ度合の指標であるが filtersはこの対象になく、その他クエリと比較して処理が早い。 メモリにもキャッシュされるため同一の検索がされる場合に処理が早い。

  • Filters do not score so they are faster to execute than queries
  • Filters can be cached in memory allowing repeated search executions to be significantly faster than queries
  • filtered query
  • range filter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "filtered": {
      "query": { "match_all": {} },
      "filter": {
        "range": {
          "balance": {
            "gte": 20000,
            "lte": 30000
          }
        }
      }
    }
  }
  }'
filterを使うべきかqueryを使うべきか

マッチ度合を利用したい場合はquery、そうでない場合はfilter

In general, the easiest way to decide whether you want a filter or a query is to ask yourself if you care about the relevance score or not. If relevance is not important, use filters, otherwise, use queries. If you come from a SQL background, queries and filters are similar in concept to the SELECT WHERE clause, although more so for filters than queries.

aggregations

SQLでいうところのGROUP BY

1
2
3
4
5
6
7
8
9
10
11
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state"
      }
    }
  }
}'
1
SELECT COUNT(*) from bank GROUP BY state ORDER BY COUNT(*) DESC

グローバルIPなくてポート解放できないから仕方なしに作ったけど
思いのほか使い勝手がいいのでオススメすべく手順残しておく

目標

VPSにPeerCastとPecalisをインストールしてデバイスフリーな視聴環境をつくる

  • グローバルIPもらえないネット環境の人もPeerCastが視聴できる
  • 視聴するマシンごとにクライアントのインストールしなくていい
  • 実況スレへの書き込みもブラウザの同じ画面からできる
  • AndroidやiOSからも視聴できるらしい

ConoHa VPS

以前に3000円クーポンx2をもらっていたのでConoHa VPSに
そうでなくとも新規登録時に1500円分のお試しクーポンがもらえます

標準プラン最小構成で月1004円、Windowsプランなら月2084円(2014/12現在) 1日使って削除すれば1日分の日割りの値段(電源OFFしてもダメ)

電話認証は必要だけど初回費用ないし カード登録しなくていいしで比較的気楽に利用できそうな感じ。

トラフィックで課金されるクラウドより定額のVPSのほうが安心。

使用ツール・バージョン

OSはConoHaのデフォルトがCentOSになっているので選択。
その他は現時点での最新を利用。

VPS起動

テンプレートイメージのCentOS6.5(64bit)を選択してVPSを作成。
パスワードを入力するほかは特に何も変更せず。

起動が完了したら rootユーザでVPS作成時に設定したパスワードでログイン。

VPSを追加する

(補足)Webコンソール

コンソール

コマンドのコピペはここから

コピペする

少し放置するとすぐ切断されてしまう。再接続するにはこれを

再接続する

若干面倒な点もあるので秘密鍵をダウンロードしてSSH接続するほうが楽かも。

必要なパッケージをインストール

GUIのインストール

PeerCastStationの設定画面はブラウザから行う必要があるので GUI環境をインストールする。PecalisもGUI上のシェルから起動しないとエラーになる模様。

1
yum -y groupinstall "X Window System" "Desktop" "General Purpose Desktop" "Japanese Support"

ブラウザ(Chromium)のインストール

Chormeのオープンソース版をインストールする。

1
2
3
cd /etc/yum.repos.d/
wget http://people.centos.org/hughesjr/chromium/6/chromium-el6.repo
yum -y intall chromium

Monoのインストール

.NETアプリをCentOS上で動かすためにMonoをインストールする。

1
2
3
cd /etc/yum.repos.d/
wget http://download.opensuse.org/repositories/home:tpokorra:mono/CentOS_CentOS-6/home:tpokorra:mono.repo
yum -y install mono-opt mono-opt-devel mono-libgdiplus-opt

と、パッケージインストールしても 後々にlibgdiplus.soがNotFoundですと怒られてしまうようなので 下記のようにconfigファイルを編集する。

1
2
3
cd /opt/mono/etc/mono
cp config __config
vi config

ファイル末尾付近の libgdiplus.so/opt/mono/lib/libgdiplus.soに書き換える。

1
2
3
4
<dllmap dll="gdiplus" target="/opt/mono/lib/libgdiplus.so" os="!windows"/>
<dllmap dll="gdiplus.dll" target="/opt/mono/lib/libgdiplus.so"  os="!windows"/>
<dllmap dll="gdi32" target="/opt/mono/lib/libgdiplus.so" os="!windows"/>
<dllmap dll="gdi32.dll" target="/opt/mono/lib/libgdiplus.so" os="!windows"/>

libgdiplus.so自体は/usr/local/libにインストールされているので

ファイアーウォールの設定(ポート開放)

PeerCastに必要なTCP:7144とPecalisのTCP:7134のポートの通信を許可しておく。

1
iptables -L --line-numbers

REJECTから始まる行が5行目にあるのを確認したのち、

1
2
3
4
iptables -I INPUT 5 -m state --state NEW -m tcp -p tcp --dport 7144 -j ACCEPT
iptables -I INPUT 5 -m state --state NEW -m tcp -p tcp --dport 7134 -j ACCEPT
service iptables save
service iptables restart

※ 特定のアクセス元からしか通信を許可しないようにしたほうがいいのかも。

GUIモードに変更して再起動する

ユーザの追加

PeerCastを動かすユーザーを作成しておく。

1
2
3
4
groupadd peercast
useradd -g peercast peercast
passwd peercast
(INPUT)

OSがGUIモードで立ち上がるように修正

1
vi /etc/inittab

上記のファイルを

1
id:3:initdefault

から

1
id:5:initdefault

に修正

日本語環境に変更

英語環境より日本語のほうがわかりやすいので

1
vi /etc/sysconfig/i18n

上記ファイルを

1
LANG=en_US.UTF-8

から

1
LANG=ja_JP.UTF-8

に修正

1
. /etc/sysconfig/i18n

再起動

1
reboot

再起動が完了するとWebコンソールにGUIの画面が表示される

ようこそ

初回起動時は上記のような画面が表示されるが全て進むで完了する
(途中メモリが足りない等言われたらOKとしておく)

視聴ツールのインストール

以降、作成したpeercastユーザでログインして進める

端末を起動

アプリケーション>システムツール>端末

PeerCastStationのインストール

ダウンロードしてきて解凍する。

1
2
3
cd
wget http://www.pecastation.org/files/PeerCastStation-1.9.0.2.zip
unzip PeerCastStation-1.9.0.2.zip

Pecalisのインストール

同じくダウンロードして解凍する。

1
2
3
cd
wget http://www.pecalis.com/data/pecalis.zip
unzip pecalis.zip

PeerCastStationの起動

1
/opt/mono/env.sh && nohup /opt/mono/bin/mono ~/PeerCastStation-1.9.0.2/PeerCastStation.exe &

PeerCastStationの設定

インターネット>chromiumでブラウザを起動して http://localhost:7144 にアクセスする。

 メモ:ctrl+zでプロセスを一時停止させて復帰させるとアクセスできなかった

pecast

設定タブから設定を行う

  1. WAN接続許可の「視聴」と「操作」にチェックする
    認証IDと認証パスワードは後ほど利用する

pecast

  1. 上り帯域計測ボタンを押して最大上り帯域を設定する
    詳しくは http://localhost:7144/help/settings.html を確認

pecast

  1. 自動切断を行うように設定しておく pecast

ローカルマシンからブラウザで設定画面を開けることを確認

VPSに接続しなくてもどこからでもブラウザで設定画面を開けることを確認する

http://VPSのIPアドレス:7144

にアクセスすると

pecast

のように認証ID、認証パスワードを求められるので入力する。

Pecalisの準備

  1. Pecalisアカウントの作成

Pecalisアカウントの新規作成 もしくはTwitter等の外部サイトアカウントでログイン

  1. 設定>アカウント設定>クライアントログインパスをコピー

pecalis

Pecalisの起動

初回起動時にクライアントログインパスを要求される

1
2
3
4
/opt/mono/env.sh && /opt/mono/bin/mono ~/pecalis/Pecalis.exe
...
クライアントログインパスを入力してください
(入力)

シェルから切り離して実行したい場合は次のようにする

1
/opt/mono/env.sh && nohup /opt/mono/bin/mono ~/pecalis/Pecalis.exe &

セットアップが出来ているか確認。

http://www.pecalis.com/setup/

pecalis

ちゃんとポートが解放されていればOK

視聴する

ローカルマシンでブラウザでPecalisサイトにアクセスして視聴

好きなチャンネル選んで実況しよう!

pecalis

お疲れ様でした!

github, heroku等で個人用途にも関わらず 特に理由もなくSSH鍵をそれぞれ個別に作成してしまっていたので デフォルトの~/.ssh/id_rsa(.pub)で統一してしまいたいの巻。

乱造されたSSH鍵…

不要なものは削除して統一したい

1
2
3
4
5
6
7
8
9
~/.ssh % ll
config github_rsa github_rsa.pub heroku_rsa heroku_rsa.pub known_hosts
~/.ssh % cat config
Host github
  HostName github.com
  Port 22
  User git
  IdentityFile ~/.ssh/github_rsa
...(略)

SSH Key Pairの作成

ssh-keygenで特にオプション指定しないで作成すると2048bitのRSA鍵が生成される。

1
2
3
% ssh-keygen -C "comment"
Enter file in which to save the key (/Users/contee/.ssh/id_rsa): (Enter)
(パスフレーズの入力)

-Cで入力したコメントがgithubのGUI等で確認できるので入力しておくとよい。

sshコマンドの-iオプションで秘密鍵のファイルを指定しない場合は ~/.ssh/id_rsaを読み込んでくれるのでファイル名もデフォルトのままで都合が良い。

パスフレーズを設定しておくと秘密鍵自体も暗号化した形で保存されるので ファイル覗かれても少し安心。もし変更したい場合は、

1
ssh-keygen -p -f <identity>

で一度設定したパスフレーズを変更できる。これはあくまでローカルマシンに保存されている 秘密鍵に対する変更なのでリモートで何かしないといけないわけではない。

GitHubにSSH Keyを登録しなおす

Generating SSH keys

今まで利用していた鍵に代わって、ブラウザでPersonal settings > SSH Keys > Add SSH Keyから画面に従って公開鍵を登録。 pbcopyでクリップボードを利用すると楽。登録するとGitHubからnew public key addedなメールが届く。

1
pbcopy < ~/.ssh/id_rsa.pub

公開鍵認証で接続できるかテストしてみる。

1
ssh git@github.com

パスフレーズの入力ダイアログが表示されるので入力。

1
2
Hi contee213! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.

こんな感じのメッセージが表示されればOK.

この時点でssh-add -lを実行すると秘密鍵がssh-agentに登録されているはず。

1
2
% ssh-add -l
2048 <fingerprint> /Users/user/.ssh/id_rsa (RSA)

HerokuにSSH Keyを登録しなおす

Managing Your SSH Keys

Heroku Toolbeltはインストール済として…

1
2
3
$ heroku keys
=== joe@example.com Keys
ssh-dss AAAAB8NzaC...DVj3R4Ww== adam@workstation.local

現在登録されているKeyを確認の上、除去

1
2
$ heroku keys:remove adam@workstation.local
Removing adam@workstation.local SSH key... done

もしくは全消去して

1
$ heroku keys:clear

あらためて登録する。

1
$ heroku keys:add

どれを追加するのか聞かれるので ~/.ssh/id_rsaに該当する番号を選択する。

登録できたら接続できるかテスト。

1
ssh git@heroku.com

ssh-add -l~/.ssh/id_rsaが登録されているのであれば パスフレーズは聞かれない。

何回もパスフレーズ入力するの面倒くさい

-Kオプション付けてkeychainに登録するのはどうだろう。

1
ssh-add -K

man ssh-addによれば-K

1
2
3
-K      When adding identities, each passphrase will also be stored in your keychain.
             When removing identities with -d, each passphrase will be removed from your
             keychain.

良さげな感じ。

VPSにSSH接続した状態でGitHub, HerokuにSSH接続

ssh -Aするか~/.ssh/configForwardAgent yesを指定してあげれば ローカルマシンの秘密鍵を利用してリモートマシンでSSH公開鍵認証できて便利ね。

エネルギー尽きた。

Ruby on Rails Tutorial の学習メモの続き。

第2章 デモアプリケーション

1章のおさらい的な

デモアプリケーションの作成

1
2
rails new demo_app
cd demo_app

開発環境のgemをインストール

1
2
3
bundle install --without production
bundle update
bundle install

gitでバージョン管理下に

1
2
3
git init
git add .
git commit -m "Initial Commit"

githubにpush

1
2
git remote add origin https://github.com/contee213/demo_app.git
git push -u origin master

scaffoldでリソース作成

rails generateスクリプトにscaffoldコマンドを渡すことで生成する

1
rails generate scaffold User name:string email:string

Ruby文法的にはscaffoldが関数でUserが第一引数で残りは nameemailのシンボルをキーとした`ハッシュといったところか。

RESTfulなルーティング

ルーティングはconfig/routes.rbで管理してそうな感じ。 いかにもリソースといったルーティングルールをresources :users で生成できてそう。

method url action comment
GET /users index show all user
GET /users/1 show show id=1 user
GET /users/new new show new user input
POST /users create create user
GET /users/1/edit edit show id=1 user input
PATCH /users/1 update update id=1 user
DELETE /users/1 destroy delete id=1 user
  • GETはページの取得
  • POSTは新しいリソースの作成
  • PUT PATCHはリソースの更新
  • DELETEはリソースの削除

デモアプリケーションのデプロイ

githubに登録

1
2
3
git add .
git commit -m "Finish demo app"
git push

前回は飛ばしてしまってたので気づかなかったけど

1
2
heroku create
git push heroku master

git push heroku masterでエラー

1
2
3
4
5
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

herokuのSSH設定

Managing Your SSH Keys

SSH Keys 手順メモ

いまいち適当に使ってるので。

1
ssh-keygen -t rsa -C "mail@address"
  • -tで生成する鍵の種類を指定する。 指定がない場合はSSH2のrsa鍵を生成するとあるので省略できそう
  • -Cでコメント。コメントには鍵の用途やその他情報を書いておける。
  • -fで鍵を格納するファイル名を指定。
  • -bで生成する鍵のbit数を指定。RSA鍵のデフォルトは2048bitで十分な桁数だと考えられてる。
  • -pですでにある秘密鍵ファイルのパスフレーズを変更できる。

ssh-agentとかssh-addとか コマンドの意味理解しないで使ってるので後で調べること。