読者です 読者をやめる 読者になる 読者になる

佐藤屋敷

文章力の無いテックブログ。技術も文章もわかっていてもわからないことだらけ。

【Mac】Visual Studio for Macのプレビュー版をインストールした

11月16日にマイクロソフトが「Visual Studio for Mac」を発表

ということで、遅れながらも我が家のMacBook Proにもプレビュー版をインストールしてみました。

www.visualstudio.com プレビュー版のダウンロードはこちらから。

※Xcodeがインストールされていないとダメです。できれば最新版。

まずは普通にダウンロードします。 f:id:satoysan:20161120142858p:plain

ずんずんとインストールします。よくわからないので全部入れてしまえ!という精神で、承諾チェックを入れながら先に進みます。 f:id:satoysan:20161120142944p:plain

f:id:satoysan:20161120143002p:plain

f:id:satoysan:20161120143036p:plain

f:id:satoysan:20161120143055p:plain

f:id:satoysan:20161120143144p:plain

インストール完了したので、起動します。 f:id:satoysan:20161120143714p:plain

f:id:satoysan:20161120143731p:plain

モバイルアプリだけでなくMacのアプリも作れるんですね。

#すこしHello worldを作ってみる

ほんとにすこし。

f:id:satoysan:20161120160414p:plain

f:id:satoysan:20161120160438p:plain

ターゲットOSの選択がいろいろできるみたいですね。 とにかくフォントが美しい。Macっていいですね。 f:id:satoysan:20161120160802p:plain

using System;
Console.WriteLine("Hello World!");

を加えて、実行。(再実行とか書いてますが、初回はデバッグなしで開始とでています)

f:id:satoysan:20161120161211p:plain

無事出力。これの他にまっさらなウィンドウも出力されます。ほんとはこっちのウィンドウがメインです。 あ、using Systemはなくても大丈夫かも。

今回はここまで。

はてなブログでカッコいいWebアイコンフォント「Font Awesome」を使って記事を飾る方法

はてなブログ デザイン

Font Awesomeって何?

簡単に言うと記事にいろいろなアイコンが挿入できるフォントです。 はてなブログだとこんなイメージ

f:id:satoysan:20160818151754p:plain

その中にある家とか矢印とかのアイコンのことです。

f:id:satoysan:20160818151844p:plain

前準備

Font Awesomeのcssをはてなブログで読み込む必要があるので、CDNを持ってきます。 詳しくは以下のリンクを確認してください。

Font Awesome
http://fontawesome.io/

License
http://fontawesome.io/license/

CDN
https://www.bootstrapcdn.com/fontawesome/

f:id:satoysan:20160818152311p:plain

Font Awesomeをはてなブログで使うための設定

記事内で呼び出すためにはCSSを設定しますが、ブログの設定とデザインの2か所で設定が可能です。また、書き方が若干異なります。

ブログの設定から

f:id:satoysan:20160818152435p:plain

ブログの設定にある詳細設定タブをクリックして、検索エンジン最適化にある「headに要素を追加」にlinkタグを設定して保存します。

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">

f:id:satoysan:20160818152536p:plain

※バージョン4.6.3については執筆時点ですので、適宜変更してください。

デザインから

f:id:satoysan:20160818152709p:plain

ブログのデザインメニューからスパナ型のカスタマイズアイコンをクリックして、デザインCSSをクリックします。 そこにすでに@importが指定されていますので、それの下に以下を追加して保存します。

@import url("//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css");

※バージョン4.6.3については執筆時点ですので、適宜変更してください。

早速記事を書いてみる

記事の書き方ですが、はてなブログには3種類の書き方があります。「見たまま」「Markdown」「はてな記法」それぞれのアイコンの書き方を紹介します。

<i class="fa fa-home"></i> 家

classの中身について

  • fa アイコン使うよ
  • fa-home アイコンの家を使うよ

ちなみに後述するサンプルの表現では<i class="fa fa-home fa-lg"></i> 家のように fa-lg を追加で指定していますが、これは表示されるアイコンのサイズになります。 未指定が一番小さく、fa-lgfa-2x ~ fa-5xとサイズを大きくしていくことができます。

見たままモードでアイコン表示

f:id:satoysan:20160818152929p:plain

まず、見たままモードだとそのままで通常ブログは書けますが、アイコンを見ながらの記事は書けません。このため、アイコンが表示されているのかを確認するためにはプレビューを見ながら定義していきます。 また、アイコンを埋め込むためには「HTML編集」で作業する必要があり、それに加えてFont Awesome側でサンプルとして定義されている<i>タグでは、見たままモードのHTML編集で消えてしまいます。(余計な?タグや特定の設定ができないようにしているのは、はてな側の優しさだと思いますが)しかし、これではアイコンの表示ができないので、別のタグ<span>タグで代用します。

f:id:satoysan:20160818153019p:plain
( Font Awesomeサイト側ではタグが指定されている )

ではさっそくHTMLを編集します。

f:id:satoysan:20160818153140p:plain
(編集前イメージ)

