2016/12/28

x11vnc、Xvfb、Xdummy、VirtualGL とか

最終的には、HeadlessでRemoteで仮想VMも全部がGPUアクセラレーションが機能するようにしたいわけだが、ひとまずはx11vncとその周辺から。

gdm + gnome-session
前回までのセットアップでは、Xを手動でstartxして起動していたが、実験の意味もあり
GDMを入れることにした。

lightdmを最初に入れたが、なぜかログインできず。原因がXAuthorityパーミンションでもなく、解決困難だったため lightdm をやめて gdm に切り替えた。

$ sudo apt install gdm
これだけでXorgでgdmが自動起動するようになる。gnome-sessionも同時に入る。

$ sudo systemctl stop gdm
ってやってもXが止まってくれない。defaultがgraphical.targetだからかな。。

gdm 常時offにしたい時
$ sudo systemctl set-default multi-user.target してリブート

gdm 常時onにしたい時
$ sudo systemctl set-default graphical.target してリブート

$ systemctl get-defaultで
multi-user.targetとなっている場合は、systemctl start/stop gdmがうまく動く。

x11vnc
これを使うと、物理ディスプレイのXをVNCでミラーリングできる。物理ディスプレイをリモート操作できるっていう代物。
$ sudo apt install x11vnc

別のホストPCで使っているvnc4serverとかは仮想XドライバなのでGPUが機能しない。
GPUイネーブルなドライバが機能するのは、ディスプレイデバイスに接続されているX環境だけなのだ。正確には物理GPUアクセス可能なネイティブなビデオドライバが動くX環境。

x11vncは以下のXvfbやDummyと組み合わせて使うとより自由度が高まる。

Xvfb
Xの仮想フレームバッファドライバ。残念ながら3DはMesaで3DHWは使えない。
仮想X環境をいくつも簡単に作れるので便利ではある。
$ sudo apt install xvfb

XDummy
これはスクリプトと説明されているけれど、プログラムソースコードが含まれている。
これを動かすためには、dummyビデオドライバとgccやclangなどのコンパイラが必要。
$ sudo apt install xserver-xorg-video-dummy
$ sudo apt install clang
$ XDummy install

すると、スクリプト内に含まれているプログラムがコンパイルされて~/bin/xdummy.so が作られる。
これがx11vncが起動するXの仮想ドライバになる・・・のかな?・・・

XDummyスクリプトを通して、このxdummy.soを使うとdlsymがundefinedだとかでエラー。

XDummy スクリプトで cc でコンパイルしている行に" -ldl" を追加して再度実行。
ユーザレベル起動だとハング!!

$ sudo XDummy :0
でやっと動いた。rootじゃなくても動くようになったと書いてあったけどなぁ。
なにかやり忘れているのかもしれないが、ちゃんとした説明がなく、-help 頼み。

org-video-dummyのdummyドライバを使ったXorg起動とこのxdummy.soは関係あるのか、ないのかイマイチ体感できず。

XDummyはXvfbよりちょっとだけ優れているのだそうな。RandRとGLX extensionsが機能することと、2Dパフォーマンスがいいらしいが、結局仮想ドライバなので、GLXはソフトエミュ。

x11vnc設定ファイル
x11vncには山ほどのオプション設定がある。sshトンネル経由とか。。把握しきれない。
色々物色して、.x11vncrcと言う名前のファイルにオプションの'-'外して羅列することで設定できるとわかり、色々実験した結果、自分なりの.x11vncrcは以下の通り。

.x11vncrc の内容
usepw
nonc
shared
noxrecord
noxdamage
noxfixes
norc
xkb
repeat
scr_keyrepeat 4-10
o x11vnc.log
usepwで初回起動でpw設定できる。いちいち-storepasswordとかやらなくていい。
あとはだいたいお決まりオプション。

VirtualGL
これはXGLなアプリをこのツールを通して実行することで、GPUイネーブルなドライバが動いているXでGLコマンドを実行させて出力イメージを転送表示するツールみたいなもの。

Linux Packages からvirtualglのdebパッケージをダウンロード
$ sudo dpkg -i debファイル

vglrunとか、vgl**なコマンドが使えるようになる。
vglconnectやvglclientとかは、より遠方のX端末同士をつなぐ時に使うみたい。
自分がやりたいこととは若干違ったので、vglrunだけ試してみた。


2016/12/10

Ubuntu16.04 intel-graphics-update-toolでドライバインストール

久々の投稿です。

Intel Skylakeアーキテクチャーのセットトップボックス Beebox-S 6200U/B/BB を買ってしまった。愛用中のShuttle DS57Uはサーバーに徹しているので、今回のBeeboxはデスクトップ環境で使っていこうと思う。


自分のBeebox-sの構成は、CPU Core-i5 6200U(Intel Graphics HD 520)、メモリ 16GB、ストレージ SATA-SSD 256GB + M.2-SSD 512GB。
ストレージデバイスを2つ内蔵できるのがいい。デュアルブートにしたかったので。
All SSDなので、ファンレスでOK。Shuttle DS57U並みに静音です。


Ubuntu16.04 Serverインストール
Desktopインストールではない。後で色々やりたいことがあるんで、gdmとか使わない。
インストーラで、Virtual Machine HostとOpenSSHにチェックを入れてインストール。
その後はおきまりの手順。
$ sudo apt update
$ sudo apt upgrade
$ sudo apt dist-upgrade

そうそう、Ubuntu14.04を入れようと思ったけど、構成が新しすぎなのか、ネットワークデバイスが認識されなかった。

