こいつ…(とりあえず)動くぞっ!

あわよくばハッカーになりたい。あと3000年生きたい。ふふふーふ.jpで打製石器を作りまくっています。バールプログラミングを提唱しています。

shopifyとの戦いの記録 その1

いやー、ブログ放置してもう2年ぐらいかなー!?久しぶりの投稿だなあーとか思ってたらもう2年8か月とかなんですね。いくら何でも放置しすぎでしょう。

さて、久しぶりの投稿は表題の通り、ここ最近小商いを始めようと思いましてshopifyを触っており、それにまつわることを書きたいと思います。紆余曲折あるので何回かに分けます。 私自身、EC関係の仕事をしており、最近すごいすごいといろんな人が太鼓や提灯をもってピカピカドンドンやっているshopifyについて、「へーそんなにすごいなら使ってみるかー」と思いshopifyを選んだ次第です。 結論から言うと、確かにshopifyは出来上がっているテーマを自分好みに手を入れていくのは比較的簡単ですごいと思いました。なんかコード編集の画面とか構造とかすごい既視感があって、なんだろうなと思っていたら完全にtumblrのそれです。(今のtumblrどんな感じか分かりませんが、少なくとも5年くらい前のtumblrはこんな感じだったなーって感じ)

ただ、簡単ですごいと思いはしたんですが、なんか昨今の感じだと「誰でも何でもできる」みたいな雰囲気が醸し出されていますが、これについては嘘だなーと思いました。 shopify関連で巷に出ている情報はどれも浅いものばかりで、「なんでもできるんか!?よっしゃshopifyでやったろ」みたいなコード触れない(が、ECの売上は他プラットホームで出ている)人に対して、最終的に制作会社が案件をコンバージョンするためのマーケティング情報でしかないなーと感じます。 後ほど記載しますが、これはshopifyの全体的な仕組みとしてもそんな感じで、「え?何その仕様???え???これを叶えるためだけにAPP入れなあかんの???しかも高くない???」みたいなことがあり、結局のところ、大きなものから小さなものまで、実現したいことをやっていくにはpageでhtmlやCSSを書いたり、何ならJSも書いたり、どうしてもだめならAPP入れたりしなければならず、それに伴い外注費や月のランニングコストがあっという間に上がっていくという感じだろうなとも思います。 足回りはしっかりしているようなので、ガッツリ毎月1000万円とか売っているような事業者にとっては月に数万のランニングコストを払ってもペイするだけのパワーを発揮してくれると思いますが、~100万くらいまでの一人でなんでもやらないといけないフェーズの人にはつらいと思います。 そのため、私も始めたばかりの小商いのため、できるだけランニングコストを抑えたい一心でこんな風に対応したよ、という記録を残しておこうと思いました。 同じようなレベル感で悩まれている人の参考になれば幸いです。

さて、何の対応をしたかというと

  1. 無料プランのテーマがいまいちだからもっといいやつ使いてえ!
  2. 日本の都道府県選択のドロップダウンメニューが表示されねえ!
  3. 日本の都道府県の並び順がABC順になってんのを北から順にしてえ!
  4. 事前のユーザー登録時に住所とか電話番号とかも登録できるようにしてえ!
  5. 規約ページを標準のじゃなくてもうちょっと文字の大きさとか何とかしたい!
  6. 購入時にチェックアウトページで会員登録できるようにしたい!

というものです。いきなりネタバレですが、6番目についてはチェックアウトページを触るにはshopify plus(月20万円……)じゃないとできないらしいので書きません。月20万て。 それ以外もなんかめっちゃ初歩的というか、そんな突拍子もないニーズでもないよな?と思ったのですが、それなのに月12ドルのAPP入れたり、テーマ買った制作会社に「それは特別対応で実装しなきゃいけないので追加で料金もらわないとですねー」とか言われる(ちなみに、タダで改修してくれとかは言ってなくて、これテーマの部分のどこで設定すればいいの?って聞いたらそう返答されました)のがshopifyの世界だったんですよ。海外はshopify触れるエンジニアめっちゃいるらしく、Stack Overflowみたいなサイトでもちょいちょい具体的な回答あったりして、日本の状況はグローバルで見ると特殊みたいですね。