編集前HTMLから以下のようにアイコンをHTMLで設定します。 また、<span>タグと</span>タグの間に全角のスペースを必ず入れてください。これを入れておかないと見たままモードの処理でタグが消されてしまいます。 <li>その2 家 <span class="fa fa-home fa-lg"> </span></li>

f:id:satoysan:20160818153236p:plain

このように書いた後、プレビューで確認するとアイコンが表示されます。

f:id:satoysan:20160818153317p:plain

Markdownモードでアイコン表示

見たままモードよりはるかに簡単になります。そのままHTMLタグを埋めていくのみです。

f:id:satoysan:20160818153357p:plain
(編集イメージ)

適用すると以下のように確認できます。

f:id:satoysan:20160818153429p:plain
(プレビューイメージ)

はてな記法モードでアイコン表示

f:id:satoysan:20160818153512p:plain
(編集イメージ)

適用すると以下のように確認できます。

f:id:satoysan:20160818153539p:plain
(プレビューイメージ)

アイコンの一覧と大きさ変えてみたり向きを変えてみたりなど

アイコン一覧 http://fontawesome.io/icons/

いろいろなサンプル http://fontawesome.io/examples/

詳しくは上記を確認してみてください。いろいろな表現ができることが分かります。

最後に

今回の記事はあくまで「はてなブログ」で「Font Awesome」アイコンを使う方法として記載していますので細かいフォントの利用方法については公式や他サイトをご確認ください。

いい記事が書ける手助けになれば。といいつつあまり記事書いていない私が言うのも。。。

PHPでRedisのPubSubを使ってクライアントに情報を通知したい

Vagrant Redis Node.js PHP

久々に書きます。今回のでは完成ではないけど、最低限はクリアしたかな。
わざわざ手間のかかることやってたりしますが許してください。

■目的、したいこと

  • PHPでクライアント別にリアルタイムに情報を通知したい。(RedisのPub/Subを使いたい)
  • ついでにRedisのmaster/slaveも試しでやってみる。

■準備したもの

  • Redis (オープンソースのkey-valueデータストア)
  • php_redis 5.6
  • Node.js
  • Socket.IO

■準備済みのもの

  • vagrant CentOS 6.5 x64
  • XAMPP v3.2.1 (古い) php 5.6

■おおまかな手順

1. vagrantの準備
2. Redisのインストール
3. Redisの設定変更と起動
4. XAMPPのphp 6.5でRedisのextensionを設定する
5. CentOSにもRedisのextensionを設定してみる
6. nodejs準備(nvmの準備)
7. jsでsubscriberを作る
8. 動作させてみる

■おおまかな説明

1. vagrantの準備

今回は3台のサーバを用意しようかなとおもいましてVagrantfileはこんな感じ。コメントのところとか削ってますが。

Vagrant.configure(2) do |config|

  config.vm.box = "puphpet/centos65-x64"
  config.vm.define :web1 do | web1 |
      web1.vm.hostname = "web1"
      web1.vm.network "private_network", ip: "192.168.33.10"
      web1.vm.provider "virtualbox" do |vb|
        vb.memory = "2048"
      end
  end

  config.vm.define :web2 do | web2 |
      web2.vm.hostname = "web2"
      web2.vm.network "private_network", ip: "192.168.33.11"
      web2.vm.provider "virtualbox" do |vb|
        vb.memory = "2048"
      end
  end

  config.vm.define :web3 do | web3 |
      web3.vm.hostname = "web3"
      web3.vm.network "private_network", ip: "192.168.33.12"
      web3.vm.provider "virtualbox" do |vb|
        vb.memory = "2048"
      end
  end

end

ほか、vagrantユーザの他に私の中の慣習としてるdevelopユーザの作成など。。

2. Redisのインストール

以下各サーバでやります。(master/slave)
ちなみにsudoでないとダメな環境の場合は$ sodo に置き換えてください。今回は基本rootでまっしぐらします。

epelの追加 ( centos65 64bit )

# wget http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm

epelリポジトリのインストール

# rpm -ivh epel-release-6-8.noarch.rpm

epelリポジトリデフォルト無効化するため開く

# vi /etc/yum.repos.d/epel.repo

enable=1をenable=0に変更する。

Redisのインストール

# yum -y install redis --enablerepo=epel

自動起動の設定

# chkconfig redis on

以上でRedisのインストールは完了

3. Redisの設定変更と起動

サービスの起動

# service redis start

バージョンの確認。問題なし。

# redis-server -v
 Redis server version 2.4.10 (00000000:0)

ひとまずiptablesを止めておく。試しで止めているだけです。セキュリティ上いろいろ必要な場合は計画を立てて実行してください。

# /etc/init.d/iptables stop

次にRedisの設定変更をします。今回 192.168.33.10 にあたるweb1はRedisのmasterにして、他のweb2,web3はslaveにします。
設定ファイルは以下となります。

# vi /etc/redis.conf

以下confの中。web1サーバで変更する項目。どこからでも接続を許可する。

#bind 127.0.0.1
bind 0.0.0.0

以下もconfの中。web2,web3で変更する項目。slaveの設定というかmasterサーバはドコドコですよと。

