node.js を Capistrano3 でデプロイ時に pm2 をいい感じに再起動したい

pm2を再起動したい

node.js を Capistrano3 でデプロイする時に pm2 を restart したいです。

単純にこれでもまぁいいのですが、

execute :pm2, 'restart', fetch(:app_name)

予めpm2で目的のアプリケーションが起動していない場合にコケます。プロビジョニング直後とか。
なので deploy.rb で pm2 のステータスによって、restart するか startするか処理をわけたいのです。

pm2の状態を取る

pm2のステータスを取る、というのでググるとよく出てくるのはこれ。
(何かのコピペが広がったんでしょうか。決まってjlistのオプションにアプリケーション名らしきものを渡してますが意味無いんじゃ)

ps = JSON.parse(capture :pm2, :jlist, fetch(: app_command))
if ps.empty?
  return nil
else
  do something
end

これだと、デプロイ先のサーバでpm2で起動しているアプリケーションが1つの場合は兎も角、複数ある場合には意図しない結果になります。

起動 or 再起動

こんな感じで乗り切りました。
もっとエレガントな方法があれば知りたいです。

ps = JSON.parse(capture :pm2, :jlist)

is_exist = false
ps.each do |row|
  is_exist = true if row["name"] == fetch(:app_name)
end

if !is_exist
  execute 'NODE_ENV=#{stage}', :pm2, 'start', "#{current_path}/app.js", '--name', fetch(:app_name)
else
  execute :pm2, 'stop', fetch(:app_name)
  execute :pm2, 'delete', fetch(:app_name)
  execute 'NODE_ENV=#{stage}', :pm2, 'start', "#{current_path}/app.js", '--name', fetch(:app_name)
end

結論

未だに ruby 慣れない

Mac で Chrome を別プロフィールで多重起動

Web系の開発とかしてて、複数ユーザでログインしたりしたいとき、Chromeならば通常のウィンドウとシークレットウィンドウの2ついけるけど、例えば10ユーザ位を使い分けたい時に。

要はこういうのをMacのChromeでやりたい時。
Chrome と Firefox の別プロフィールやIDでの多重起動方法 – PC活用術

Terminal を開いてこんな風にすればいいです。


/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir=~/tmp/001

サーバサイドSwift

ちょくちょくサーバサイドSwiftの話を聞くのですがいまいち覚えきれないのでメモ。結構沢山あるんですね。

Perfect
9915 Star
名前が凄いし、Star数もそれを裏付けている。老舗かつ本命。

Kitura
5018 Star
対抗。天下のIBMがまさかのNode.js/Swift推しでOracle(Java)を牽制。

vapor
7815 Star
活発にメンテされている印象で気になります。

Swifter
1854 Star
地味だがメンテはされているっぽい。

Taylor
893 Star
残念ながら開発が止まっているっぽい。

Slimane
68 Star
日本製。頑張ってほしいです。

Swift もバージョン3.0になり少しずつ開発者人口を増やしている感あります。サーバサイドもSwiftでやっちゃえ的なノリ嫌いじゃないです。

久しぶりに Titanium の Android のアプリやモジュールをビルドしたらハマったこと

Titanium もいつのまにか 6.0.0 の RC が出て、V8がアップデートされたから 全Androidのモジュールビルドしなおしな!という事だと聞いて。

そう言えばSDKが4になった頃からノーメンテだったのを思い出したので、本当に久しぶりにビルドしてみたところ色々あったのでメモを残しておきます。
あとソラで打ててたCLIを色々忘れていて驚きました。

環境

OS: MacOS 10.12.1
Node.js: 6.9.1
npm: 3.10.8
Titanium CLI Version: 5.5.1

アプリのビルド時にinvalid session

appc ti build -p android とかすると、こんなん出る。

[ERROR] invalid session

なんとなく手癖で


appc logout
appc login

したら治りました。

Path must be a string. Received undefined

node.js が新し杉。
Node.jsが6.x系でAndroidをビルドしようとすると出るらしい。

node.jsを4系にダウンロードして解決。
sudo n 4.6.1

モジュールが使えない msg:java.lang.UnsatisfiedLinkError

[ERROR] linker: /data/app/myapp/lib/arm/libcom.mymodule.so: has text relocations
[ERROR] TiApplication: (KrollRuntimeThread) [28,79] Sending event: exception on thread: KrollRuntimeThread msg:java.lang.UnsatisfiedLinkError: dlopen failed: /data/app/myapp/lib/arm/libcom.mymodule.so: has text relocations; Titanium 5.5.1,2016/09/27 05:39,b18727f