さて、初めはテーマについてです。 無料のテーマはさらっと見てみたのですが、どうしてもなんか物足りない。ECだっていう、売り物を売っている場所ですよー!!っていうオーラが足りない気がしたんですよね。 でも公式の有料テーマは180ドルとかだし、何より数が少ないので、どうしたもんかなー、いきなり詰んだやんと思っていました。 結論からいうと、shopifyのテーマは外部のマーケットにたくさんあり、そこからダウンロードして読み込ませるのがいいと思います。 私はここで買いました。結構安くて、50ドルくらいで買えました。

themeforest.net ※いろんなサービスやシステムのテンプレが売っているので必ずshopify用を買うよう気を付けましょう。

ただ、ここでテーマ買って良かった良かったすべて解決というわけにはいきません。 海外のECサイトと日本のECサイトは明らかにオーラやトンマナが異なります。shopifyのテーマはshopifyがナレッジを提供してくれてたりするのでまだいいですが、こういう野良マーケットで買ってくると多かれ少なかれカスタムする必要が出てきます。親切に仕様書や全体の構成など詳しいドキュメントはまず無いと思いますので、chromeデベロッパーモードとshopifyのコード編集画面を行ったり来たりしながら構成を把握し、どこを直せばいいのか調べるという作業が必ず発生すると思います。この時点で多くの人が脱落してしまうと思います。 これがshopifyのデカい問題で、全体の枠組みはshopifyが規定してくれているからいいのですが、その中のファイルがどう結びついてどうなっているかはテーマにより異なるため、テーマを変えるとこのあたりの作業をまたやり直さなければいけないということになります。 なので、一番最初のテーマは5年くらい使う気持ちで選んだ方がいいと思います。

さて、いよいよ具体的にここのコード直したらこうできたよの部分に入りますが、前置きが長くなったので今日はここまでにします。

三日坊主で今までまともにブログを続けられたことがないので、ちゃんと僕が記事を書けるよう、皆さん応援してください。よろしくお願いいたします。

SlackのAPIでDMを送るには

なんか今月は2週間目くらいで、「旦那ー!だんなー!旦那のブログがもう100PV超えたでやんすよー!!」というはてなからの連絡が来て、これはもう僕の時代来ているなと。僕が提唱する、バールプログラミング a.k.a 動きゃあいいんじゃ動きゃあが市民権を得始めているなと、そう思ったんですよ。 なのでちょうど、マジふざけんなハマり案件があったので更新してみました。

なにかっつうと、SlackのAPI(chat.postMessage)でメッセージを送るっていうスーパー初歩的なやつについてなんですが、今回、botユーザー作って、そいつに個々人にDMを送らせたかったんですけど、全くうまくいかんのですよ。 今回GASでやっていたんですが、chat.postMessage使おうと思うと、以下のような感じになるですよ。

  var messagePayload = {
    "token": token, //必要なスコープはbot・chat:write:user・chat:write:bot
    "channel":送り先のチャンネルID
    "text": "テスト"
  };

  var messageOptions = {
    "method" : "post",
    "contentType": "application/x-www-form-urlencoded",
    "payload" : messagePayload
  };

  var result = UrlFetchApp.fetch('https://slack.com/api/chat.postMessage', messageOptions);

一瞥してわかるくらい、打製石器ヘビーユーザーの我々にも優しい感じなのですが、「チャンネルのところに送り先のSlackユーザーID入れたらDM送れるでー」みたいなことどっかで見たから一生懸命入れて送るんですが、なぜかSlackbotとのDMにメッセージが入っちゃったんですね。 もうお前はお呼びじゃねえんだと。アイコンを好きに変えられない、訳わからん顔したお前とはできるだけ話したくねえんだと、俺は俺が作った可愛いbotと蜜月のDMを交わしてえんだとブチ切れですよ。 Slackユーザー名の書式かなーと思って、@つけてみたり、<>で囲んでみたり、display Name入れてみたりしても一向にうまく行かねえ。 もう英語記事行くしかねえなと思って検索してみたら、見つけましたよ。

github.com

要するに、DM送るときは、まず、im.open叩かないといけないらしい。 普通はチャンネル指定してバールを振り回すといい感じにしてくれるスラ子ちゃんでも、流石にプライベートエリアになると、ワンクッション入れないとよしなにしてくれない訳ですよ。か、可愛いじゃん……。