X環境インストール
$ sudo apt install ubuntu-desktop とかで入れちゃうとgdmとかがセットアップされてしまうので、バラで入れていきます。

$ sudo apt install xserver-xorg-video-intel
$ sudo apt install xfonts-100dpi xfonts-75dpi xfonts-scalable
$ sudo apt install xserver-xorg
$ sudo apt install xinit

startsで素のXが起動する段階。

Xfce4 デスクトップ環境インストール

$ sudo apt install xfce4 xfce4-goodies

$ sudo apt install fonts-takao-pgothic fonts-takao-gothic fonts-takao-mincho
で、日本語フォントも入れる。
startxすると綺麗なXfce4デスクトップでXが動く。

Intelグラフィックスドライバインストール

ちょっと前までは、intel-graphics-installerがUbuntu15.10までしか対応していなくて難儀していた感がありましたが、今はintel-graphics-update-toolに改名され、16.04にも対応しました。
ここの 2.0.2 の方を使います。2.0.3は、16.10用です。

$ sudo apt install fonts-ancient-scripts
$ sudo apt install libpackagekit-glib2-18
$ sudo dpkg -i intel-graphics-update-tool_2.0.2_amd64.deb (ダウンロードしたやつ)

Xサーバー起動してドライバセットアップ
$ startx
$ sudo intel-gaphics-update-tool

で起動したインストーラウイザードに沿ってドライバインストールして再起動。

ちゃんと入ったかな?
$ sudo apt install mesa-utils
$ glxinfo | grep Device
  Device: Mesa DRI Intel(R) HD Graphics 520 (Skylake GT2) (0x1916)
よし。

$ glxinfo | grep version
server glx version string: 1.4
client glx version string: 1.4
GLX version: 1.4
    Max core profile version: 3.3
    Max compat profile version: 3.0
    Max GLES1 profile version: 1.1
    Max GLES[23] profile version: 3.1
OpenGL core profile version string: 3.3 (Core Profile) Mesa 11.2.2
OpenGL core profile shading language version string: 3.30
OpenGL version string: 3.0 Mesa 11.2.2
OpenGL shading language version string: 1.30
OpenGL ES profile version string: OpenGL ES 3.1 Mesa 11.2.2
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.10

ふむ。3.3ですか。4.xなら良かったのに。GLES3.1はちょっと嬉しいかも。

ということで、このマシンではGPU関係のことを中心にいろいろと遊ぶ予定です。


2016/04/30

GoogleSiteページをRubyで更新する

AppEngineやHerokuの無料枠ではオープンなサイトを立てることになる。もちろん、そこはプログラマブルなので認証を自分で組み立てればプライベート化は可能だ。
でも、Googleサイトならば設定でプライベートサイトをいくつも建てられる。自分で組まなくていい。

ここでの目的は、DDNSを使わずにいかに快適にプライベートサーバーへアクセスできるか?で、サイトページを自動更新できれば、どの端末からでも活用しやすいだろうと。

Goolge Sites API を使えば簡単にサイトの更新をプログラムから行える。っていう話ですが、説明やサンプルが充実しているのは、JavaとPythonだけ。じゃあrubyは?

rubyにも'gdata'gemがあるのだけど、残念ながら目的のSitesAPIはまだ?サポートされていないようですね。

それに認証手順のページもrubyに関しては雑というか古い?ような気がする。OAuth2.0での完全な流れが読み取りづらい。

素直にPythonで書いたほうが絶対楽ですが、ここは敢えてRubyでやってみたという内容です。

google-api-client
$ gem install google-api-client
で入れる。googleauth ・ jwt ・ oauth2 と芋づるで入る。

Using OAuth 2.0 for Web Server Applications
当たりを読みます。Google Cloud Platformのコンソールから適当なプロジェクトでOAuth2.0の認証クライアントIDを作る。
そこからダウンロードできる認証ファイル(JSONファイル)をそのまま使います。

このページにもRubyでの流れが書いてあるのですが、どういうわけか実用的な流れが書いてありません。Pythonガイドのように一度認証手順を踏んだら後はrefresh_tokenでaccess_token取得する流れを示して欲しかった。

OAuth2.0はサービスアカウント認証に比べ、どうしてもこの手順が必要なのが面倒ですが、Google的にはこれを推奨している。認証コードを受け取るサイト(redirect先)を自分で用意する事ができれば全てを自動化することも不可能ではないだろう。

refresh_tokenを記録するための最初の手順スクリプト
require 'google/api_client/client_secrets'
require 'google/api_client/auth/storage'
require 'google/api_client/auth/storages/file_store'

CLIENT_SECRETS_FILE = 'client_secrets.json'
CREDENTIAL_STORE_FILE = 'credential_store.json'

client_secrets = Google::APIClient::ClientSecrets.load(CLIENT_SECRETS_FILE)
auth_client = client_secrets.to_authorization
auth_client.scope = 'https://sites.google.com/feeds/'
puts auth_client.authorization_uri.to_s

puts 'code='
auth_client.code = gets
auth_client.fetch_access_token!

storage = Google::APIClient::Storage.new(
  Google::APIClient::FileStore.new(CREDENTIAL_STORE_FILE))

storage.write_credentials(auth_client)

ググッても中々この手順をシンプルに示してくれている記事を見つけることが出来なかった。

CLIENT_SECRETS_FILE=ダウンロードしたjsonファイル
CREDENTIAL_STORE_FILE=保存したいファイル名
を指定して実行すると、ブラウザでアクセスするためのURLが表示される。
puts auth_client.authorization_uri.to_s の部分ですね。

スクリプトは認証コード入力状態で待機。