なんだか良くわからないけど、しばらくモジュールをbuildしてなかったからなぁ。
と言う訳で、Android用のmoduleを、まずは現行の SDK 5.5.1.GAでビルドしなおす事に。

Androidモジュールのビルドってどうやるんだっけ?

ant ですよ!
android というか Java さわらなさ過ぎ問題。

当たり前すぎてREADMEとかに書いてないけど忘れる時は忘れる。
あんなに毎日アントアントメイブンメイブンだった日々はもうはるか昔。

モジュールのビルド時のエラー

こんなん出ました。


% ant
Buildfile: /Users/me/module/MyModule/android/build.xml

BUILD FAILED
/Users/me/module/MyModule/android/build.xml:37: Cannot find /Users/me/Library/Application Support/Titanium/mobilesdk/osx/4.0.0.GA/module/android/build.xml imported from /Users/me/module/MyModule/android/build.xml

build.propertiesに指定されているSDKが入ってなかった。

appc ti sdk select して、存在するSDKを確認の上、build.propertiesのtitanium.platformのPATHを変更する。

SDK 6.0.0対応は?

SDK 6.0.0がGAになったら、後日またビルドします。

socket.io 1.4系で 4undefined (追記あり)

socket.ioを最新 (1.4系)にアップデートすると、emitの動きがおかしいというか、Clientで受け取れない事がありました。

こういうのは大丈夫だけど、