というわけで以下のように変えたら無事、可愛い我が子からDM来ましたよ。

  var imPayload = {
    "token": token, //必要なスコープはbot・im:write
    "user": DM相手のSlackユーザーID(@とかはいらない),
  };
  
  var imOptions ={
    "method" : "post",
    "contentType": "application/x-www-form-urlencoded",
    "payload" : imPayload
  };

  var messagePayload = {
    "token": token, //必要なスコープはbot・chat:write:user・chat:write:bot
    "channel":JSON.parse(UrlFetchApp.fetch('https://slack.com/api/im.open', imOptions)).channel.id,
    "text": "テスト"
  };

  var messageOptions = {
    "method" : "post",
    "contentType": "application/x-www-form-urlencoded",
    "payload" : messagePayload
  };

  var result = UrlFetchApp.fetch('https://slack.com/api/chat.postMessage', messageOptions);

これで3時間くらいハマったわ。もうこんな悲劇が繰り返されませんように!!!!

「技術レベル:花粉」でもわかるChrome拡張機能の作り方

世間には「圧倒的簡単さで〇〇を作る方法」とか、「爆速で××作ってみた」とかそういうtipsが山ほどあるわけですが、正直そういうやつって、もうイオナズン覚えちゃってる人が、とりあえずこうすればイオラ出せるよみたいに書いてるやつじゃないですか。こちとらメラもライター程度のがやっとで、物理で殴り合ってスライムやドラキーとかなりきわどい勝負して、何なら10回以上コンティニューしてるわけですよ。もうね、勘弁してくれと。分らんと。最初の2行をなるほどと思って読み進めていると、早々に「とりあえずメラミの要領でサクッと魔力を集中させます」みたいなこと書いてあるんですよ。おい、ちょっと待てと。さくっとメラミ出せるならこんなに苦労してへんわと。