そのURLブラウザでアクセス>Googleデフォルトのコード表示ページ(urn:ietf:wg:oauth:2.0:oob)に認証コードが表示されるので、それをコピペ。

auth_client.fetch_access_token! で認証され、auth_clientには次回用のrefresh_tokenも取得される。

後はこれをファイルにでも記録して再利用すればいい。そのAPIも用意されているので使ってみたのが最後のstrage部分。

Site API Protocol Guide
Sites APIをラップしてくれているRubyGemがなかったので、ここを頑張って読む。

gdataAPIとかで何とかならないのか?と調べたけれど、ラップされていないサービスAPIは結局Protocol Guideに書いてある手順と変わらない。ならば、ややこしい物を使うより素直にhttp gemを使うことにした。

認証済みファイルからaccess_token取得してサイトページ内容を更新するスクリプト
# coding: utf-8
require 'google/api_client/client_secrets'
require 'google/api_client/auth/storage'
require 'google/api_client/auth/storages/file_store'
require 'net/http'
require 'oga'

CREDENTIAL_STORE_FILE = 'credential_store.json'

# ファイルを読んで認証
credential = Google::APIClient::Storage.new(
  Google::APIClient::FileStore.new(CREDENTIAL_STORE_FILE))

auth_client = credential.authorize

authorization = "access_token=#{auth_client.access_token}"

feed = "https://sites.google.com/feeds/content/site/自分のサイト名"
feed += "?path=/home" # path=で更新したいページをパスで指定
feed += "&#{authorization}" # 認証access_tokenを付ける

# GET
uri = URI.parse(feed)
result = Net::HTTP.get URI.parse(feed)
xml = Oga.parse_xml result
entry = xml.at_xpath('feed/entry')
title = entry.at_xpath('title').text
etag = entry.attribute('gd:etag').value
url = entry.at_xpath('id').text

# ページ内容をファイルから読んで加工
xml = Oga.parse_xml File.open('entry.xml').read
entry = xml.at_xpath('entry')
entry.attribute('gd:etag').value = etag
entry.at_xpath('title').inner_text = title
body = entry.to_xml

# PUT
uri = URI.parse("#{url}?#{authorization}")
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
  request = Net::HTTP::Put.new uri
  request.set_content_type('application/atom+xml')
  request.body = body
  http.request request
end
p response

ページ内容テンプレートファイルは Updating an entry に記載されているものから若干修正する程度のものを使う。contentタグの中に変更内容を記述しておく。

PUT先のURLはfeedレスポンスのにあるhrefアトリビュートにあると書かれているが、エレメントが他にたくさんあるのでogaで探すのが面倒です。見た限り<id>が同じ内容なので、そっちを使うようにした。
gd:etagをちゃんとページ固有のETagにする必要があるので、オリジナルを取得してテンプレート側へセットする。

titleもセットしておく必要がある。違うtitleにしてしまうとfeedをGETするときのpath=のパス名も変更することになる。この辺はあまり汎用性を確保できない。

こうやって実際にやってみると、難しくないがリファレンスドキュメントだけでは理解しきれないのも事実。チュートリアルがもう少し優しければよかったなぁ。


2016/04/14

VLCプレイリスト出来なかったのでHLSメニューをクラウドファイルで

タイトルが何言ってるかよく分からないですね。

我が家で地デジ録画システムが安定稼働しているが、録画していない時は recfsusb2nでリアルタイムHLS (HTTP Live Streaming) をしている。それを時々、VLCからURL直接叩いて視聴するということをやっているのだけど、URLだとどの放送局なのかが良くわからない。
そうだ!プレイリスト形式でチャンネルリスト作ってやればいいじゃないか!

今更ながらに閃いたわけですが、簡単だろと色々トライしてみたけど出来なかった・・・
だから別の方法で解決した。というお話です。

1stトライ
録画サーバーにM3U形式のチャンネルURLリストを出力させるようにして、VLC media player使って「ネットワークストリームを開く」にからアクセスするとM3Uリストと認識して読んでくれる。
中身はこんな感じです。アドレス:ポートは本物じゃありません。
#EXTM3U
#EXTINF:0,NHK総合
http://111.222.333.444:8888/27
#EXTINF:0,NHKEテレビ
http://111.222.333.444:8888/26
#EXTINF:0,日本テレビ
http://111.222.333.444:8888/25
#EXTINF:0,テレビ朝日
http://111.222.333.444:8888/24
#EXTINF:0,テレビ東京
http://111.222.333.444:8888/23
#EXTINF:0,TBS
http://111.222.333.444:8888/22
#EXTINF:0,フジテレビ
http://111.222.333.444:8888/21
#EXTINF:0,TOKYO MX
http://111.222.333.444:8888/20
VLCデスクトップ版は大丈夫なのです。いや違うか。プレイリストを外部から読み込む機能はないので、「ネットワークストリームを開く」でリストを開くと最初に書いてあるURLから再生が始まってしまう。それを停止するとやっとプレイリストが現れる。でも何とかOK。

VLC for iOS、VLC for Android/Fire だと、同じように最初のURLが再生されるが、プレイリストとして一覧表示してくれない。プレイリストとして読んだのではなく 'mpegurl' ファイルだとしか認識していないようだ。全然ダメだ。

よって、簡単だと思っていたことは脆くも断念することとなった。

もう一つの条件は、外からもアクセスできるようにしたかったので、HLSのURLはWANアドレスにしなければならない。WANアドレスは時々変わってしまうのでファイルをローカルに持つことが出来ないのだ。