io.on("connection", function(socket) {
socket.emit("OK");

roomのsubscriberにbroadcastしようとすると、client側で受け取れない。


io.on("connection", function(socket) {
// socket.toでも同様
socket.in('myroom').emit('message', 'hello world');

正確に言うと受け取れないんじゃなくて、受け取ったデータがおかしい。
ChromeでWSをキャプチャすると、client側にとこういうのは届いている。


4undefined

ワークアラウンドとしては、socket.io を 1.3系にダウングレードすること。

io.emit causes 4undefined frame – Issue #2590 – socketio/socket.io – GitHub

昨今はsocket.io の 1.3系のビルドに手こずるから凄い嫌なんだけど、該当コードを全て修正する事も現実的で無い場合は仕方が無い感じ。

2016-10-18追記
socket.io 1.5.0で治りました。良かった。

https://github.com/socketio/socket.io/issues/2590

XCode 7 で EXC_BAD_ACCESS のデバッグ (Zombie Objects)

 

相変わらず EXC_BAD_ACCESS で慌てる自分がいます。

EXC_BAD_ACCESS ググっても日本語で書いているものはかなり古い記事が多いので、誰かのために書いておきます。
環境はXCode 7.2.1 です。

NSZombieEnabled

まずはゾンビオブジェクト(解放されたオブジェクト)へのアクセス時に止まる様にしてみます。

[Edit Schema] – [Diagnostics] で [Enable Zombie Objects] にチェックします。

以前は、Arguments に NSZombieEnabledを追加、なんてしてた気がしますが、XCode 7の今はこうするみたいです。

おおよその場所が特定できたらブレークポイントを貼って色々見てみますが、今回の私のケースではそれでは全く原因が判りませんでした。

ARC以前のObjective-Cと比べるとSwiftになってから格段に楽になったというか、オプショナル型を正しく活用すればあまりクラッシュに遭遇する事は無くなりました。
ただライブラリの作りの都合上で暗黙的アンラップ型(Implicitly Unwrapped Optional)を使わざるを得ないケースも多々あり、今回そのへんが原因かなと思って一生懸命調べてたけど全然外してました。

デバッグは思い込みダメ。絶対。

shell malloc_history

昔はデバッガに shell malloc_history ってやってた気がしますが、今はこんなんが出るだけです。

error: ‘shell’ is not a valid command.
error: Unrecognized command ‘shell’.

どうやらInstrumentsでやれって事みたいです。

Instruments で Zombies を調べる

XCode 7 で [Product] – [Profile] をクリックします (または⌘+i)

[Choose a profiling template for] で [Zombies] を選択し、[Choose]をクリックします

2016-02-11 22.59

赤丸(Record)ボタンをクリックします
2016-02-11 23.02

実機やシミュレータを操作してEXC_BAD_ACCESSを再現させます

再現したら出る[Zombie Messaged] の矢印的なボタンをクリックします

2016-02-11 23.05

EventType が Zombie、 RefCt が-1のクラスとメソッドが特定出来ました

2016-02-11 23.06

あとはこっから類推して実際のコードであたりをつけてデバッグします。

因みに今日の自分の場合、色々試している中でAVCaptureDeviceにaddObserverしたりしたのを中途半端に消し忘れてたのが原因でした。半日無駄にしました。

[Swift2] Facebook Popを使ったアニメーション

 
前回やってみたアニメーションとは別のアプローチで。
facebookが提供しているアニメーションライブラリPopを使ってみます。

https://github.com/facebook/pop

Titaniumでいうと何でしょう。ちょっと違うけど Alloy.builtins.animation みたいな?

インストール

CocoaPods 使いした。楽だし。というかSwift触りだしてからは手動でやったことない。

Podfileを書いて、

platform :ios, ‘8.0’
use_frameworks!

target ‘myswiftproject’ do
pod ‘pop’, :git => ‘https://github.com/facebook/pop.git’
end

Swift2だしバージョンはなんとなく最新をgitリポジトリより取得にしました。

あとはターミナルで

pod install

します。

ソースコード

使いやすそうです。
他にも色々なアニメーションパターンが用意されています。

Windows 10 のライセンス認証 エラーコード 0xC004f050 の対応

 
いつか誰かのためにメモ残します。
めっちゃ時間かかったけど辛抱強く付き合って頂いた電話サポートの中の人ありがとう。
自分の環境はMacのBootcampだけど、多分素のWindows機でも同様と思います。

環境

Macbook Pro (El capitan) + Bootcamp + Windows 10 Home (Windows 8 Pro からのアップグレード)

起こったこと

  1. Macbook その1で bootcamp で Windows 8 Pro 64bit DSPインストール、8.1にアップデート
  2. Windows 10 Home へアップグレード
  3. Macbook その1 で WinClone Basic を使ってBoobcamp領域をバックアップ
  4. Macbook その2 で WinClone Bacic を使ってBoobcamp領域をリストア
  5. Macbook その2 の Windows10 Home で、「ライセンス認証されていません」的な エラーコード[0xC004f050]が表示される (文言をメモするの忘れた・・・)

この時点で、winverを実行したときの表示は、バージョン 10.0

対応その1 Windows Update

まずはOSのバージョンが古いとの事だったので、Windows Updateを実行。
途中まで出来たけど、再起動後、「更新できませんでした」的なダイアログが出て失敗。
winverを実行したときの表示は、バージョン 10.0のまま

上書きインストール

  1. Edgeを起動し、アドレスバーに [aka.ms/win10jp]と入力
  2. 表示されたページの[ツールを今すぐダウンロード]をクリック
  3. ダウンロードしたツール(MediaCreationTool.exe)を実行
  4. 色々指示に従う。途中Windows10のダウンロードが有る。40分位かかった
  5. 再起動後インストールが開始されるので色々待つ(1時間位かかった)

再起動後、winverの表示は、バージョン 1511

ここで、[設定] – [更新とセキュリティ] – [ライセンス認証] を開くと以下の表記。

「Windows はライセンス認証されていません。このデバイスにインストールされている以前のバージョンの Windows が、Windows 10 にアップグレードする前にライセンス認証されていなかったためです。エラーコード 0x803F7001

ここまでくれば大丈夫。
[プロダクトキーを変更します]をクリックし、Windows 8のプロダクトキーを入力すると、無事 [Windows はライセンス認証されています] になりました。

Mac間でのBootcamp領域の引っ越し、かつWindows 10はアップグレードしてのインストールの場合は要注意かも。

全然関係ないけどaka.msってMS用のアカマイの事だろうか。

このままだとC:\Windows.old、C:\Windows.~BT等のフォルダが残ったままで貴重なSSDの容量を無駄に消費するので、[ディスクのクリーンアップ] – [システムファイルのクリーンアップ] を忘れずに。

C:\ESDは手動で削除しました。

結果的に、アップグレードで肥大してたCドライブ(データ含め49GB)が、39.4GBになり、デバイス関連のレジストリも綺麗になったっぽいので、かえってよかったのかもしれない。

[Swift2] 背面カメラのトーチをオン

 
暗い所でもカメラ撮影したいんです。

ソースコード

なんかだいたい判ってきたんですが、Swift2になってエラーと取り回しが1系から変わっているんですね。
swiftのtry〜catchの作法がまだ良く判らないんだけどこれで良かったのかしら。

[Swift2] UIView(ボタン)をフェードイン

 
アニメーションやってみたくなったので、全く必要性は無いけどボタンをフェードインしてみます。

欲しいのはTitaniumでいうと Ti.UI.Animation 的なやつです。

Objective-Cでちょろっと書いた事あるやる方で、コードアシストだけでほぼ書けました。
未だに文法の理解がフワッとしていて、コールバックの書き方が良く判ってないです。

他にも色んなやり方があるんだと思いますが一応動きました。

ソースコード

動いたやつ