# slaveof <masterip> <masterport>
slaveof 192.168.33.10 6379

以上で設定完了。各サーバでRedisの再起動をする。

# service redis restart

設定を確認する。web1の場合( redis-cliで入り、infoコマンドを実行する )

[root@web1 ~]# redis-cli
redis 127.0.0.1:6379> info
redis_version:2.4.10
:
:
role:master

設定を確認する。web2,web3の場合( redis-cliで入り、infoコマンドを実行する )

[root@web3 ~]# redis-cli
redis 127.0.0.1:6379> info
redis_version:2.4.10
:
:
role:slave
master_host:192.168.33.10
master_port:6379
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0

問題なくmasterとslaveで分かれました。これでmasterの更新内容がslaveで参照可能となります。
master_link_statusがdownだと接続失敗しています。ネットワーク周りを確認してください。

また、vm.overcommit_memory=1の対応について今回は省略します。
redisのログや、ネットで検索してみてください。

4. XAMPPのphp 6.5でRedisのextensionを設定する

Windows上というか、XAMPP v3.2.1 php6.5でRedisに接続を試みたいので、dllを設定します。

必要な物は2つ

php_igbinary-1.1.1-5.6-ts-vc11-x86.zip
php_redis-2.2.5-5.6-ts-vc11-x86.zip

php.iniでは以下の様な設定をします。(dllを\xampp\php\extの下に入れてね)

extension=php_igbinary.dll
extension=php_redis.dll

igbinaryはこちら
https://pecl.php.net/package/igbinary/1.1.1/windows

redisはこちら
http://windows.php.net/downloads/pecl/snaps/redis/2.2.5/

あとはwindowsのコマンドプロンプトで以下のように問題無ければOK。
dllが正しくないとバージョンチェックだけで怒られます。もし怒られるようなら、phpバージョンなどを再確認して環境に適したzipをダウンロードして下さい。

C:\Users\satoysan>php -v
PHP 5.6.12 (cli) (built: Aug  6 2015 12:06:20)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
    with Xdebug v2.2.5, Copyright (c) 2002-2014, by Derick Rethans

Webでどうのこうのしたい場合はXAMPPのApacheを再起動してください。

次に実行テストを行います。
test.php

<?php
$redis = new Redis();
$redis->connect("192.168.33.10",6379);
echo $redis->ping();

実行するとこのような感じに。+PONGが帰ってくればOKです。

C:\Users\satoysan>php  C:\Users\satoysan\IdeaProjects\redisTest\test.php
+PONG

5. CentOSにもRedisのextensionを設定してみる

同様にCentOSにもPHPやらApacheやらをインストールしてPHPからRedisを実行するため、さくっとyumでインストールします。(web1に)

apacheとphpのインストール

# yum -y install httpd php

サービスの起動

# service httpd start

自動起動の設定

# chkconfig httpd on

