TensorFlowをMacで試す

TensorFlowでましたね。胸熱な感じです。
難しい言葉が溢れる中、これ一発でディープラーニングがキャズムを超えるとは思わないけど、とりあえず使ってみました。
Macに入れて、サンプル動かしたかっただけなのに色んなトラップが仕掛けられてます。

とりあえずインストール

$ pip install https://storage.googleapis.com/tensorflow/mac/tensorflow-0.5.0-py2-none-any.whl
tensorflow-0.5.0-py2-none-any.whl is not a supported wheel on this platform.

はい、こけました。
公式のチュートリアル2行目に書いてますが、Python3系では動かず、Python2.7系でしか動きません。
気を取り直しpyenvで2.7に切り替え再度インストール。
無事インストールされました。

$pip freeze
numpy==1.10.1
six==1.10.0
tensorflow==0.5.0

ディープラーニングといえば、MNISTで試すというが定番なのか知りませんですが、これを試してみます。

# git clone --recurse-submodules https://github.com/tensorflow/tensorflow

さっそく学習させてやろうと思いましたが、またもエラー発生。

# python ./tensorflow/g3doc/tutorials/mnist/fully_connected_feed.py
Traceback (most recent call last):
  File "./tensorflow/g3doc/tutorials/mnist/fully_connected_feed.py", line 23, in <module>
    from tensorflow.g3doc.tutorials.mnist import input_data
ImportError: No module named g3doc.tutorials.mnist

fully_connected_feed.py のモジュール呼び出しの部分を修正

from tensorflow.g3doc.tutorials.mnist import input_data
from tensorflow.g3doc.tutorials.mnist import mnist
↓
import input_data
import mnist

別の部分でエラー発生!キー!

# python ./tensorflow/g3doc/tutorials/mnist/fully_connected_feed.py
Traceback (most recent call last):
  File "./tensorflow/g3doc/tutorials/mnist/fully_connected_feed.py", line 223, in <module>
    tf.app.run()
  File "/Users/takashiaoki/.pyenv/versions/2.7.10/lib/python2.7/site-packages/tensorflow/python/platform/default/_app.py", line 11, in run
    sys.exit(main(sys.argv))
  File "./tensorflow/g3doc/tutorials/mnist/fully_connected_feed.py", line 219, in main
    run_training()
  File "./tensorflow/g3doc/tutorials/mnist/fully_connected_feed.py", line 139, in run_training
    loss = mnist.loss(logits, labels_placeholder)
  File "/Users/takashiaoki/www/tensorflow2/tensorflow/tensorflow/g3doc/tutorials/mnist/mnist.py", line 94, in loss
    indices = tf.expand_dims(tf.range(batch_size), 1)
TypeError: range() takes at least 2 arguments (1 given)

mnist.pyが新しすぎるとの事なので、古いバージョンに差し替える

# python ./tensorflow/g3doc/tutorials/mnist/fully_connected_feed.py
・
・
・
Training Data Eval:
  Num examples: 55000  Num correct: 49218  Precision @ 1: 0.8949
Validation Data Eval:
  Num examples: 5000  Num correct: 4512  Precision @ 1: 0.9024
Test Data Eval:
  Num examples: 10000  Num correct: 9017  Precision @ 1: 0.9017

やっと学習しだしました。
数回やって精度は90%ほどです。

TensorBoardを使えばブラウザ上で学習状況がみれるのでこれを試してみます。

# tensorboard --logdir=./data

ブラウザで、http://localhost:6006/ に接続するとグラフが確認できます。

ログが入ったディレクトリを指定するだけ良いはずなのにでない…

調べてみると相対パスでたダメな模様。

# tensorboard --logdir=/Users/takashiaoki/www/tensorflow/tensorflow/data

はい、動きました。

y軸はミスした数ですね。
これがドンドン下がって学習されていってるのが見て取れます。

アプリケーションフレームワークと違い、もっと土台になる部分のフレームワークです。
これにもうちょい実装がのった形で、誰か何かリリースしてくれないかなーと思う文系エンジニアでした。

Googleフォトで写真のバックアップ環境がようやく整った

Googleフォトでましたね。