VLC for iOSはクラウド対応になっている。これを利用しよう。
HLSサーバーの方からクラウドへHLSファイルとしてアップロードしておけばいい。
チャンネルごとのmpegurlファイルのリスト表示で良しとしよう。

VLC for Android/Fireはクラウド非対応。こっちは「ES File Explorer」を使う。
そっちからクラウドへアクセスする。で、ファイルをタップすると”どのアプリ使って再生する?”って聞いてくるので”VLC”をデフォルトアプリに設定すれば、ほぼ同じような使い心地となる。
他のファイルマネージャアプリでもいいと思う。

Google Drive使う
これは自分がよく使うところだからという理由。適当な場所に下のようなファイルを作ってあげます。
チャンネル名.ts ファイル の中身
#EXTINF:0,チャンネル名
http://111.222.333.444:8888/27
VLC for iOSからGoogle Drive上の チャンネル名.tsファイル をタップするとEXTINFOに書いてあるチャンネル名が表示されて、その下のURLからHLS再生してくれます。

拡張子の".ts"はVLCが認識する拡張子ならなんでもいいだろうけどナマのmpegtsなので".ts"が適当かなと思ってそうしました。

WANアドレス変わったらどうする?
はい。いつものようにスクリプトを書きましたとも。
Google Cloud Platformコンソールの「API Manager」から
Drive APIを有効にして、OAuth認証情報を作成して、gimite/google-drive-ruby 入れて、
以下の様なRubyスクリプトを書いて、
# coding: utf-8
#require "google/api_client" ←はずさないとgemがコンフリクトする
require "google_drive"
require 'net/http' ↓ここで自分のWANアドレス取得
result = Net::HTTP.get(URI.parse('http://自分のWANアドレス取得.appspot.com'))

URL = "http://#{result}:8888"
DIR = "MyTV"←GoogleDrive上のフォルダ
Channels = {
  "NHK総合.ts" => "#EXTINF:0,NHK総合\n#{URL}/27",
  "NHKEテレビ.ts" => "#EXTINF:0,NHKEテレビ\n#{URL}/26",
  "日本テレビ.ts" =>"#EXTINF:0,日本テレビ\n#{URL}/25",
  "テレビ朝日.ts" => "#EXTINF:0,テレビ朝日\n#{URL}/24",
  "テレビ東京.ts" => "#EXTINF:0,テレビ東京\n#{URL}/23",
  "TBS.ts" => "#EXTINF:0,TBS\n#{URL}/22",
  "フジテレビ.ts" => "#EXTINF:0,フジテレビ\n#{URL}/21",
  "TOKYO MX.ts" => "#EXTINF:0,TOKYO MX\n#{URL}/20"
}
session = GoogleDrive.saved_session("./google_drive_config.json")
dir = session.collection_by_title(DIR)
Channels.each do |key,c|
  file = dir.file_by_title(key)
  if file
    file.update_from_string(c)
  else
    file = session.upload_from_string( c, key, content_type: 'application/x-mpegurl')
    dir.add(file)
  end
end
実行する。一発目はDriveAPIの承認処理とかでゴニョゴニョあるけど。
content_type : 'application/x-mpegurl'としているけれど、mpegurlならなんでも大丈夫かも。
    # M3U8 media types
    # application/mpegurl
    # application/x-mpegurl
    # audio/mpegurl
    # audio/x-mpegurl
'text/plain'じゃだめだった。指定しないとGoogleドキュメントタイプになるようだ。
'audio/x-mpegurl'にするとGoogleDriveアイコンが変なのになる。これはこれでいいかも。

1つ難点が
綺麗に出来上がった風だが、"MyTV"フォルダ(API的にはCollect)に直接ファイルを作成したいのだが、それが出来ない。ファイルはルートに作成されてしまう。
dir.add(file)でMyTVフォルダにtsファイルを配置することはできるが、ルートから移動するのではなくルートにあるファイルオブジェクトの虚像が置かれるだけ。そのためルート上のtsファイルを削除すると一緒に消えてしまう。
最初ファイル作成した後はカッコ悪いが手動でMyTVへ移動させる必要がある。
その後はアップデート処理になるのでMyTVフォルダ内で更新される。

これを時々クーロンとかで実行するとか、WANアドレス監視をして変更された時だけ実行するとか。
簡単なことだと思って始めたら、結果こんなんなってしまった。

2016/04/05

みなやってるっぽいんで herokuでrails4 やっておこう

実はまだHerokuを使ったことがなかったなぁと思って唐突だけどやってみるかと。
そしていつものようにHeroku専用のlxcインスタンスを作るところから。

lxcインスタンス準備
$ sudo lxc-clone -n heroku master (予め作成済みのubuntu15.04のマスターインスタンス)
$ sudo lxc-start -n heroku
$ ssh heroku
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install wget git curl

アカウント作成
Heroku Sign up でサインアップして、飛んできたメールでアクティベーション。

Heroku Toolbelt インストール
https://toolbelt.heroku.com/debian の通りに

$ wget -O- https://toolbelt.heroku.com/install-ubuntu.sh | sh
で入れる。
残念なのが、これを実行するとruby2.2がシステム環境にインストールされてしまう。
使わないのに・・・

Herokuログイン
$ heroku login

アプリ作成
$ heroku apps:create my-app
my-appがHerokuでユニークじゃないとエラーになる。

コンソール起動
$ heroku run bash --app my-app
おぉ。すごい遅いけど、my-appインスタンスへちゃんと入れた。

my-appインスタンスの中をちょっと見てみる
$ ruby -v
ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]
/usr/bin/rubyは1.9.3なのか。