pecl redisのライブラリインストール
(php redisドキュメント https://github.com/phpredis/phpredis#classes-and-methods)

# yum -y install php-pecl-redis --enablerepo=epel

apache 再起動

# service httpd restart

先ほどのphpプログラムが動作すればOKです。

6. node.js準備(nvmの準備)

それではクライアントを作るためにnode.jsをガツガツインストールします。
これはweb2,web3にインストールを行います。適当な一般ユーザで実行します。
私の環境の場合はdevelopユーザを作っています。

NVM(Node Version Manager)を導入

$ git clone https://github.com/creationix/nvm.git ~/.nvm
$ source ~/.nvm/nvm.sh

node.jsのバージョンチェック

$ nvm ls-remote

現時点での最新バージョンインストール

$ nvm install v5.6.0
$ nvm use v5.6.0
 Now using node v5.6.0 (npm v3.6.0)

デフォルト設定

$ nvm alias default v5.6.0

確認

$ node -v
v5.6.0

npmのアップデート

$ npm update -g npm

npmのグローバルのパッケージをアップデート

$ npm outdated -g
$ npm update -g

実行環境の構築

$ mkdir nodejs_server
$ cd nodejs_server
$ npm init

package.jsonを編集して軽い感じに

{
  "name": "nodejs_server",
  "version": "1.0.0",
  "description": ""
}

package.jsonができているので、使うかも?ライブラリをローカルインストール。

$ npm install --save redis
$ npm install --save socket.io
$ npm install --save socket.io-emitter
$ npm install --save socket.io-redis
{
  "name": "nodejs_server",
  "version": "1.0.0",
  "description": "",
  "dependencies": {
    "redis": "^2.4.2",
    "socket.io": "^1.4.5",
    "socket.io-emitter": "^1.0.0",
    "socket.io-redis": "^1.0.0"
  }
}

7. jsでsubscriberを作る

web2に以下のコードを用意するsubclient.js( web2のチャンネルはtest_1 )

var subscriber = require('redis').createClient(6379, 'localhost');

//個別のチャンネルと全体用のチャンネルを試しで。
subscriber.subscribe(["test_1","all"]);

subscriber.on('message', function(channel, message) {
    console.log('channel: ' + channel + ', message: ' + message);
});

web3に以下のコードを用意するsubclient.js( web3のチャンネルはtest_2 )

var subscriber = require('redis').createClient(6379, 'localhost');

//個別のチャンネルと全体用のチャンネルを試しで。
subscriber.subscribe(["test_2","all"]);

subscriber.on('message', function(channel, message) {
    console.log('channel: ' + channel + ', message: ' + message);
});

web2,web3でjsをそれぞれ実行して待ち状態へ。

$ node subclient.js

8. 動作させてみる

windows上でもweb1でも構わないので、以下のphpを実行してみる。

<?php
$redis = new Redis();
$redis->connect("192.168.33.10",6379);

$redis->publish('test_1', 'test1!! hello, world!');
$redis->publish('test_2', 'test2!! hello, world!');

$redis->publish('all', 'test users! hello, world!');

上記を実行するとweb2,web3で起動していたsubclient.jsの元にそれぞれメッセージが無事届いて幸せに。

web2

channel: test_1, message: test1!! hello, world!
channel: all, message: test users! hello, world!

web3

channel: test_2, message: test2!! hello, world!
channel: all, message: test users! hello, world!

一応届いている。
使ったり使ってなかったりいろいろ中途半端だけど。。。
次回はもっとクライアント!ッて感じへ続く。図を次は書きます。

MeCabをWindows 8.1上のjavaでインストールを行う( Intellij IDEA 15 )

Intellij IDEA 15 MeCab java

クリスマスイブですね。安心してください。そんなのかんけーねー。

■目的、したいこと

  • MeCabをjavaで使いたい
  • Windows 8.1 64bitで使いたい
  • Intellij IDEAで使いたい
  • とにかくお手軽にサクッと

■準備するもの

  • Windows 8.1 64bit
  • Intellij IDEA (記事時点なら14 or 15)
  • MeCab本体のWindows版(コンパイル済みの IPA 辞書辞書付き)
  • mecab-0.996_x64.zip
  • cmecab-java-2.0.1-src.zip

■インストールの前に

Intellij IDEAについては既にインストール済みを想定です。javaのコンソールプロジェクトを作成して

System.out.println("TEST");

くらいは実行できることを前提です。

■おおまかな手順

  1. MeCab本体のインストール ( mecab-0.996.exe 配布版は32bit )
  2. libmecab.dllの設置 ( 64bit版を設置 )
  3. cmecab-2.0.1.jarの作成
  4. Intellijでモジュールの読み込み
  5. javaで解析実行

■おおまかな説明

1. MeCabのインストール( mecab-0.996.exe )

f:id:satoysan:20151224171626p:plain
UTF-8でインストールします。

2. javaバインディング用のファイルをダウンロードしてきます。

f:id:satoysan:20151224171949p:plain
mecab-0.996_x64.zipとcmecab-java-2.0.1-src.zipをダウンロードします。
そして、mecab-0.996_x64.zipをまず解凍してbinディレクトリにあるlibmecab.dllをSystem32以下にコピーする。
(PATHを通せば別にココでなくても良かったハズですが、今回は面倒なのでコピー)

f:id:satoysan:20151224172728p:plain

3. Intellijでまずjavaプロジェクトを作成してcmecab-2.0.1.jarを作ります

cmecab-java-2.0.1-src.zipを自由なトコロにまず解凍します。
次にIntellijで新規javaプロジェクトの作成

特に何も指定せず
f:id:satoysan:20151224173315p:plain

Command Line Appで進めてあとは自由なプロジェクト名を設定
f:id:satoysan:20151224173330p:plain

できたプロジェクトからそのままAnt Buildをつかってcmecab-2.0.1.jarを作ります
f:id:satoysan:20151224174014p:plain

「+」ボタンで先ほど解凍したcmecab-java-2.0.1-srcの中にある「build.xml」を指定する
f:id:satoysan:20151224174112p:plain

でBuildを行う。(緑の三角ボタン)
f:id:satoysan:20151224174417p:plain

cmecab-2.0.1.jarが作成される。
f:id:satoysan:20151224174639p:plain

4. Intellijでモジュールの読み込み

Project Structureでjarを読み込みます。
f:id:satoysan:20151224175058p:plain
cmecab-2.0.1.jarとlibにあるbridj-0.6.1.jarを読み込みます。


5. サンプルソースを実行する。

HowToUse - cmecab-java - 使用方法 - MeCabのJavaバインディング+Lucene/Solr用トークナイザ・フィルタ - Google Project Hosting
このソースそのままを実行。

以下念のため引用

package com.company;

import net.moraleboost.mecab.Lattice;
import net.moraleboost.mecab.Tagger;
import net.moraleboost.mecab.impl.StandardTagger;
import net.moraleboost.mecab.Node;

public class Main {

    public static void main(String[] args) {

        StandardTagger tagger = new StandardTagger("");
        System.out.println("MeCab version " + tagger.version());

        // Lattice(形態素解析に必要な実行時情報が格納されるオブジェクト)を構築
        Lattice lattice = tagger.createLattice();

        // 解析対象文字列をセット
        String text = "本日は晴天なり。";
        lattice.setSentence(text);

        // tagger.parse()を呼び出して、文字列を形態素解析する。
        tagger.parse(lattice);

        // 形態素解析結果を出力
        System.out.println(lattice.toString());

        // 一つずつ形態素をたどりながら、表層形と素性を出力
        Node node = lattice.bosNode();
        while (node != null) {
            String surface = node.surface();
            String feature = node.feature();
            System.out.println(surface + "\t" + feature);
            node = node.next();
        }

        // lattice, taggerを破壊
        lattice.destroy();
        tagger.destroy();

    }
}

すると以下のように出力される。

f:id:satoysan:20151224175439p:plain

■最後に

とにかく試し実行のためにもう少しキッチリやるべき場所とか無視してここまで来ました。
本気で動かすときはCentOSとかでやるので、とにかくWindows上でガリガリ開発するための準備となります。

MQTTを試してみる( 2/2 )

MQTT Vagrant

前回に引き続きMQTTを試します。長いです。

■前回の記事

satoyashiki.hatenablog.com

■環境、用意するもの

  • Windows 8.1 64bit
  • Windows上のCentOS6.X 仮想サーバ(vargrant)でのmosquitto-1.4.5
  • Windows上のクライアントはPaho 1.1 ( JavaScrpt client )

■Paho 1.1 ( JavaScript版 )

www.eclipse.org

■前提

  • Windows上のCentOS6.Xへmosquittoをyumでインストール済み
  • mosquittoが、CentOS上で起動済みでPython接続が成功したあとの話

■以下手順続き

  1. WindowsからJavaScript接続してみる。上手くいかない。
  2. あ、mosquittoがWebSocketモードじゃないのね?設定を変える。動かない。
  3. mosquittoのRedHat/FedoraのyumのリポジトリはWebSocketが無効なのでソースコンパイルが必要とわかる。
  4. ソースコンパイルをいろいろする。
  5. やっと準備完了でmosquitto起動
  6. WindowsからJavaScript接続してみる。上手くいく。やったー。
  7. 試しにCentOSをやめてUbuntuでやってみる。WebSocketが素直にうまくいく。
  8. これは罠なので気を付けようって話。(ググったブログは結構Ubuntuのサンプルばかり。)
  9. 結局世界のStack Overflowは凄いと言うことだ。
  10. 疲れました。お疲れ様です。

1. WindowsからJavaScript接続してみる。上手くいかない。

コードはPahoからダウンロードしてきてコードを準備( 上にあるPahoページからmqttws31-min.jsを入手する )

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>TEST</title>
    <script type="text/javascript" src="mqttws31-min.js"></script>
    <script type="text/javascript" src="mqclient.js"></script>
</head>
<body>

</body>
</html>

client.js

// Create a client instance
var client = new Paho.MQTT.Client("192.168.33.20", 1883 , "clientId" + new Date().getTime());

// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;

// connect the client
client.connect({onSuccess:onConnect});

// called when the client connects
function onConnect() {
    // Once a connection has been made, make a subscription and send a message.
    console.log("onConnect");
    client.subscribe("/World");
    message = new Paho.MQTT.Message("Hello");
    message.destinationName = "/World";
    client.send(message);
}

// called when the client loses its connection
function onConnectionLost(responseObject) {
    if (responseObject.errorCode !== 0) {
        console.log("onConnectionLost:"+responseObject.errorMessage);
    }
}

// called when a message arrives
function onMessageArrived(message) {
    console.log("onMessageArrived:"+message.payloadString);
}

IPとかはvagrantで設定したものです。
ポートはmosquittoのデフォルトです。

chormeのデベロッパーツールを開いて実行。なんか上手く動いてない。
f:id:satoysan:20151112174535p:plain

WebSocket connection to 'ws://192.168.33.20:1883/mqtt' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET

2. あ、mosquittoがWebSocketモードじゃないのね?設定を変える。動かない。

WebSocketモードじゃないので設定を変えることに。

mosquitto.confの設定マニュアルeclipse.org

mosquitto.conf

# Place your local configuration in /etc/mosquitto/conf.d/

pid_file /var/run/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

#log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d

protocol websockets

protocol websocketsを追加

mosquitto再起動。

# /etc/init.d/mosquitto restart
Shutting down Mosquitto MQTT broker1447318610: mosquitto version 1.4.5 terminating
1447318610: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
                                                           [  OK  ]
Starting Mosquitto MQTT brokerError: Websockets support not available.
Error found at /etc/mosquitto/mosquitto.conf:12.
Error: Unable to open configuration file.
                                                           [FAILED]

なぜにWebsocketがサポートされとらんのじゃ!いろいろ調べる。いろいろググる。

3. mosquittoのRedHat/FedoraのyumのリポジトリはWebSocketが無効なのでソースコンパイルが必要とわかる。

stackoverflow.com
あー・・・なるほどなるほど。Answersを見ると結構衝撃。
つまり、CentOS版のパッケージはダメってことですね。Webosocketsが。

4. ソースコンパイルをいろいろする。

駆け足で行きます。

# yum remove mosquitto
# yum install gcc-c++
# yum install cmake
# yum install openssl-devel
# cd /usr/local/src/
# wget http://mosquitto.org/files/source/mosquitto-1.4.5.tar.gz
# tar zxvf mosquitto-1.4.5.tar.gz
# cd mosquitto-1.4.5
# vi config.mk

mosquittoのパッケージはさよならします。そしてコンパイルする準備で最初yumでいろいろインストールします。

config.mkをイジってWITH_WEBSOCKETS:=noをyesに変更してWebosocketsを有効に。ちなみにWITH_SRVをyesにしたままだと、c-areasというライブラリがないと怒られるので、こちらもインストールする。面倒な場合はconfig.mkでnoにすればコンパイルは通ります。他libuuid-develなんかも入れますが、WITH_UUIDをnoにすれば・・・うんぬん。

以下全部対応します。

# cd ../
# wget http://c-ares.haxx.se/download/c-ares-1.10.0.tar.gz
# tar zxvf c-ares-1.10.0.tar.gz
# cd c-ares-1.10.0
# ./configure
# make
# make install 
# cd ../
# yum install libuuid-devel
# wget http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/snapshot/libwebsockets-1.5-chrome47-firefox41.tar.gz
# tar zxvf libwebsockets-1.5-chrome47-firefox41.tar.gz
# cd libwebsockets-1.5-chrome47-firefox41
# mkdir build
# cd build
# cmake ../ -DLIB_SUFFIX=64
# make 
# make install

mosquittoのコンパイル準備完了

# cd /usr/local/src/mosquitto-1.4.5
# make
# make install
# cd /etc/mosquitto
# useradd mosquitto
# cp mosquitto.conf.example mosquitto.conf
# vi mosquitto.conf

ということで、mosquitto.confを修正してprotocol websocketsに変更

#protocol mqtt
protocol websockets

ちょっと試しでmosquitto --helpとかしてみるとエラーがでたりします。

mosquitto: error while loading shared libraries: libwebsockets.so.5: cannot open shared object file: No such file or directory

こいつに対応するにはパスを指定する必要があります。

# vi /etc/ld.so.conf.d/liblocal.conf

liblocal.conf

/usr/local/lib64
/usr/local/lib

そして適用

# ldconfig

ちょっとコマンド実行お試し。

# mosquitto --help
mosquitto version 1.4.5 (build date 2015-11-12 09:54:01+0000)

mosquitto is an MQTT v3.1 broker.

Usage: mosquitto [-c config_file] [-d] [-h] [-p port]

 -c : specify the broker config file.
 -d : put the broker into the background after starting.
 -h : display this help.
 -p : start the broker listening on the specified port.
      Not recommended in conjunction with the -c option.
 -v : verbose mode - enable all logging types. This overrides
      any logging options given in the config file.

See http://mosquitto.org/ for more information.

うまくいきました。

5. やっと準備完了でmosquitto起動。

では早速起動

# mosquitto -c /etc/mosquitto/mosquitto.conf -d
1447322705: mosquitto version 1.4.5 (build date 2015-11-12 09:54:01+0000) starting
1447322705: Config loaded from /etc/mosquitto/mosquitto.conf.
1447322705: Opening websockets listen socket on port 1883.

おお、websockets listen socketしたー!

6. WindowsからJavaScript接続してみる。上手くいく。やったー。

ようやく帰ってきました。JavaScriptのソース実行
f:id:satoysan:20151112190739p:plain

CentOSには厳しい道程があるので、気をつけよう!そのうちyumでWebSocket対応版が出ると思うけどね!*1

付録

srcコンパイルで入れたmosquittoにゃ起動シェルがないので、/etc/init.d/にシェルを置きます。
https://gist.github.com/basuke/7777918
ここは環境に合わせて修正する。

7. 試しにCentOSをやめてUbuntuでやってみる。WebSocketが素直にうまくいく。

vagrantでubuntu/trusty64boxファイルを作る。
で・・・ささっとapt-getで放り込んで実行

$ sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
$ sudo apt-get update
$ sudo apt-get install mosquitto
$ su -
# cd /etc/mosquitto/
# vi mosquitto.conf
# service mosquitto start

mosquitto.confの中を修正。protocol websocketsに。
さっきのjavascriptコードのIPが違うのでそこだけ変更して実行すると…うまくいきました。
つまりはUbuntuでやってる人はこの問題にぶち当たらないということですね!
でも本番サーバがCentOSになってたりしてハマり道を歩むという。。。

9. 結局世界のStack Overflowは凄いと言うことだ。

 ありがとう。Stack Overflow。ありがとう。Stack Overflowユーザの皆様。

*1:ついでにこの記事も死滅する運命

MQTTを試してみる( 1/2 )

MQTT Vagrant

仕事では無縁なものだったので話には聞いていたけど全く手を出していなかったのですが、そろそろ知っておかないとなあと感じ始めましたので、やってみることにしました。(ラズパイで使う予定)

■MQTTとはなんぞや

  • 1対多の通信可能なプロトコル
  • すごく軽量
  • 仕組みが簡単
  • IoTサービスにうってつけ
  • チャットやらスマホのゲームなんかにも使われる

■目的、したいこと

  • MQTTを使ってみたい
  • サーバーはCentOSで
  • ブローカーはMosquitto
  • クライアントはJavaScriptを希望だけど、今回はPython。

■環境、用意するもの

  • Windows 8.1 64bit
  • Windows上のCentOS6.X 仮想サーバ(vargrant)でのmosquitto-1.4.5
  • Windows上のクライアントはPaho 1.1 ( Python client )

■入手元

ブローカー( Mosquitto )

クライアント( Paho )

■以下手順

  1. CentOSを準備( vagrant init puphpet/centos65-x64 ) *1
  2. CentOS起動( vagrant up )
  3. CentOSの初期の設定をごにょごにょする。(password変えたり、ユーザ作ったり)
  4. yum で mosquitto をインストールする。
  5. mosquittoを起動する。
  6. WindowsからPython接続してみる。上手くいく。
  7. JavaScript編は次回へ続く

■以下、気になるところの説明

4. yumでmosquitto をインストールする。

# cd /etc/yum.repos.d

yumリポジトリを準備します。

# wget http://download.opensuse.org/repositories/home:/oojah:/mqtt/CentOS_CentOS-6/home:oojah:mqtt.repo

ファイルをダウンロードします

# yum install mosquitto

mosquittoをインストール

5. mosquittoを起動する。

# /etc/init.d/mosquitto start

6. WindowsからPython接続してみる。上手くいく。

WindowsにPython2.7がインストールされていることが前提です。無い場合はインストールしてください。

Takahiro Ikeuchi氏のコードを拝借して接続テストを試みます。librabuch.jp

まずは paho-mqtt というパッケージを用意します。私の場合はIntellij IDEAですので、Pythonで新規プロジェクトを準備し、内部ターミナルでpipを実行しました。
f:id:satoysan:20151111002759p:plain

それでは、コードを拝借してsub.py,pub.pyの準備を。。一部IPやらトピックなどを修正しています。

pub.py ( 1秒置きに5回ループしながら「test test」をサブスクライバーへ )

from time import sleep
import paho.mqtt.client as mqtt

host = '192.168.11.52'
port = 1883
topic = 'sato/a1'

client = mqtt.Client(protocol=mqtt.MQTTv311)

client.connect(host, port=port, keepalive=60)

for i in range(5):
    client.publish(topic, 'test test')
    sleep(1)

client.disconnect()

sub.py

import paho.mqtt.client as mqtt

host = '192.168.11.52'
port = 1883
topic = 'sato/a1'

def on_connect(client, userdata, flags, respons_code):
    print('status {0}'.format(respons_code))

    client.subscribe(topic)

def on_message(client, userdata, msg):
    print(msg.topic + ' ' + str(msg.payload))

if __name__ == '__main__':

    client = mqtt.Client(protocol=mqtt.MQTTv311)

    client.on_connect = on_connect
    client.on_message = on_message

    client.connect(host, port=port, keepalive=60)

    client.loop_forever()

で…sub.py,pub.pyを実行したのですが、接続失敗しました。なぜなら…iptablesが邪魔しておりました。22ポートを除く他のポートがALLブロックされてて…なので、まずは解放というか停止。

# /etc/init.d/iptables stop
iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
iptables: Flushing firewall rules:                         [  OK  ]
iptables: Unloading modules:                               [  OK  ]

気を取り直してsub.py,pub.pyを実行。問題なく1秒置きにsub.py側に「sato/a1 test test」が出力されます。
f:id:satoysan:20151111005322p:plain

まずはめでたしめでたし。

7. JavaScript編は次回へ続く

こっちはWebSocketでハマります。CentOS用のmosquittoの闇は深いです。
次回へ続く。

*1:vagrantの起動とか設定はここでは省きます。

WindowsにVirtualBoxとVagrantをインストールしたメモ

VirtualBox Vagrant

◆目的、したいこと

複数台のCentOSをWindows上で起動したい。
CentOS6.7にしてみる。

◆環境

  • OS: Windows 8.1 64bit
  • CPU: i7-4790 3.60GHz
  • Mem: 8G

◆インストールしたもの

  • VirtualBox-5.0.8-103449-Win.exe
  • VirtualBox 5.0.8 Oracle VM VirtualBox Extension Pack
  • vagrant_1.7.4.msi
  • vagrant-manager-windows-1.0.0.3.exe *1

◆それぞれの入手とインストール

■VirtualBoxの入手

■Vagrantの入手

■Vagrant Managerの入手

■インストールの順序というかやった順序

  1. VirtualBox-5.0.8-103449-Win.exeを何も考えずインストール
  2. Extension Packもインストール
  3. vagrant_1.7.4.msiをインストール( 最後に再起動要求が来るのでYesに )
  4. Vagrant Managerはまだインストールしてなかった
  5. 私の場合C:\はSSDで容量少ないからそんなところにいろいろ置きたくなかったのでVirtualBoxの仮想マシンフォルダの変更とvagrantの設定ファイルをD:\の自分の決めたところへ
  6. ひとまずvagrantの設定ファイルはD:\vMachine\centosとした
  7. cmdコマンドでコマンドプロンプト起動してD:\vMachine\centosへ移動
  8. そこでvagrant initコマンドの実行をしてVagrantfileを作る
  9. エディタでVagrantfileファイルの編集
  10. 初回起動くらいはコマンドラインでvagrant upを実行し仮想サーバを3台起動
  11. 初回はbento/centos-6.7からダウンロードされるので時間がかかります
  12. 無事起動が確認できたら一旦シャットダウンvagrant halt
  13. Vagrant Managerのインストール
  14. あとは自由にSSHなどで接続してそれぞれのサーバの設定を行います。*3
9.で書いたVagrantfileの内容
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  config.vm.box = "bento/centos-6.7"
  
  config.vm.define :web1 do | web1 |
    web1.vm.hostname = "web1"
    web1.vm.network "public_network", ip: "192.168.1.50"
  end
  
  config.vm.define :web2 do | web2 |
    web2.vm.hostname = "web2"
    web2.vm.network "public_network", ip: "192.168.1.51"
  end

  config.vm.define :db1 do | db1 |
    db1.vm.hostname = "db1"
    db1.vm.network "public_network", ip: "192.168.1.60"
  end
  
end
10.vagrant upを実行するとこんな感じで表示(抜粋)
D:\vMachine\centos>vagrant up
Bringing machine 'web1' up with 'virtualbox' provider...
Bringing machine 'web2' up with 'virtualbox' provider...
Bringing machine 'db1' up with 'virtualbox' provider...
==> web1: Checking if box 'bento/centos-6.7' is up to date...
==> web1: Clearing any previously set forwarded ports...
==> web1: Clearing any previously set network interfaces...
==> web1: Preparing network interfaces based on configuration...
    web1: Adapter 1: nat
    web1: Adapter 2: bridged
==> web1: Forwarding ports...
    web1: 22 => 2222 (adapter 1)
==> web1: Booting VM...
==> web1: Waiting for machine to boot. This may take a few minutes...
    web1: SSH address: 127.0.0.1:2222
    web1: SSH username: vagrant
    web1: SSH auth method: private key
    web1: Warning: Connection timeout. Retrying...
    web1: Warning: Remote connection disconnect. Retrying...
==> web1: Machine booted and ready!
==> web1: Checking for guest additions in VM...
==> web1: Setting hostname...
==> web1: Configuring and enabling network interfaces...
==> web1: Mounting shared folders...
    web1: /vagrant => D:/vMachine/centos
==> web1: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> web1: flag to force provisioning. Provisioners marked to run always will still run.
==> web2: Checking if box 'bento/centos-6.7' is up to date...
==> web2: Clearing any previously set forwarded ports...
==> web2: Fixed port collision for 22 => 2222. Now on port 2200.
==> web2: Clearing any previously set network interfaces...
==> web2: Preparing network interfaces based on configuration...
    web2: Adapter 1: nat
    web2: Adapter 2: bridged
==> web2: Forwarding ports...
    web2: 22 => 2200 (adapter 1)
==> web2: Booting VM...

~~~~~
VirtualBoxマネージャーを見るとこんな感じでしっかり3台起動している。*4

f:id:satoysan:20151108132717p:plain

さて、ここまできたらSSHでサーバにつなぎます。前述のVagrantfileではweb1サーバは"public_network", ip: "192.168.11.50"として記載していますのでそのままTeraTermなどで接続します。*5

vagrant-managerで起動するイメージ

f:id:satoysan:20151108135205p:plain

vagrant upと同等のことがコマンドプロンプトを開かずに行えます。*6

f:id:satoysan:20151108135453p:plain

vagrantへsshログインする

f:id:satoysan:20151108142010p:plain

ユーザー名:vagrant
パスワード:vagrant
rootもパスワードがvagrantです

■その他の話

windowsでvagrant sshが素直にできないので、TeraTermを使って接続するのですが、ssh接続が127.0.0.1:2222になるのが嫌でVagrantfileconfig.vm.network "private_network"ではなく"public_network", ip: "192.168.1.50"にしています。いくつかネットで検索しても"private_network"のip指定でsshできているような記述があるのですがどうしてもできなかったので・・・。*7
その後web1などに接続してApacheをインストールすればブラウザでhttp://192.168.1.50/と叩けばテストページが表示します。

*1:VagrantManagerはなくてもコマンドたたけば基本はいらない

*2:VirtualBox 5.0.8 Oracle VM VirtualBox Extension Packをダウンロード

*3:各サーバのメモリ設定などは他のサイトでたくさん記載しておりますので、検索してみてください

*4:コマンドプロンプトを管理者モードで起動してvagrant upするとVirtualBoxマネージャーの電源オンが連動しなくてハマります。

*5:ipconfigとかで表示しませんがSSHで接続できます。

*6:コマンドで実行できるのがvagrantのイイところとかそういうのは置いておく。

*7:なんかうまいやり方を探す時間があまりなかったので今回はこれで