長年の課題デジカメ&iPhoneの写真をどうするか問題がGoogleフォトの無料化で90%くらい解決しました。
紆余曲折を経て、ここ数年はデジカメとiPhoneの合わせて15000枚程の写真を、iPhoto(現在の写真アプリ)に保存してました。iPhotoライブラリはデフォルトのままだとMBAのハードディスクの容量が一杯になるので外付けHDです。
ただ、これだとノートパソコンでいつでも気軽にみれないし、外部(オンライン経由)からもみれない。
その解決策としてiPhotoの野良プラグインで定期的にGoogle+にアップロードするというもの。一度に行えるのは1000枚までだし、「ここからこの写真まで」というのも手動で選んで管理しないとダメでした。
Google+へのバックアップはrawファイルじゃなかったので、バックアップはたまにrsyncで別の外付けHDDに行うというからりアクロバティックな技も用いてました。

で、今回のGoogleフォトのリリースでiPhotoを使うのは辞めて、Googleフォトで一括管理することになりました。

既存ファイルのGoogleフォトへの移行作業が結構大変でした。
iPhotoやMacの同期ツールがあるけど、これだと既存Googleフォト(G+移行分)とiPhotoとiPhoneの写真が重複する可能性があります。
そこで、一旦Googleフォトの削除を行いました。Webだと相当時間がかかるため、MacもiPhoneの同期も止めてiPhoneアプリから削除を行います。

予め想定してたのですが、iPhoneアプリで削除を行うとiPhoneの写真も消えてしまいます。私の場合はiPhotoに置いてたので問題なかったですがこれは少し焦りますね。Googleフォトに「バックアップ」のつもりが「同期」状態になってます。Macだと「バックアップ」感覚ですね。Googleフォトから写真けしてもiPhotoから消えるわけではない。
余談続きでいうと、iPhoneアプリのバックアップはバックグランドで動いてるくれません。アプリ立ち上げとかないとダメなんです。謎仕様。

これで、GoogleフォトとiPhoneの写真は綺麗さっぱりなくなりました。
あとは、既存ファイルに関してはMacアプリでiPhotoライブラリのデータをGoogleフォトにバックアップすればOKです。rawファイルをアップロードする事もありすごい時間はかかります。1ファイル20秒程なので数日はかかりそうですが、たまに自動で出来上がるイベントを眺めたりして過ごしてます。

最近はデジカメで写真を取ることは滅多になくiPhoneばかりなので、たまにGoogleフォトのiPhoneアプリを立ち上げバックアップ取っていけば安心ですね。

さらにApple熱が下がり、次はAndroidへのスイッチが確実だと思った今回のI/Oでした。

めでたしめでたし。

退職しました→入社しました→退職しました

長らく更新してないうちに年の瀬ですね。
技術的なトピックが少ないけど今年は色々ありました。

◆2014年7月

10年近くお世話になった会社を退職。
好きなことばかりさせてもらって居心地も良いところだったけど、US行きの頓挫という現実が辛すぎて退職に至りました。

◆2014年8月

アプリ作ってるドベンチャーに入社
自分の世界の狭さと力不足を知る
父他界
お疲れ様でした。
未だテレビで重病のドラマやドキュメンタリーは観れないけど、父の最後を看取れたのは良かった。
犬を飼う
かわいすぎてヤバイ。
父他界後の暗い雰囲気がなくなり家族の笑顔が増えた。

◆2014年9月〜2014年11月

働く
FlaskやったりLaravelやったりiOSやったりパワポやったり。

◆2014年12月

退職。

人生は何が起こるかわからない。
来年が楽しみでしかたない。

良いお年を。

未分類

ITunes Matchが止まる件

iTunes Matchはじまりましたねー。
全部の音楽データをMacに入れてる時は容量をセーブしたくて、USのアカウントで使ってみたのだけどその時は日本のiTunes Storeで購入したDRMで保護されたデータがマッチもアップロードをされずやめてしまいました。

で、今回日本でサービスが始まったということで特に必要性は感じなかったけど、せっかくなので初日にサインアップして御多分にもれず途中で止まるというトラブルに巻き込まれまくりました。

1、Step1が止まる問題は、「iTunes Matchをアップデート」でだいたい解決します。
これはUSバージョンでも発生するようで、英語でのツイートもちょくちょく見ます。
スクリーンショット 2014-05-05 15.59.44
スクリーンショット 2014-05-05 16.24.51