$ java -version
java version "1.7.0_95"
OpenJDK Runtime Environment (IcedTea 2.6.4) (7u95-2.6.4-0ubuntu0.14.04.1)
OpenJDK 64-Bit Server VM (build 24.95-b01, mixed mode)

$ python -V
Python 2.7.6

$ uname -a
Linux (ノード名) 3.13.0-79-generic #123-Ubuntu SMP Fri Feb 19 14:27:58 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Ubuntuなのね。そうでしょうとも。

$ free
             total       used       free     shared    buffers     cached
Mem:      62916388   59003396    3912992     123832    1872016    9203196
-/+ buffers/cache:   47928184   14988204
Swap:     63963132    2880184   61082948
ほうほう。

$ whoami
u52987
アプリ名とかじゃないのか。

ホスト名=インスタンスノード名だった。emacs入ってなかった。
当然sudoないし、pingないし、
あまり面白くなかったので退散!


rvm ruby rails4環境

$ curl -sSL https://rvm.io/mpapis.asc | gpg --import -
$ curl -sSL https://get.rvm.io | bash -s stable
$ source .rvm/scripts/rvm
$ rvm install 2.2.4 --default
$ gem install rails --no-ri --no-rdoc

Herokuはpostgresql(Sqliteは使えない)なのと、rails4のpg gemはNativeビルドなので
$ sudo apt-get install postgresql-server-dev-9.4
で入れておく

後は Getting Started with Rails 4.x on Heroku に書いてあるとおりに

$ rails new myapp --database=postgresql
成功したら
$ cd myqpp
Gemfileの'therubyracer'のコメント外して
$ bundle
$ rails g controller welcome

conf/routes.rb のroot設定を有効に
app/views/welcome/index.html.erb ファイル作成

Heroku gems
gem 'rails_12factor', group: :production
ruby "2.2.4"
をGemfileの一番下に加える

ローカルで動作確認
$ rails s -b 0.0.0.0

gitリポジトリ作成
$ git init
$ git add .
$ git commit -m "the myapp first commit"

Herokuアプリ作成

$ heroku create (名前はお任せで)
この時点でgitリモートにherokuがいる

deploy
$ git push heroku master

ほぉ。git pushでデプロイってことになるのかぁ。

指定されたURLへアクセス・・エラーだ・・ ログ確認
$ heroku logs
index.html.erbが適当すぎた。

ついでに、ここでもWANアドレスを表示するアプリにしてみる

app/controllers/application_controller.rb に以下のbefore_actionコールバックを追加
  before_action do
    $request = request
  end

app/views/welcome/index.html.erbで以下のように表示
<%= $request.remote_ip %>

更新
$ git commit -a -m "request.remote_idを表示"
$ git push heroku master

URL確認。後はこれの繰り返しですかね。

puma使うようにしてみる
チュートリアルでデフォルトはwebrickが動いてるがproductionではpumaがオススメだと。
Procfileを作成して
web: bundle exec puma -t 5:5 -p ${PORT:-3000} -e ${RACK_ENV:-development}
って書くと。

ローカルテストするんだったら.envファイルを作ってPORTとRACK_ENVを定義しておくとか
チューニングとかはconfig/puma.rb作って、なんとかかんとか。
この辺は、ちょっとパスしましたが、ドキュメントは親切丁寧ですね。

railsコンソール
$ heroku run rails console
rake実行
$ heroku run rake db:migrate

bundle execの代わりにheroku runって感じですか。

$ heroku run bash で再びコンソールへ

$ ruby -v
ほお。Gemfileで指定した2.2.4だ。どこ?
$ which ruby
/app/bin/ruby -> ../vendor/ruby-2.2.4/bin/ruby
アプリのローカル環境に入ってるんですね。

デプロイしたアプリが入ってます。ここが起動パスなのは間違いないと思うけど
ログファイルは空っぽ。どこか別のところで管理されているのだろうね。


$ cd myapp したら以下のメッセージが現れた!cdする度に表示される
RVM used your Gemfile for selecting Ruby, it is all fine - Heroku does that too,
you can ignore these warnings with 'rvm rvmrc warning ignore /home/ubuntu/heroku/myapp/Gemfile'.
To ignore the warning for all files run 'rvm rvmrc warning ignore allGemfiles'.
「RVM使ってるんだね。Herokuもだよ。このメッセージ消したければこうしなさい」ッて感じ?
やりますとも。
$ rvm rvmrc warning ignore allGemfiles
はい。消えました。

SSH Gitでデプロイするためには

Deploying with Git に詳しく書いてあるわけですが、ざっくりやってみると

SSH Key作って登録
$ ssh-keygen
$ heroku keys:add
keygenしたファイルをuploadするか?って聞いてくる。入れる。
$ heroku keys (アップされたか?)

接続チェック
$ ssh -v git@heroku.com
debug1: Offering RSA public key: /home/ubuntu/.ssh/id_rsa
debug1: Server accepts key: pkalg ssh-rsa blen 279
debug1: Authentication succeeded (publickey).
OKなようだ。

$ heroku create --ssh-git
'-ssh-git'を付けると、git remoteが、https://じゃなくて、git@heroku.com:になる。
SSHキー登録が住んでいれば、gitアカウントのSSHでデプロイされる。

--ssh-gitを付けるのめんどくさいって時は
$ git config --global url.ssh://git@heroku.com/.insteadOf https://git.heroku.com/
をやっておけば、デフォルトがSSHになるそうな。