前置きが長くなりましたが、本ページでは私のような永遠のscript "kitten"に向け、この度習得した「真」圧倒的分かりやすさでchromeのアドオンを作る方法をご紹介したいと思います。 子猫ちゃんがネット上を放浪しまくって継ぎはぎで得た知識を開陳しているので、解説が間違ってたらごめんね(テヘペロ

あとなんかすげーほったらかしにしていたんですが、月間100PVとかいってて、一日3人くらいの人が見てくれてるわけで、とっても嬉しいです。皆様ありがとうございます。

chromeのアドオンといってもいろいろあるわけですが、今回は、右上にアドオンのアイコン出してクリックするとなんか出るやつと、右クリックメニュー(正しくはContext Menuっていうらしいよ)にオリジナルメニュー入れていい感じの機能つけるやつを実現するにはどうすればええねんということをご紹介したいと思います。ちなみに、browser action(いろんなURLで使う)とpage action(特定のURLに対して使う)と2種類あるらしいんですが、今回はbrowser actionの方です。

さて、chromeのアドオンの概略構造みたいなのはググれば詳しい人の記事がたくさん出てくるのでざっくりとしか書きませんが、今回の場合は

  • manifest.json(必須の設定ファイル)
  • background.js(右クリックメニューの処理)
  • main.html(右上のアイコンクリックしたときに出すやつ)
  • haahaaDisplay.js(onclick使うためのやつ)

この4つがあればOKです。これらを駆使して

  • 右上にアドオンのアイコンを出し、それをクリックするとウィンドウが出て、入力欄に文字列を入れてボタンを押すと文字列がウィンドウ内に表示される。
  • どっかのウェブページに表示されている文字列をドラッグで反転選択し、右クリメニューを選択するとalertで文字列が表示される。

という全く使いどころのないアドオンを作成してまいります。

manifest.jsonのポイント

基本的にはググって出てくる通りにやっとけば間違いないのですが、はまりポイントは、backgroundのところだと思います。ググるとバージョンアップ前の?結構古い記事が出てきてここにhtmlファイルが設定されているようなものが散見されます。昔は、「常に不可視なページをバックグラウンドで開いておいて、作業発生したらそいつにやらせとけばええやん?」みたいな発想(background page)だったらしいですが、閉じれもしない常時開かれているページが拡張機能の数だけ存在してたらメモリめっちゃ食うやん!というわけで、現在は、「作業が発生したときのみjsかなんか動かせば良くね?」(event page)というのが推奨されているようです。ここで右クリで動かしたいスクリプトを指定するとともに、event pageでの動作にするためには"persistent": falseが必要らしいので忘れないようにしましょう。また、permissionscontextMenu(右クリメニューのこと)を入れないとアドオンが右クリメニュー使えないっぽいのでここもお気を付けください。めんどくさかったらallにしとけばいい気がします(危険思想)。 また、右上のアドオンアイコン周りはbrowser_actionのところで設定します。クリックすると出てくるウィンドウ用のhtmlはdefault_popupのところに設定しておきます。

//manifest.json
{
    "manifest_version": 2,
    "name": "ハァハァアドオン",
    "description": "あなたのchromeをヤバいやつにするアドオンです。",
    "version": "0.1",
    "background": { 
        "scripts": ["background.js"],
        "persistent": false
    },
    "permissions": ["tabs","contextMenus"],
    "icons": {
        //"48": "icon.png"
      },
    "browser_action": {
        //"default_icon": "icon.png",
        "default_title": "haahaaExtension",
        "default_popup": "main.html"
    }
}

各項目はググればちゃんとした人の解説結構出てくるので割愛します。バージョンアップの件があるので、なるべく新しい記事見た方がいいです。default_iconとiconsの48サイズはディレクトリにアイコンの画像を用意しとかないと 拡張機能読み込んだ時にエラーが出るのでコメントアウトしてます。適当なアイコン入れるときはコメントアウト解除して設定してください。

main.htmlのポイント

要するにただのhtmlです。サイズは一番外側の要素の縦横サイズで決まるので、いい感じにするといいと思います。 でも、ただのhtmlと言いつつ、しれっと、onClick=function()(例えば<input type="button" onClick=function()>)が使えないというトラップが待ち構えています。ここで僕含め読者の85%の村人AはGoogleの我々のデキなさに対する無理解に怒りを隠しきれないと思いますが、その怒りのパワーで乗り越えましょう。 そこで、以下のようなJSをhtmlに持たせてあげてイベントを追加する必要があり、haahaaDisplay.jsが必要になってくるわけです。

//haahaaDisplay.js
'use strict';
document.addEventListener('DOMContentLoaded', function () {
    document.getElementById('kinkyButton').addEventListener('click', function () {
        let displayTarget = document.getElementById('kinkyDisplay');
        const targetName = document.forms.targetNameInputForm.targetName.value;
        const displayText ='chrome→(*´Д`)<'+ targetName + 'タン……ハァハァ……';
        displayTarget.innerText = displayText;

    });
}, false);

簡単に日本語でイメージを示すと以下の通りです。

ページの読み込みが終わったら右記の指示書確認よろ→
kinkyButtonっていう名前の要素がクリックされたらこの処理やっといて→
ページのtargetNameInputFormのtargetNameっていう部分に入力されてる値に
「タン ハァハァ……」をつなげてkinkyDisplayっていう要素に表示されるテキストとして入れる

main.html自体の全体像はこんな感じです。

<!--main.html-->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link href="./main.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="./haahaaDisplay.js"></script>
</head>
<body>
    <table>
        <tbody>
            <tr>
                <td>
                    <form id="targetNameInputForm" action="">
                        <input type="text" id="targetName" size="20" maxlength="10" minlength="10" autofocus=true>
                        <input type="button" id="kinkyButton" value="ハァハァする">
                    </form>
                </td>
            </tr>
        </tbody>
        <table>
            <div id='kinkyDisplay'></div>
</body>
</html>

background.jsのポイント

ここが一番の肝かと思います。右クリメニューを出すにはchrome.contextMenus.createというchromeAPIを使いますが、ただ単にこいつを使うだけだと、アドオンを呼びだす度にメニューに登録されてしまうらしい?ので、 chrome.runtime.onInstalled.addListenerと組み合わせることでインストール時に一度だけ右クリックメニューへの追加が行われるようにします。 右クリメニューは階層を作れるので、親メニューと同じ感じで子メニューも淡々と登録します。異なる点としては、子メニューは、親メニューのidをparentIdに設定する必要があります。 そして、chrome.contextMenus.onClicked.addListenerで右クリックメニューを選択した後の動作を設定します。 infoというオブジェクトに右クリメニューが選択された時のデータがいろいろ入っているので、今回は、反転選択したテキストをselectionTextで取得しています。 infoに何が入ってるかは、公式のリファレンスをご参照のこと。 そして、選択されたメニューのidによって処理を振り分けます。今回は大した処理じゃないので引数に入れた関数内で処理が完結していますが、複雑な処理の場合は、普通のJS感覚でかっこの外に別で関数作っても引数内の関数で使えます。

//background.js
'use strict';

//親メニュー登録
chrome.runtime.onInstalled.addListener(function () {
    chrome.contextMenus.create({
        id: "fromSelectionToHaahaaExtension",
        title: "ハァハァさせる",
        contexts: ["all"],
        type: "normal",
    }, function () {
        alert("chromeは ハァハァすることを おぼえた");
    });
});

//サブメニュー登録
chrome.runtime.onInstalled.addListener(function () {
    chrome.contextMenus.create({
        id: "soft",
        parentId: "fromSelectionToHaahaaExtension",
        title: "優しく",
        contexts: ["all"],
        type: "normal",
    });
    chrome.contextMenus.create({
        id: "hard",
        parentId: "fromSelectionToHaahaaExtension",
        title: "激しく",
        contexts: ["all"],
        type: "normal",
    });
});

//ここからメニューに割り当てる処理
chrome.contextMenus.onClicked.addListener(function (info,tab) {
    const selectedMenu = info.menuItemId;
    let haahaa;
    const targetName = info.selectionText;

    switch (selectedMenu) { //呼び出されたメニューによりハァハァする回数を変える

        case 'soft':
            haahaa = 'ハァハァ……';
            break;

        case 'hard':
            haahaa = 'ハァハァハァハァハァッハァッハァハァハァハァハァハァ……';
            break;
    }
    alert(targetName +'タン……'+ haahaa);

});

以上で簡単なchrome拡張機能が作れました! 紹介した4つのファイルを同じディレクトリにいれてchromeに読み込ませるとあなたのchromeがハァハァしだすぞ!やってみよう! パッケージングしていない拡張機能chromeに読み込ませる方法は

naokixtechnology.net

が、 chromeのパッケージングは

pineplanter.moo.jp

が分かりやすかったです。Naokixさん?(著者名がわからなくて違ったらすいません)、Uematsu Satoshiさん、ありがとうございます。

npmをupdateすると使えなくなる問題

今日も今日とて元気にnodeの勉強だよ!今日はHubotを触るよ!
え!?もしかして、ハボットなんですか!?ヒューボットじゃないんですか!?!?
なるほど、まずはnpmを、3.10.10からアップデートするんですね!npm update -g npm
よし!次に新しいパッケージをインストールするぞ!npm install -g generator-hubot

-bash: /home/ubuntu/.nodebrew/current/bin/npm: No such file or directory

な ぜ な の か

ググりにググりを重ねても一向にそれらしき答えは得られずマジで詰まってどうしようかと思い、とりあえず溜まった洗濯物を片付けて再挑戦するも無理でスターウォーズ5見て再挑戦しても無理でこのまま墓に入るのかと思いました。
症状としては、アップデートする前は/home/ubuntu/.nodebrew/current/bin/npmにあったのに、updateするとこいつが消えてしまい、そのせいでPathが通らなくなるらしい、というところまで分かったが、そっから先どうすんねんというところで無事万策尽きた。npmのドキュメントを斜め読みしてみてもそれらしい内容はなく、もう全部きれいにして、nodebrew入れるところからやるしかないのかなあと思っていた矢先。
ふと、変な場所にnmpやnodeをインストールした残骸があると、以後のアップデートやインストールの際に悪さをするという情報(macでnodebrewをインストしたらnpmコマンドでエラーが出たときの対応 | はやとも工業所) があったのを思い出した。(はやともさんありがとうございます)そういえば、nodebrewディレクトリの中じゃないとこにnmpのディレクトリあったな?と思い、nodebrewでnodeをアンインストールしたのち、/home/ubuntuにあった.npmというディレクトリ(とついでに.nmprc)をぶち消し、node入れるところからやり直してみた。

$ rm -rf /home/ubuntu/.npm
$ nodebrew install-binary v6.11.1
$ nodebrew use v6.11.1
$ npm update -g npm
$ npm -v

->5.6.0

脳内でロッキーが勝った時の音楽が大音量で響きました。みなさんもぜひここでお聞きください。


Bill Conti - The Final Bell (Rocky)

npmでinstallできない???

Node.jsの勉強中、requestをnpmでinstallしようとしたら、
protocol error, symlink '../sshpk/bin/sshpk-conv' -> '/home/ubuntu/workspace/npm-training/node_modules
というエラーが出て無理だよっていわれた。
調べてみると、どうやら、Win+vagrantだとシンボリックリンクが使えないせいらしい。でもシンボリックリンク使えるように設定したんだけどなー?
と思いつつ、npm install --no-bin-linksだといけると書いてあったので言われるがままにやってみたら無事にインストールされた。
npm config set bin-links falseでnpm installの時のデフォにできるらしい。
あとは、Winは管理者権限ならsymlinkを作れるようになるらしいので、vagrantを動かすコマンドプロンプトを管理者権限で起動すると--no-bin-linksをつけなくても大丈夫になるらしい。
やってみたらマジやん!そして私はそっと、vagrant用のコマンドプロンプトのショートカットを右クリックし、詳細設定から管理者で実行するようにしたのであった。
インターネットって本当にいいものですねぇ

cronでpythonのスクリプトが動かない

ハマりました。 pythonでウェブサイトのデータを編集してCSVを出力するスクリプトを作り、cronで定期実行するようにしました、が。
動かない!!!全然CSVが出てこない!!なんで!!なんでなの!!!
(いろいろやりすぎて何が効いたのかわからないので違ったらすいません)

やったこと

1.cronでエラーが出ていないか調べる

crontabに登録したコマンドの標準出力と標準エラー出力をログ書き出ししてcronがちゃんと動作しているか調べました
→どうやら動いてるっぽかった

2.スクリプトに不具合がないか調べる

cronは動いているっぽかったので、スクリプトの問題を調べました。

  • csvのモジュール?はカレントディレクトリを設定することができるらしく、 それを設定するコードがなかったのでそのせいかなと追加してみました。→未だ動かず
  • crontabに登録するコマンドでpythonコマンドにパスを付ける。→普通コマンドラインで起動するときはpython /ディレクトリ/スクリプト.pyとしますが、cronに入れるときはpythonではなく、pythonのフルパス?を書く必要があるそうです。which pythonでパスを調べ、/ディレクトリ/python /ディレクトリ/スクリプト名.pyとしました。→未だ動かず
  • スクリプトの実行権限を見直す。初歩の初歩ですいません。→未だ動かず

この時点で途方に暮れ、とりあえず一日寝かせることにしました。奇妙なのは、コマンドラインではちゃんと動く。cronに入れたときだけ動かない。そして翌日、ついに核心的な方法に到達しました。

  • homeで動くか試してみる。→cronの場合は起動時にカレントディレクトリがhomeになるらしいという情報を聞きつけ、試してみました。確かに、手動で動かすときは、スクリプトディレクトリで動かしてた!さっそくやってみました。→動かなかった!!!
    原因は、アクセスするサイトが証明書必須だったので、requestsで証明書を指定してアクセスさせていたのですが、その証明書を指定するパスが相対パスだったためhomeで起動すると上手く読み込めずエラーとなっていました。この部分を修正したところ、ちゃんとcronで動きました!ドーパミンでたああ

そんなこんなでした

環境構築のまとめ

コマンドとか構文とかは分からなくなってもググれば何か出て来るけど、環境構築だけは言われるがまま魔導書を音読したらベルゼバブが使い魔として召喚できちゃった状態なので、新しいPC買ったりして現在の開発環境を再現しなきゃいけなくなったときに死んでしまわないためのメモ。ちなみにwin10です。

1.VirtualBoxをインストールする

5.2系じゃなくて5.1系がいいらしい。5.2系はvagrantと組み合わせるときに、仮想ビデオカード?がどうとかで?なんか上手く動かない?らしい。

2.vagrantをインストールする

え!?!?ヴェィグラント!?!?ヴァグラントじゃいないんですか!?
N予備校では2.0.0が推奨されていたけど2.0.1をインストールしてみた。ダメなら変えたほうがいいかも。インストール場所はデフォルトでいいらしい。 以下はコマンドプロンプトで操作する。

3.vagrantで仮想ubuntuを入れる

仮想環境をインストールするディレクトリをどっかにmkdirしてそこにcdしておく。 (%USERPROFILE%\vagrant\ubuntu64_16にした) んで、その場所でubuntuのboxをインストールする。vagrant box add ubuntu/xenial64
そしてイニシャライズ。vagrant init ubuntu/xenial64

(4.win7か8系の場合のみpowershellを入れるためにchocolateyをインストール。)

vagrantpowershell使うらしい。インストールのコマンドはまじで呪文詠唱。やばい。@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
これでchocolateyが入ったらしいので、powershellをインストールする。choco install -y powershell

5.仮想ubuntuにログイン

これで準備できたのでSSHで仮想ubuntuにログインする。クライアント?にはrlogin使った。
まずはvagrantを起動。vagrant up (ちなみに停止はvagrant halt突然のドイツ語) rloginをプロトコルssh、Server Adress はlocalhost、Socket Portは2222、User Name はubuntuSSH Identity Key は「(3で作ったディレクトリ)/.vagrant/machines/default/virtualbox」の中に入っているprivate_keyを指定、デフォルト文字セットはUTF-8に設定して接続する。

6.仮想ubuntuを日本語化

ここからはrloginのコンソールを使う。 sudo locale-gen ja_JP.UTF-8で日本語環境を作成。
すごい!ついに噂のsudoを使ったぞ!
echo export LANG=ja_JP.UTF-8 >> ~/.profileで日本語で起動するようにprofileに書き込み?
source ~/.profileで設定を反映する。
dateコマンド使ってみて日本時間が出ればおけ

7.vagrantfileの設定(共有フォルダ)

vagrantfileはマジでヴォイニッチ手稿。形容詞として表現するならヴォイニッチい。「気を利かせてコメントアウトをうまいこと外せば設定できるようにしてあるぜ!」って感じなんだろうけど逆にゴチャゴチャして訳わからん。書き方もよく分からんしvagrantの設定は勉強が必要。 とりあえず、win側とubuntu側それぞれに同期させたいフォルダ作る。そしてvagrantfileの41行目あたりのなんもない行にconfig.vm.synced_folder "(win側のフォルダのvagrantfileから見た相対パス)", "(ubuntu側のフォルダの絶対パス)"を追加する。 Winの場合はさらにその下にconfig.vm.synced_folder "(win側のフォルダのvagrantfileから見た相対パス)", "(ubuntu側のフォルダの絶対パス)" config.vm.provider :virtualbox do |vb| vb.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/(ubuntu側のフォルダの絶対パス)","1"] endを追記する。なんやねん。直上のコマンドのポイントは、ubuntu側のフォルダの絶対パスは/で始まるので、SharedFoldersEnableSymlinksCreate//ってなるところな気がする。

8.vagrantfileの設定(メモリを増やす)

さらに、メモリを増やすために46-52行目辺りにある 「config.vm.provider "virtualbox" do |vb|」と 「vb.memory = "1024"」と「end」の#を外す。 winは管理者権限で起動したコマンドプロンプトfsutil behavior set SymlinkEvaluation L2L:1 R2R:1 L2R:1 R2L:1(fsutil behaviorはNTFS ボリュームの動作を設定する?コマンドで、 set SymlinkEvaluationでコンピューター上に作成できるシンボリック リンクの種類を制御するらしいよ。このコマンドの意味は、ローカルとかリモートとか関係なくシンボリックリンクを有効にしている、らしい。きっと仮想環境と同期するのに必要なのだろう。シンボリックリンクとは、いろいろ調べた結果、影分身だと理解しました。)をやった後、 設定を反映するためにvagrantを再起動させる。 vagrant reload --provision

9.gitの設定もする

あともう一息。。。gitはデフォで入っているっぽい。rloginの方でsudo apt-get updateでアップデートし、最新がちゃんと入ったか確認するためあえてapt-getでinstallしてみる。
sudo apt-get install git
そしてSSHの公開鍵をgithubに登録する。 ssh-keygenでsshkeyを作成。パスワードは入力しないでenterでいいっぽい。入れてもいいんだろうけどcommitするときとか面倒くさい。(入れてしまったので面倒くさいですが再設定するのもなんとなく面倒くさいです)うまくいくとなんかAAとFingerPrintが表示されて~/.sshの中に鍵が作成されてる。
登録するのは.pubの公開鍵の方なのでcat ~/.ssh/id_rsa.pubで中身を表示してgithubのsetting>SSH and GPG keys>SSH keys>NewSSH keyを選択。
Titleは適当(使ってる仮想LinuxのBox名が分かりやすい?)、keyに先ほどcatで表示したものをコピペ入力してadd。

10.一息入れる

トワイニングイングリッシュブレックファーストが好きです。
しかし、結局魔導書の写本を作ってしまった感。。。。