2、Step2の進行中だけど、ちょくちょく止まる問題は、サインアウト・サインインを繰り返せばだいたい解決します。
これもUSバージョンでも初回は発生しました。2〜3回繰り返した気がします。

3、2をやっても一向に進まない場合、これがかなり困りモノです。2000曲中1995曲くらい完了してあと少しで進まないアレです。
「iCloudの状況」を表示させてどの曲で詰まってるか確認します。

スクリーンショット 2014-05-05 16.28.35

スクリーンショット 2014-05-05 16.06.14

詰まってる曲を一旦iTunesから削除してマッチングを再開させます。これで完了すれば、この曲が原因なのが確定ですね。 その際Step3は光の速さで完了します。処理的には並列で動いてるけど、表示は単一なのでStep2だったということでしょうか。Step3のアップロードのアクションは既に終わってる状態です。

私の場合25曲程がこのどうしょうもないファイルたちでした。
うち12曲はなんとしてもアップロードさせたい思い出アルバムの曲たちです。13曲入りのアルバムの12曲だけがアップロードできない状態でした。
タグを弄ってもAACにしてもWAVにしてもダメなのでやっぱり波形の問題?と思いAudacityという波形編集ソフトでフィルターかけてみたけどダメ。
最終的に一応アップロード可能なファイルができたのだけど、曲の最後7秒ほどを削ったバージョン。3秒ほどではダメ。アップロードに失敗してしまいます。
ただ7秒だと曲が削られてしまうんですよね。残念。さすがにこれは採用できず未だアップロードできないままです。

これがアップルのソフトウェアクオリティというべきか、長年のアップル信者の私もさすがにがっかりです。
以前なら「こういうところもひっくるめてアップルの良さ!」と言ってたになあ。

GhostをHerokuで動かす

noteにせよMediumにせよGhostにせよシングルカラムのブログが流行ってますね。だいぶ前にGhost入れてみてフーンで終わってたので改めてインストールする事にしました。
Herokuはなんだかんだで1年に1回くらい使うけど全然使い方が頭に入らないので今回整理の意味も込めて書いていきます。

これがないと話にならないので、まずはGhostをダウンロードします。
「Ghost」をGoogleで検索すると「Image for Ghost」とか出てきて心臓に悪いですね。

ダウンロードしてきたGhostを解凍・展開します。5/1現在バージョンは0.4.2。
展開したGhostのディレクトリに移動します。

$ cd /path/to/ghost/
$ npm install
$ npm start
$ open http://127.0.0.1:2368/

node.jsが入ってることが前提だけど、これだけどとりあえず動きます。

これをパブリックに公開する為、Herokuにデプロイします。

まずは、デプロイ後に実行されるコマンドを記述したProcfileを作成します。

web: NODE_ENV=production node index.js

いきなりだけど、こけるの承知でHerokuへデプロイする準備にとりかかります。
ProcfileもひっくるめてCommitします。後述のHeroku createする前にcommitしておいた方が後々楽です。

$ git init
$ git add .
$ git commit -m "Initial Commit"

ローカルにHerokuコマンドは入ってるけど鍵とかどうなってるか忘れたので一旦鍵をリセットして新しいのを作成・送信。

$ heroku keys:clear
$ ssh-keygen -t rsa -C "メールアドレス"

.ssh/cofigに下記を追記

IdentityFile ~/.ssh/id_rsa

Herokuへログインします。

$ heroku login

「君のローカルに公開鍵みつかったけどどれを転送する?」
とでるのでさっき生成した公開鍵をHerokuに転送する。

鍵の準備が整ったのでアプリを作成します。
Herokuのサイトからももちろんできるけど、コンソールを開いてるのでコンソールから作ります。
アプリ名はなんでもいいので、

$ heroku create

を実行。

Creating hoge-moge-7151... done, region is us
http://hoge-moge-7151.herokuapp.com/ | git@heroku.com:hoge-moge-7151.git
Git remote heroku added

みたいに一瞬で作成される。
gitのリポジトリを事前につくってたので、Herokuのリモートリポジトリも追加されます。

これで兎にも角にもデプロイする準備ができたのでpushします。

$ git push heroku master
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'git@heroku.com:hoge-moge-7151.git'

DBがsqliteのままなのでこける
Railsと同じくGhostはsqlite3だけど、Herokuではsqliteが使えないのでPostgresを使います。