既存アプリのgitリモートにherokuを追加するには
$ heroku git:remote -a (アプリ名) --ssh-git
--ssh-git付けなければ、https://になる。これは何度もやり直せる。



何だかんだやらずにrailsアプリ即デプロイしたらどうなるか試してみたら

remote: ###### WARNING:
remote:        Include 'rails_12factor' gem to enable all platform features
remote:        See https://devcenter.heroku.com/articles/rails-integration-gems for more information.
remote:
remote: ###### WARNING:
remote:        You have not declared a Ruby version in your Gemfile.
remote:        To set your Ruby version add this line to your Gemfile:
remote:        ruby '2.2.4'
remote:        # See https://devcenter.heroku.com/articles/ruby-versions for more information.
remote:
remote: ###### WARNING:
remote:        No Procfile detected, using the default web server.
remote:        We recommend explicitly declaring how to boot your server process via a Procfile.
remote:        https://devcenter.heroku.com/articles/ruby-default-web-server
と、ワーニングは増えたけど普通に動きましたね。




最後に

前記事でGoogle Cound PlatformのApp Engineで簡単アプリ作成を書いた。
で、Ruby環境について読んでいたらApp EngineのRuby=Railsのことらしい。
なんだ、AppEngineでRails動くんじゃないか。
無料枠で使用できるなら、今度やってみようと思ったが、残念有料枠でした。
60日間無料お試しで遊ぶ程度しかできないようだ。


2016/04/01

AppEngineで簡単WANアドレス取得アプリ作成

昔 Google App EngineでWANアドレス管理サーバー なんて記事を書いたが、今回は最も簡単な方法で作ってみる。管理いらずの方法で目的は果たせる。

前回、Google Cloud Platformでプロジェクト作成してGitホスティングする記事を書いたが、そこまでは同じ。

プロジェクトのダッシュボードへ行く。
(AppEngineのダッシュボードはアプリ稼働させてから行くところ)

「Try App Engine」をクリックして、"Hellow World"アプリ作成とデプロイまでのチュートリアルをスタートさせる。

どの言語を使用するかだが、Java、Python、PHP、Go の4つが無料枠で使用できる。
そのうちのお好みの言語で。
ブラウザはChromeがいいかも。Firefoxでやったらコピペしたい文字列が空欄になった・・

ここでは最も簡単なPHPとGoでやってみる(だけど自分でコードは一切書かない)

「PHPのチュートリアルを開始する」で開始すると右側にチュートリアルが出てくる
「次へ」
「プロジェクトを作成する」 前記事の要領で
「次へ」
左上のサービスメニューから”開発”を選択 (言う通りにしないとチュートリアルが進まない)
「次へ」
ソースコードリストから"app.yaml"ファイルをクリックしてオープンする
”/”をクリックしてリストへ戻る (という手順のチュートリアルなのだ)
「次へ」
Google Cloud Shellを起動 (ナビバーの「>.」アイコン)
"show me how"というリンクをクリックすればどこをクリックすればいいのか教えてくれる。
初めての起動だと、インスタンスの構築に若干時間がかかる。2016年末まで無料だそうな。

Shellで
$ cd src/(project ID)/gcloud でクローン済みのリポジトリへ移動
チュートリアルに表示されている文字列をShellへコピペ実行でもOK
「次へ」
$ gcloud preview app deploy でデプロイする
チュートリアルに表示されている文字列をShellへコピペ実行でもOK
「次へ」もしくはチュートリアルキャンセル
チュートリアルはAppEngineのダッシュボードでステータス表示と続くが、この辺でキャンセルしてもいい。

WANアドレス表示アプリに改造

”開発”ダッシュボードからhelloworld.phpをクリック
「編集」で編集モードに
'Hello, world!' を $_SERVER['REMOTE_ADDR'] に書き換え
commit」でコミットする
Google Cloud Shellで
$ git pull する
$ gcloud preview app deploy でデプロイする

Goでも流れは同じだけど、Shellで編集する流れにすると
$ emacs hello/hello.go (なんとCloud ShellでEmacsが最初から使えるよ!)
handlerメソッドの fmt.Fprint(w, "Hello, world!") を fmt.Fprint(w, r.RemoteAddr) に変更
キーバインドが違うんでカーソル移動が厳しいか・・・
$ gcloud preview app deploy (デプロイ)
一応commit&pushも
$ git config --global user.email "my_name@gmail.com" (セットしてなければ)
$ git config --global user.name "my name" (セットしてなければ)
$ git commit -a -m "メッセージ"でコミット
$ git push origin
プレビュー確認
$ goapp serve  (Goのチュートリアルやると分かるがCloudShellからテストサーバー起動出来る)
Shellウインドウ左端の「ウェブでプレビュー」アイコンクリックすると表示される

https://(プロジェクト ID).appspot.com へアクセスするとWANアドレスが表示される

チュートリアルでGoogle Cloud Shellを使う流れになっているけど、2017年になったらどういうチュートリアルになるんだろ?素朴な疑問

javaの場合は
$ mvn gcloud:run テストサーバー起動
$ mvn gcloud:deploy デプロイ
忘れそうなので書き残しておく

gcloudブランチ
チュートリアルから作成したリポジトリは、masterではなくgcloudブランチを使う流れになっている。
masterとgcloudブランチの違いは、app.yamlファイル。
masterにはapplication: ~と version: ~の記述が冒頭にあるけど、gcloudブランチには無い。

試しにmasterブランチをgcloudデプロイしてみたら、applicationとversion記述はもう要らぬ!と怒られてデプロイできなかった。


ログからWANアドレスを知る