まずnpmでpgモジュールがインストールされるようにpackage.jsonを編集。

"dependencies": {
        "pg": "latest”,
        "bcryptjs": "0.7.10",
        "bookshelf": "0.6.1”,

config.jsにPostgresの設定を書きたいところだけど、デフォルトでPostgresが用意されているわけでないので、一旦Herokuのサイトに行きPostgresのアドオンをインストールします。
アドオン一覧のページに行って、Heroku Postgresを追加。プランはFreeのにしておきます。

追加されたPostgresアドオンの詳細ページ(Connection Setting)に接続情報が記載されています。このページを開きながらコンソールに戻りconfig.jsの設定を行います。
編集するのはもちろんProductionの方です。

以下のようになります。

    production: {
        url: 'http://hoge-moge-7151.herokuapp.com',
        mail: {},
        database: {
            client: 'postgres',
            connection: {
              host: process.env.POSTGRES_HOST,
              user: process.env.POSTGRES_USER,
              password: process.env.POSTGRES_PASSWORD,
              database: process.env.POSTGRES_DATABASE,
              port: '5432'
            },
            debug: false
        },
        server: {
            // Host to be passed to node's `net.Server#listen()`
            host: '0.0.0.0',
            // Port to be passed to node's `net.Server#listen()`, for iisnode set this to `process.env.PORT`
            port: process.env.PORT
        }
    },

DBだけでなくURLやnodeのポートなんかも設定を変更しています。
DBの接続情報はHerokuの環境変数からとることにします。環境変数へ登録するのは先程のConnection Settingの情報ですね。

heroku config:set POSTGRES_HOST=****
heroku config:set POSTGRES_USER=****
heroku config:set POSTGRES_PASSWORD=****
heroku config:set POSTGRES_DATABASE=****

これでPostgresの設定も完了。

これで一応動くけど、認証メールが送れないとGhostの管理画面で怒られ続けられます。
自分にしか飛ばさないので、SMTPをGmailにしておきます。

mail: {
    transport: 'SMTP',
    options: {
        service: 'Gmail',
        auth: {
            user: ‘hoge@gmail.com',
            pass: ‘*******'
        }
    }
},

再度pushします。

$ git push heroku master
 -----> Launching... done, v13
      'http://hoge-moge-7151.herokuapp.com/ deployed to Heroku

To git@heroku.com:hoge-moge-7151.git
   79bed5c..7675064  master -> master
$ open http://hoge-moge-7151.herokuapp.com/

問題なく開けれたら成功ですね。
個人的には、Herokuは開発環境/グローバルでのテストとしてはいいけど、痒いところに手が届かず、なかなか公開サービスには使えないと思ってたけどブログ程度ならいい気がしてきた。
開発環境/グローバルでのテストに特化したPaaSがあったらいいのにな。昔のGeocitiesみたいに広告入るPaaS。需要あると思う。

0

L1ビザの面接@アメリカ総領事館

L1ビザが移民局で承認されると、アメリカ大使館・総領事館で面接があります。
基本的にここまでくれば問題なしとのことだけど、これまで同様準備が大変です。

流れとしては、

  1. DS-160のフォーム入力
  2. ビザ申請料金の支払い・面接の予約
  3. 面接

です。

DS-160のフォーム入力

まず、DS-160というフォームの入力をオンラインで行います。

一般的なペラ1のフォームとは大違いで、ページ数は20ページくらいで入力項目も?なものも多いです。もちろん途中保存もできるけど70分程かかります。
基本英語だけど吹き出しで日本語訳を出すこともできます。
現在の仕事・両親の名前・過去5回のアメリカへの渡航歴等多岐に渡ります。I-797の情報やアメリカの免許があれば免許番号とかもいるので手元に用意して置いた方がいいです。
色んなサイトで書かれてる、写真のアップロードはなかなかの苦行です。
私は4回くらいエラーがでてアップロードできませんでした。
Photoshopである程度加工してサイトにあるPhoto Cropping Toolで加工してようやくOKでした。偶然かもしれないけど、このPhoto Cropping Toolをつかったら一発でいけたのでなかなか上手くいかない場合は試してみたらいいと思います。
これでようやくDS-160が発行されます。最後に表示される証明書?はメールにして送っておくといいです。

ビザ申請料金の支払い・面接の予約

次に、ビザ申請料金の支払い・面接の予約です。
料金はL1なので$190。結果問題なかったのですが、私は、大使館面接のこと <予約編> – ひのすけまるの珍道中で拝見した情報を元に支払いページに行きました。
支払った後に支払い受付番号が発行されるのでなく、なぜか支払う前に受付番号が付与されます。サイト上にしれっとこの番号が書かれてるけど、超重要です。支払い後確認メールすらこないです。ほんと重要。
ただ、このページは本来どこからいくのだろう? 大使館面接のこと <予約編> – ひのすけまるの珍道中にリンクがあったから良かったものの本来の遷移元が見つからなかったです。他の支払いページはあった。
https://cgifederal.secure.force.com/

予約を行う前にサインアップして、DS-160程ではないけどフォームに名前やパスポート番号等をガシガシ入力していく必要があります。
ビザの種類でL1(Blanket)とあるけどL1の表記はない。かなり焦ったけどL1(Blanket)にチェックを入れておけば良いです。(問い合わせ確認済み)
先ほどのビザ申請料金の受付番号を入力する欄もありますね。
全部入力が終わったらようやく面接の予約です。だいたい週2日くらいの間隔でAvailableな日があります。明日の予約とかは厳しいけど来週の予約とかならいけそうです。

面接

ようやく面接ですね。
面接前日の話、本業が忙しくて全然準備してなかったので面接を延期しようとおもってサイトを訪れたら前日じゃもう日程変更はダメみたいでした。ということで前日18:00くらいから、バタバタしだして「あれ、何持っていくんや?」って状態に。
「明日10:00から面接ですけど、何持っていけばいいですか?」と問い合わせフォームで問い合わせてみても時既に遅し。
タイミング・書いてる人のビザの種類で変わるという事もあってブログでは色々書かれています。
サポーティングレターがいるとかレターパックがいるとか等。
結果L1(ブランケットでない)の面接に必要なのは、

  1. 面接の予約確認表 (オンラインで予約したあとに送られてくる)
  2. DS-160の確認表
  3. パスポート
  4. I-797B(I-129のReceipt込)
  5. 写真(2inch*2inch)

これを、大使館のサイトで推奨されてる並びでクリアファイルに入れる。
ただ5の写真、私は要らなかったです。
これは謎で大使館のサイトに要ると書いてるし実際総領事館でビザ申請に並んでる人はみんなもってたけど最後まで要らなかった。
面接の時に2回、写真ないけどいいかと聞いたけど要らないとのこと。謎。

ここからは大阪のアメリカ総領事館の話になります。東京の大使館と少し違うこともあるかと。

当日、10:00に予約を入れてたけど、これが10:00から面接なのか10:00に総領事館来いという意味かはわからず。
とりあえず9:30に総領事館にいったところ20人くらいの列ができてました。
並ぶこと15分程でセキュリティチェックの後館内に入る事が出来ました。PCや携帯はここに預けます。
その後3Fに移動。
ここで、必要書類のチェックと質問2件。待ち時間は7〜8分程。
聞かれた内容は、「会社名は?」「何の会社?」の2つだけ。英語でくるかと思ったけどまさかの日本語。しかも若干関西弁。
3人いたけど、みんな日本語で話してたみたい。日系アメリカ人かな。
で、同じフロアでデジタルな感じの指紋採取。

その後、2Fに面接に行けと言われテクテク階段を降りてくとすでに20人くらいの列。これは少し待った20分くらいかな。携帯なし時計なしのボッチには長く感じた。
面接は、免許センターの窓口的なカウンターでイケメンの白人の兄ちゃんに4つほど英語で質問されました

  • 「今の会社に何年いる?」
  • 「何の会社?」
  • 「役職は?」
  • 「部下何人いる?」

で「OK、4日くらいでビザ発行されるから! Have a good day!」で終了でした。
他の人は、ビザのタイプや新規や更新かにもよるけど、大体そんな感じっぽい。更新の人はUSの住所とかも聞かれたっぽい。
2つカウンターあったけど、もう片方はかなり長時間に及んでた。属人性によるのかわからないけど、少なくともL1の私はそんな感じでした。
と、謎のカウンターが一時開けられてそちらに移動させられ面接受けてる人もいました。そこも長時間に及んでた。

総領事館到着から面接終了後退館まで1時間弱でした。
パスポートが返却されてないけど、まずは一安心です。

0

AWSの課金状況をプログラマブルに取得する

AWSの課金状況をプログラマブルに取得するには、CloudWatch経由で取得します。
Billing用のAPIがあるわけでなく、CloudWatchでAWSの下記情報を監視するように設定し、そこから課金のメトリクスを取得します。

「課金」と書いたものの正確には「請求額」の取得ですね。
取得にあたり2つ注意点として、

  • Amazon側の請求確定のサイクルは必ずしも1時間に1回というわけではないので、ずっとEC2を使ってるのにAPIでデータを取得してみても1時間前と2時間前の料金が同じという事は多々あります。大体3時間くらいのサイクルでアップデートされてる気がします。
  • サービス別では取得できるけど、リージョン別やインスタンス別の取得等はできません。

という事があります。

以下がスクリプトです。
Pythonなんでbotoを利用しています。
どこのブログに書いてたけど確かにec2のネームスペースというのが気持ち悪い。
元々、CloudWatchはEC2の負荷状況を監視する目的だけだったからかな。

import datetime
import os
import sys
import boto.ec2.cloudwatch

AWS_REGION = "us-east-1"
AWS_KEY_ID = "***************"
AWS_SECRET_KEY = "***************"
 
cloudwatch_conn = boto.ec2.cloudwatch.connect_to_region(
        AWS_REGION,
        aws_access_key_id=AWS_KEY_ID,
        aws_secret_access_key=AWS_SECRET_KEY)

end = datetime.datetime.utcnow()
start = end - datetime.timedelta(hours=4)
 
services = ['AWSDataTransfer', 'AmazonEC2', 'AmazonGlacier','AmazonRoute53',  'AmazonS3', 'AmazonSNS']
 
for service in services:
        value = cloudwatch_conn.get_metric_statistics(
                3600,
                start,
                end,
                'EstimatedCharges',
                'AWS/Billing',
                'Maximum',
                dimensions = {'ServiceName':[service], 'Currency':['USD']}
        )
        if not value:
                continue
        print service
        print value
        print value[0]['Maximum']

課金状況を取得するには、
metric_nameにEstimatedChargesをnamespaceにAWS/Billingにしてやる必要があります。
BillingServicesは使ってるサービスを列挙すれば良いです。

US-EASTにすべてのリージョンの課金情報があつまるので、それに接続します。

4時間前から取得していますが、これも前述通り1時間前とかだと請求額が確定してないからかデータの取得はできません。

色々おもしろいことができそうですね。
現在は、これをFluentdに投げて、Kibanaで読み込むということをしています。
CloudWatchのグラフみとけというツッコミはいらないです。

0

Vagrantでsynced_folderがマウントされない件

新しいBoxを初めてvagrant upしたら以下のようなエラーがでた。

[default] -- /share
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
 
mount -t vboxsf -o uid=`id -u vagrant`,gid=`id -g vagrant` /share /share
 
Stdout from the command:
 
Stderr from the command:
 
/sbin/mount.vboxsf: mounting failed with the error: No such device

で、sshでログインはできるけど/shareディレクトリはマウントされておらず。
調べていくと、virtualbox周りのエラーという事で、ログイン後vboxaddを再度セットアップをすれば治るとの記事をみたので実行したもののなおらない。

[vagrant@localhost ~]$ sudo /etc/init.d/vboxadd setup
Removing existing VirtualBox DKMS kernel modules           [  OK  ]
Removing existing VirtualBox non-DKMS kernel modules       [  OK  ]
Building the VirtualBox Guest Additions kernel modules
The headers for the current running kernel were not found. If the following
module compilation fails then this could be the reason.
The missing package can be probably installed with
yum install kernel-devel-2.6.32-358.6.2.el6.x86_64
 
Building the main Guest Additions module                   [FAILED]
(Look at /var/log/vboxadd-install.log to find out what went wrong)
Doing non-kernel setup of the Guest Additions              [  OK  ]

失敗。
言われた通りkernel-devel-2.6.32-358.6.2.el6.x86_64をインストールする前に、さらに調べていくと、kernel と kernel headersの違いがかもという事。

[vagrant@localhost ~]$ yum list kernel*
Loaded plugins: fastestmirror, presto
Determining fastest mirrors
 * base: www.ftp.ne.jp
 * extras: www.ftp.ne.jp
 * updates: www.ftp.ne.jp
Installed Packages
kernel.x86_64                     2.6.32-220.el6             @anaconda-CentOS-201112091719.x86_64/6.2
kernel.x86_64                     2.6.32-358.6.2.el6          @updates
kernel-firmware.noarch            2.6.32-358.6.2.el6          @updates
kernel-headers.x86_64             2.6.32-358.6.2.el6          @updates

なるほど確かにkernel-headersが2.6.32-358に対して、kernelが2.6.32-220と若干古い。
じゃあ、kernelのupdateだけでいいんじゃないかと思い以下を実行

yum update kernel
kernel                     x86_64            2.6.32-358.18.1.el6            updates             26 M

反映させる為に再起動を試みたけど同じエラーが発生でmountされていない。
1時間ほど経過してたのでイライラしつつ、さっき言われた通りにkernel-devel-2.6.32-358.6.2.el6.x86_64をインストール。

yum install kernel-devel-2.6.32-358.18.1.el6.x86_64

きたっ!
セットアップを実行後、vagrant reloadで無事マウントされました。
配布されてたboxが悪かったのか、VirtualBox4.2.6とか古いやつを入れてたせいか分からなかったけどこれで無事インストール完了しました。
めでたしめでたし。

0

はてなブックマークとあとで読む系のサービスをつなぐHaboryをリリースしました。

logo-2

HaboryというWebサービスをリリースしました。
はてなブックマークとあとで読む系のサービス(Readability,Pocket,Instapaper)をつなぐWebサービスです。はてなブックマークするだけで自動的にあとで読む系のサービスにもポストされます。
一度連携設定したら何もしなくていいサービスですのでぜひご利用ください。

今回に関しては作ったモチベーションとか開発小咄的なものはなく、
半年かけて作ったFaboryが非常に残念な結果に終わった反面、開発期間も2週間程のお気軽サービスがどうなるか、これがみてみたいというのと、
この手のサービスは一度セットアップに訪れたらユーザーはもうWebサイトを訪ねる事はありません。(ツイエバ、ハテブテ然り) これのマネタイズという程ではないけどサーバー代ペイできる方法の模索、
くらいです。

簡単にいうとなんとなく作ったという事ですね。

0

通知センターにObjective-Cで通知を出す

なぜかMacアプリ作ってます。今をときめくiPhoneアプリでなくMacアプリ。
備忘録として、Macの通知センターにobjective-cで通知させる方法です。

Screen Shot 2013-09-09 at 7.08.17 PM

とか

Screen Shot 2013-09-09 at 7.07.50 PM

とかみたいなやつですね。

■Notification.h

#import <Cocoa/Cocoa.h>
@interface Notification : NSObject <NSApplicationDelegate, NSUserNotificationCenterDelegate>
- (void)notify:(NSString *)title subtitle:(NSString *)subtitle informativeText:(NSString *)informativeText url:(NSString *)url;
@end

■Notification.m

#import "Notification.h"
@implementation Notification
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
}
- (void)notify:(NSString *)title subtitle:(NSString *)subtitle informativeText:(NSString *)informativeText url:(NSString *)url
{
[NSUserNotificationCenter defaultUserNotificationCenter].delegate = self;
 
NSUserNotification *userNotification = [[NSUserNotification alloc] init];
userNotification.title = title;
userNotification.subtitle = subtitle;
userNotification.informativeText = informativeText;
userNotification.userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:url, @"url", nil];
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:userNotification];
}

// ダブルクリックでURLで指定した先に飛ぶ
- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
{
NSURL *url = [NSURL URLWithString:[notification.userInfo valueForKey:@"url"]];
[[NSWorkspace sharedWorkspace] openURL:url];
}
@end

で、通知を出したいところでこのクラスのnotifyというメソッドを呼び出す。

notification = [[Notification alloc] init];
    [notification notify:@"タイトル" subtitle:@"サブタイトル" informativeText:@"テキスト" url:@"http://yahoo.com"];

subtitleは、あまり使われてない印象。
これを引数でタイトルやテキストを指定できるアプリケーションにして、LLから呼び出せるようにしとけば俺々ツール作る時に便利ですねー。