自宅以外の場所から自宅の現在のWANアドレスを知ために、以前は今回のようなアプリに更にアドレスをアプリで保存管理出来るようにしたり、変更された際にはメール通知するとか色々めんどくさいことをしていた。

今回は最も簡単(いい加減?)な方法で確実に知ることが出来る方法だ。

「ツールとサービス」メニューから”Stackdriverのログ"から、GETリクエストログの1つを開けてみれば、その先頭にWANアドレスが書かれている。

Stackdriverサービスのログリスト観覧だけなら、これも無料枠で大丈夫。

cron/crontabで定期的にwgetでアクセスさせておく。認証もしないシンプルアクセス

我が家のサーバーへアクセスしたくなった時、このログを出先で確認すればいいのです。
もう認証やらメール通知やら、小難しいことしないでも十分実用になっております。

懸念点としては、攻撃にあって通信量で無料枠オーバーとか不特定多数のログが多すぎて
自分のアクセスが見つからない・・・とか?
今のところその心配は皆無です。自分以外のアクセスは0です。

ログを見れば分かるからAppEngineアプリもHelloWorldのままでいいじゃんとも思うが、
外でも仕事で今のWANアドレス(GWはどれ通ってる?)知りたい時に手軽に利用できるんで
表示させるだけでも便利なのです。

2016/03/31

GoogleCloudPlatformでプライベートGitホスティング

昔の記事 Google Driveとgriveとgitリポジトリ  ではGitのプライベートリポジトリを無料で使えるところないかなぁ?とか思ったりしていたが、Google Cloud PlatformでプライベートGitホスティングが無料で使用できることに最近気づいた。ストレージ容量や通信量など制限はいくつかあるけれど個人レベルで使用するには十分。

Google Cloud Platform から見ていくと分かりにくいが、プロジェクト作成・Gitホスティング・AppEngineアプリサイト作成は無料枠内で利用できる。

その辺の流れをまとめてみた。

ChromeとかでConsoleへ自分のGoogleアカウントでログインする。
最初に、とにかくプロジェクトを作成する。

作成する際に若干注意する点としては、GitリポジトリURLやAppEngineのURLは、プロジェクト名ではなく、その下に小さく表示されている Project ID 名になる。ここをできるかぎり希望の名前になるように頑張る。

青いメニューバー左端の三本線アイコンメニューから下の方の”開発”を選ぶ。
ここがGitリポジトリのダッシュボード。

自分のローカル環境にGoogle Cloud SDKをインストール
Linux、Debian/Ubuntu、Mac、Windows版があるが、自分がこの手のことにいつも使っているのはUbuntuなので、Ubuntuで進める。

Devian/Ubuntuタブを選択するとインストールと初期設定までのスクリプトが表示されているので
これをそのまま実行すれば良い。

ただ、実行に必要なツールとして、curl python gitが必要なので予め入れておく。

$ gcloud init で初期設定 が行われる。これはCUIな対話式になっている。
:Googleアカウントへログイン
:自分のプロジェクトの選択
:Googleソースホスティングを使用するか?(当然Yes!)
:Gitリポジトリをクローンする?(defaultの1を選ぶ)
:ディレクトリ名はどうする?(defaultのままで良ければEnter)
これでdefault(もしくは指定したディレクトリ)へGitリポジトリが作成される。

$ git remote -v で確認すると
origin  https://source.developers.google.com/p/(プロジェクトID)/r/default (fetch)
origin  https://source.developers.google.com/p/(プロジェクトID)/r/default (push)
となっている。あとは git で普通にpush、pullすればよい。

既存Gitリポジトリにremote addするには、空のソースコードページに書いてあるとおり
$ gcloud init (やってなければ)
$ git config credential.helper gcloud.sh
$ git remote add google https://source.developers.google.com/p/(Project ID)/r/default
で追加できる。

無料枠内の利用であればどんな用途でもいいと思う。

2016/03/17

USBカメラをlxcインスタンスから使ってみる

最初 普通にカメラモジュールを買って遊んでみようと思ったが、調べているうちにチューブカメラ(スネークカメラ)の方が遊びがいがありそうだったので、買ってみた。

チューブカメラ(スネークカメラ)
kamura 7mm 6LED カメラ USB接続エンドスコープ(内視鏡) 防水 内視鏡スコープ
1300円は安いんじゃないかな。自分は2mを買ったけど何故か5mの方が100円安い設定・・・
レビューも詳しい商品説明もなかったけど、2~3千円台のやつと大差ないだろうとエイヤ!購入。

チューブカメラをUbuntuサーバーに付けて

認識してるかな?

$ lsusb
Bus 001 Device 006: ID 1908:2311 GEMBIRD

$ dmesg |grep CAMERA
[    2.535026] usb 1-1: Product: USB2.0 PC CAMERA
[   10.129511] uvcvideo: Found UVC 1.00 device USB2.0 PC CAMERA (1908:2311)
[   10.131662] input: USB2.0 PC CAMERA as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/input/input5
[ 8834.645489] usb 1-1: Product: USB2.0 PC CAMERA
[ 8834.646070] uvcvideo: Found UVC 1.00 device USB2.0 PC CAMERA (1908:2311)
[ 8834.646467] input: USB2.0 PC CAMERA as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/input/input11

$ ls -l /dev/video*
crw-rw---- 1 root video 81, 0  ~~~~ /dev/video0

どんなデバイスかな?

$ sudo apt-get install v4l-utils
video4linux2 utilitiesを入れて

$ v4l2-ctl -d /dev/video0 --info
Driver Info (not using libv4l2):
        Driver name   : uvcvideo
        Card type     : USB2.0 PC CAMERA
        Bus info      : usb-0000:00:14.0-1
        Driver version: 4.2.8
        Capabilities  : 0x84200001
                Video Capture
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps   : 0x04200001
                Video Capture
                Streaming
                Extended Pix Format

最大640x480 30fpsの標準的なUVC Camera。USBコネクタ側に先端のLED調光ダイヤルが付いていて4段階くらいの制御が出来ている。


lxcインスタンス側から使えるようにする

/var/lib/lxc/(instance)/config に
”lxc.cgroup.devices.allow = c 81:* rwm”

lxc.hook.autodevスクリプトに
”mknod -m 660 ${LXC_ROOTFS_MOUNT}/dev/video0 c 81 0”
"chgrp video ${LXC_ROOTFS_MOUNT}/dev/video0"

を加え、lxcインスタンスを起動。これでホストと同等にアクセスできるようになった。
後々めんどくさいので
”mknod -m 666 ${LXC_ROOTFS_MOUNT}/dev/video0 c 81 0”
だけにして、誰でもOKに。

キャプチャツールでテスト

Ubuntu Webcam で紹介されているものを幾つか試してみる

streamer
$ sudo apt-get install streamer
$ streamer -o test.jpeg -s 640x480

シンプルでコンパクトなコマンドツール。自分はこれで満足です。

cheese
$ sudo apt-get install cheese
$ cheese
** Message: cheese-application.vala:211: Error during camera setup: No device found

ほえ?自動的にデバイスを認識するって話ですが? "-d /dev/video0" してもだめでした。
lxcインスタンスからとか、tightvnc上での起動とかが絡んでるかもしれないけど、もういいっす。

VLC
$ sudo apt-get install vlc
$ vlc

難なくtightvnc上にGUI出てきました。/dev/video0を選んで 再生も問題なし。
$ vlc v4l2:///dev/video0 とすればすぐさま再生。

ただ、起動するとエラーではないけれど

pulse audio output error: PulseAudio server connection failure
Qt: XKEYBOARD extension not present on the X server.
Failed to open VDPAU backend libvdpau_nvidia.so

のメッセージが出るのが気になる。

$ cvlc v4l2:///dev/video0

でコマンドツールで起動するとXKEYBOARDのメッセージだけは消せる。
けど他は消せないなぁ。

iPadやAndroidとかではどうかな?
iPadにCamera Connector Kit経由で繋いでみたら消費電力が高すぎるから使えないと言われた。それじゃあと、外部電源付きのUSBハブをさらに経由したら、サポートしていないカメラだと言われた。。。
 AmazonFireHDXに繋いでみたが認識しなかった。外部USBカメラアプリをいくつか試してみたが、やっぱり認識しないようだ。USB変換ケーブルが原因の可能性もあるかな。今の所残念な状態。


2016/03/15

8x8LEDと超音波センサーとArduinoで遊ぶ

久々の投稿となります。昨年末に突然左目が斜視になってしまい、歩くのもおぼつかない自体となってしまいました。幸いにも現在はほぼ回復し、普通の日常が戻ってまいりました。

ということで、年末に書き残そうと思っていたことなど・・・


RaspberryPi2も楽しいけれど、もっとローコスト環境で遊んてみたくなって、ArduinoUNOとArduinoNanoを購入し、なにかまとまったものを作ってみようと思って作ったのが上の写真。

(見えないけど)電池パックの上にユニバーサル基板を載せて、8x8LEDモジュールと超音波距離センサーとArduinoUNOを載せて適当に繋いで、Sketchでプログラムして動かしています。
障害物との距離に応じてLEDに表示するものを変化させるというだけの単純なシステムです。

クリスマスには”Merry Xmas”と”サンタとトナカイ”と”Xmasツリー”の3パターンアニメーションをやったりして、子供が以外なくらい結構遊んでくれました。(目がおかしくなったのはその直後くらい)
正月には”A Happy New Year 2016”などで使いました。

今回技術的なことは殆ど無いんですが、あえて上げれば・・・

Nanoじゃ辛い
最初 ArduinoNano を基盤にさしてコンパクトに作ろうと思ったのですが、Nanoの5V端子から5Vが出ないのです。LEDとセンサーが5Vを要求しまして、Nanoでは駆動できませんでした。
別電源供給も考えましたが、UNOなら大丈夫だったので、UNOを無理やり載せた形になりました。

8x8LEDノイズが超音波センサーを狂わせる
LEDからのノイズがセンサーを誤動作させてしまうのです。自分の耳にも聞こえるくらい厳しい高周波を出します。コンパクトに収めて子供に遊ばせることが重要だったのでFFCで分離したくなかったし。
結局、LEDの発光レベルを1段下げるとギリギリですがセンサーが生きる状態になりました。
物理的なモードスイッチとかも付けて、アニメーションをセンサー連動と手動切替が出来るようにしたり、アセンブリ段階で意外と苦労しました。

3軸モーションセンサーも買ったけど
無理やり繋いでデータは取れるようになったけれど、簡単に応用できるポイントがなかったので外しました。

ArduinoIDE環境
特に難しいことはないんですが、Macに繋いでやりたかったけれど一発では認識せず。USBドライバがどうとかこうとかで認識させるまで面倒そうだったので、ShuttleサーバーマシンにArduino開発専用インスタンスを'lxc'で作って、そこにIDEを入れてVNCサーバー通して動かす方法を取りました。この方が断然安定していて不安なく作業ができます。


今度は原点に戻って、RaspberryPiとカメラモジュールで色々やってみたいと思っています。