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

もぐてっく

人は1つ歳を取る度、1ビットづつ大きくなれると信じてた。

Yet Another 実行中のmikutterにコードを流し込むやつを作ったよ

mikutter

何これ?

明けましておめでとうございます。

これは「あー正月ってテレビもつまんないしマジすることないよねー」カレンダー (なにそれ?)1日目の記事です。(1年ぶり2記事目)


今回は「起動中のmikutterに外部から任意のコードを流し込むプラグイン&コマンド」を作ったのでその紹介をば。

これ、コンセプトは@toshi_aさんのmikutter-modeと同じで、プラグインを改造するたびにmikutterをいちいち再起動したくないよねと言うところです。

じゃあなんで再発明してんだよ溜まってるIssue処理しろよ最近お前の腹の出方ヤバイだろ痩せろよ?のかと言うと、

もぐのがMacDBusを動かせなかった

mikutter-modeがプロセス間通信に使っているLinux御用達フレームワークDBusが、もぐののMacではなんかエラーになるんですよね。
なので、今回は古のRuby標準ライブラリであるdrubyでプロセス間通信を実現しました。

もぐのがvim

mikutter-modeはEmacsLISPで実装されてる所がいっぱいあって、vimで使うにあたってよくわかんなかったので。
せっかくなので、エディタに依存しない仕組みにすることにしました。

(ちなみにmikutter-modeのvim移植は2GMonさんによる実装があったりします。)
github.com

インストール

GitHubからzipファイルをダウンロードして、プラグインディレクトリにmikutter-code-injectorと言うディレクトリ名で展開して下さい。

moguno/mikutter-code-injector · GitHub

※mikutterプラグインマネージャ"Packaged"で"moguno"を検索してインストールするのもおすすめです。

使い方

普通にmikutterを起動する。

ごく普通にmikutterを起動してください。

見た目には変化はありませんが、netstat -aするとこんな行が増えてたりします。

tcp6       0      0  localhost.39311        *.*                    LISTEN

コードを送り込む

~/.mikutter/plugin/mikutter-code-injector/にmktrと言うコマンドがあります。
そのmktrの標準入力にRubyコードを流し込んでみてください。
起動中のmikutterでコードが実行されます。

実行できるコードに制限はなく、mikutterのフル機能を操作できます。

仕組み的にはmikutterのトップレベルbindingをdrubyで公開しておいて、mktr側でそれを取得。
んで、取得したbindingのevalを呼ぶとmikutter側でコードが実行されると言う寸法です。

それでは試しに、コマンドラインからつぶやいてみましょう。

echo 'Service.primary.post(:message => "みくっ")' | ./mktr

f:id:moguno:20151121103409p:plain

ちゃんとつぶやけましたね。
速攻で複数人からふぁぼられてるのは弊TLの仕様です。

vimから使ってみる。

もぐのはvimスクリプトが書けない人なので、mikutter-modeの様なvimとの統合機能は作り込んでません。
て言うか、vimではこんな風に現在のバッファをmktrの標準入力に流し込むことが出来るので、これでいっかーな感じになってます。

:w !./mktr

これで本格的なプラグイン開発にも対応できますね。

f:id:moguno:20151121111310p:plain

現状の制限として、mikutter起動時のイベントon_bootはコード流し込み時には実行されません。
この辺はなにか工夫できたらいいなと思ってます。

IPアドレス固定なしで家庭内サーバを公開できるデーモンを作ったよ

何これ

自宅サーバを公開したい!
→ルータのポートマッピングを設定しないといけない!
→サーバのIPアドレスを固定しないといけない!
→IPアドレスの管理めんどい!DHCPのまま公開したい!

と言う、おおよそサーバ管理者に向かないものぐさ思考をUPnPを使って解決することにしました。

UPnPとは、ネットワーク内でのサービス提供者の発見、サービス内容の公開、リモートプロシージャコールを行う仕組みです。10年以上前からあるふっるい技術ですね。

当時はWebサービスマッシュアップ技術の本命だったのですが、結局、サービス探索なんてあんま使わないじゃん。RPCはシンプルなRESTでいいじゃん。となって流行る前に忘れられた感があります。

そんなわけで、UPnPを使ってて広く実用化されているのはルータのポート開放とDLNA位と言うのが現状です。

UPnPでのポート開放は通常はメッセンジャーなどのアプリケーションが自分用のポートを開けるために使用しますが、今回、これを使って任意のポートを制御するデーモンを作ってみました。

こだわったところ

mDNSとの親和性

mDNS(avahi、bonjour)を使えば、ローカルなDNSサーバがなくとも「ホスト名.local」と言う名前で端末にアクセスできるようになります。これを使えばDHCPでころころIPアドレスが変わる端末にも、ホスト名でアクセスできるということです。素晴らしい。

今回作ったデーモンはこの素晴らしいmDNSとの連携を意識した設計になっています。

デーモンは定期的にホスト名を正引きして、IPアドレスが変わっていた場合はルータにポートマッピングの再登録を行います。
この動きにより、ポート転送先サーバとして「ホスト名.local」を指定していれば、たとえサーバのリブートでDHCPから払い出されるIPアドレスが変わったとしても、ポート転送を追従させることができます。

これによって当初の「DHCP環境でもサーバ公開したい!」が達成できるというわけです。

集中管理にも分散管理にも使えます

このデーモンはデーモンが動作しているサーバへのポート転送の他に、別のサーバへのポート転送も設定することができます。

なので、管理サーバ立ててネットワーク内のすべてサーバのポートマッピングを集中管理することもできますし、それぞれのサーバでデーモンを動かして各サーバに自分が使うポートの管理を任せることもできます。

ダウンロード

github.com

インストール

Ruby開発キットをインストールする

apt-get install ruby ruby-dev build-essential

mupnp gemをインストールする

gem install mupnp

設定ファイルを編集して/etc/にコピーする

cp -p pnp_portmapd.conf.sample /etc/pnp_portmapd.conf

デーモンを起動する。

./pnp_portmapd

設定ファイル

YAML記法になってます。
JSONと違ってコメントが書き放題なのが良いですね。

# 設定
Settings:
  # ポートマッピング更新周期(秒)
  Period: 5

# ポートマッピング定義
PortMapping:
  # 転送先ホスト名
  akari.local:
   - ExtPort: 82   # 外部ポート
     IntPort: 81   # 転送先ポート
     Protocol: TCP # プロトコル(TCP/UDP)
   - ExtPort: 100
     IntPort: 101
     Protocol: UDP

  alicia.local:
   - ExtPort: 101
     IntPort: 102
     Protocol: UDP

この設定を適用すると、うちのルータではこんな感じになります。
akari.localが192.168.11.17、alicia.localが192.168.11.11です。
両者ともIPアドレスDHCPから払い出されたものであり、IPアドレス固定なしでサーバが公開できています。

f:id:moguno:20151126120957p:plain

ログファイル

/var/log/pnp_portmapd.logです。
ルータに設定を行うたびにINFOメッセージを出しているので、眺めてると楽しいです。

ライセンス

License: 3 clauses BSDとやらにします。

Mac OS Xでmikutterの通知とサウンドが使えるようになるプラグイン

mikutter

何これ?

OS Xでmikutterの通知ポップアップとサウンドを使えるようにします。
RubyからMacの通知を出すgem(terminal-notifier)を見つけた記念です。

インストール

GitHubからzipファイルをダウンロードして適当なディレクトリに展開して下さい。

moguno/mikutter-notifier-osx · GitHub

※mikutterプラグインマネージャ"Packaged"で"moguno"を検索してインストールするのもおすすめです。

もしかするとmikutterディレクトリでbundle installしないといけないかもしれません。

使い方

他のOS同様に、設定画面の「通知」メニューから有効にしたい通知とサウンドファイルを設定してください。

f:id:moguno:20151018221201p:plain

加えて、「サウンド」メニューから「Mac OS X」を選択してください。

f:id:moguno:20151018221213p:plain

こんな感じで通知が出て来ればOKです。

f:id:moguno:20151018221535p:plain

タイトルのターミナルっぽいアイコンはOS Xの仕様でterminal-notifierのアイコンから変更できないそうです。残念。

Proxmox VEのLXCコンテナにavahi-daemonを入れようとしてハマった話

Proxmox VE 4.0 LXC Avahi Ubuntu 15.04

Proxmox VEが4.0にバージョンアップしてLXCベースのコンテナが使えるようになったので、コンテナをぽこぽこ作っててハマったメモです。

コンテナのテンプレートはみんな大好きUbuntu Serverの15.04(ubuntu-15.04-standard_15.04-1.amd64.tar.gz)です。

2コンテナ目からavahi-daemonのインストールがコケる

IPアドレスお手軽解決のavahi-daemonを各コンテナにインストールしていたところ、2つ目のコンテナでapt-getが失敗する怪現象が発生しました。

root@FileServer:~# apt-get install avahi-daemon
・・・
Setting up avahi-daemon (0.6.31-4ubuntu4) ...
update-rc.d: warning: start and stop actions are no longer supported; falling back to defaults
Job for avahi-daemon.service failed. See "systemctl status avahi-daemon.service" and "journalctl -xe" for details.
invoke-rc.d: initscript avahi-daemon, action "start" failed.
dpkg: error processing package avahi-daemon (--configure):
 subprocess installed post-installation script returned error exit status 1
dpkg: dependency problems prevent configuration of libnss-mdns:amd64:
 libnss-mdns:amd64 depends on avahi-daemon (>= 0.6.16-1); however:
  Package avahi-daemon is not configured yet.

dpkg: error processing package libnss-mdns:amd64 (--configure):
 dependency problems - leaving unconfigured
Processing triggers for dbus (1.8.12-1ubuntu5) ...
Processing triggers for ureadahead (0.100.0-19) ...
Processing triggers for systemd (219-7ubuntu6) ...
Errors were encountered while processing:
 avahi-daemon
 libnss-mdns:amd64
E: Sub-process /usr/bin/dpkg returned an error code (1)

インストール後の自動起動がコケた結果、パッケージのインストールに失敗しているようです。
ファイルのインストール自体は済んでるみたいなので、試しに手動で起動してみます。

root@FileServer:~# avahi-daemon

Found user 'avahi' (UID 109) and group 'avahi' (GID 119).
Successfully dropped root privileges.
chroot.c: fork() failed: Resource temporarily unavailable
failed to start chroot() helper daemon.

なんでかふわっとした理由でfork()が失敗してますね。

ここまでの情報を使ってググると、ズバリの英語ページが見つかりました。

Avahi, setrlimit NPROC and lxc | Playing on the frontier

どうやら、avahi-daemonの中で作れるプロセス数の条件が制限されている模様です。

その制限がなぜかコンテナ間で共有されていて、複数コンテナの合計でこの制限に引っかかるっぽいですね。実際、1つめのコンテナを落とすと起動に成功しました。

# Linuxのネームスペースのサポートが未だ完璧でないんでしょうか。
# 応用したら別のコンテナをDoS出来そうでヤバいすね。

対策

avahi-daemonのインストール失敗後、/etc/avahi/avahi-daemon.confのプロセス数制限を無効にします。

     61 [rlimits]
     62 #rlimit-as=
     63 rlimit-core=0
     64 rlimit-data=4194304
     65 rlimit-fsize=0
     66 rlimit-nofile=768
     67 rlimit-stack=4194304
     68 #rlimit-nproc=3   ←コメントアウト。

avahi-daemon.conf編集後、再度apt-get install avahi-daemonしてインストールを成功させればOKです。
既にインストール済みのコンテナのavahi-daemon.confも同様に修正しておきましょう。

mikutter on Mac OS XのためにCairoとPangoのオレオレPortfileを作った話

MacPorts mikutter

OS X El Capitanへのアップグレードに伴いMacPortsをアップデートしたところ、cairoのQuartzサポートが悪さをする事象が再発しました。

moguno.hatenablog.jp

MacPortsのアップデートでactivateしていた古いパッケージが破棄された模様。

今使ってるsvnから古いPortfileを持ってくる技も今後使えなくなる可能性があるので、いい感じのPortfileを書いて、オレオレで抱え込むようにします。

方針

variantの+quartzが悪さをしているのは確実なのだけれど、+quartzがデフォルトで無効化出来ないようになっているので、その辺りをハックしたPortfileを作ります。

MacPortsにオレオレツリーを追加する。

ここでは、自分のホームディレクトリにmacportディレクトリを作ってそれをオレオレツリーにします。

mkdir ~/macports

vi /opt/local/etc/macports/sources.conf

・sources.conf

  8 # To add a local source, add a "file://" entry.
  9 #
 10 #   Example: file:///Users/landonf/misc/MacPorts/ports
 11 #
 12 # To prevent a source from synchronizing when `port sync` is used,
 13 # append "[nosync]" at the end.
 14 #
 15 #   Example: file:///Users/landonf/misc/MacPorts/ports [nosync]
 16 #
 17 # Note that MacPorts parses source URLs in order; when a port appears in
 18 # multiple sources, it installs the first occurrence. For local sources
 19 # to shadow remote ones, "file://" URLs must come before other URLs.
 20 file:///Users/moguno/macports             ←オレオレツリーのパスを追加

ハックするPortfileをもらってくる。

CairoとPangoを本家ツリーから頂いてきます。

cd /opt/local/var/macports/sources/rsync.macports.org/release/tarballs/ports/

tar cf - graphics/cairo | tar xf - -C ~/macports/
tar cf - x11/pango | tar xf - -C ~/macports/

Portfileの編集

デフォルトで有効になる+quartzをぶっ潰します。

cairo

118     #default_variants        +quartz     ←コメントアウト
119     # Don't allow Quartz support to be disabled. Keep the variant for awhile in
120     # case any dependents are using the active_variants portgroup to check for it.
121     #variant_set             quartz     ←コメントアウト

pango

 62     #default_variants    +quartz     ←コメントアウト
 63     # Don't allow Quartz support to be disabled. Keep the variant for awhile in
 64     # case any dependents are using the active_variants portgroup to check for it.
 65     #variant_set         quartz     ←コメントアウト

最後にPortIndexファイルを作って完成です。

cd /Users/moguno/macports
portindex

インストール

通常通りインストールすると、オレオレツリーを優先して使ってくれます。

sudo port install cairo
sudo port install pango

こんな感じで、x11にのみ+がついていればOKです。

sudo port info cairo pango

cairo @1.14.2_1 (graphics)
Variants:             opengl, quartz, universal, [+]x11     ←これ

Description:          Cairo is a vector graphics library with cross-device output support. It is designed to produce identical output on all output media while taking advantage of
                      display hardware acceleration when available (e.g. through the X Render Extension).
Homepage:             http://cairographics.org/

Extract Dependencies: xz
Build Dependencies:   pkgconfig
Library Dependencies: libpixman, glib2, fontconfig, freetype, libpng, zlib, expat, xrender, xorg-libXext, xorg-xcb-util
Conflicts with:       cairo-devel
Platforms:            darwin, macosx
License:              LGPL-2.1 MPL-1.1
Maintainers:          ryandesign@macports.org
--
pango @1.38.0 (x11)
Variants:             quartz, universal, [+]x11     ←これ

Description:          The goal of the Pango project is to provide an open-source framework for the layout and rendering of internationalized text.
Homepage:             http://www.pango.org/

Extract Dependencies: xz
Build Dependencies:   pkgconfig
Library Dependencies: glib2, cairo, harfbuzz, gobject-introspection, Xft2
Conflicts with:       pango-devel
Platforms:            darwin
License:              LGPL-2
Maintainers:          ryandesign@macports.org, openmaintainer@macports.org

これで安定してMacでmikutter出来ますね。

Bonjour for Windows不要!Windows10マシンに".local"でアクセスしよう!

Windows10

はじめに

家庭内LANのIPアドレスの管理って面倒ですよね。

一般のご家庭はDHCPから払い出されたのを空気の様に使ってればいいですが「家庭内サーバを立てよう!」とか変な気を起こすと、固定IPアドレスの管理を未来永劫しいられる事になります。

仮想マシンがぽこぽこ増えたり減ったりするこのご時世。めんどいですね!!

そんなあなたに朗報です。

Windows10でサーバレス&オープンなホスト名解決の仕組みであるmDNSがサポートされました。

情報ソースはこちらです。
仮想化雑記帳: Windows 10 and Bonjour

Macで言う所のBonjour。*NIXで言う所のavahiですね。

Windows8まではmDNSを使うためにiTunesもしくはBonjour Print Services for Windowsに含まれるBonjour for Windowsをインストールする必要があったので、今回の標準搭載はかなり嬉しいです。

情報ソースはプレビュー版での検証ですが、製品版でもちゃんと実装されています。
しかしながらプレビュー版と同じく、デフォルトではファイアウォールがmDNSのパケットを捨てています。(意味なくね?)

今回はmDNSを有効化するために、GUIからWindowsファイアウォールの設定変更をやってみようと思います。

Windowsファイアウォールの設定

コントロールパネルを起動する

Windows10ではアクションセンターの「すべての設定」が公式の設定画面になっていますが、できる事が異様に少ないので昔ながらのコントロールパネルも現役です。

左下のWindowsボタンを右クリックして「コントロールパネル」を起動して下さい。

f:id:moguno:20150912085411p:plain

Windowsファイアウォールの設定画面を起動する

f:id:moguno:20150912090211p:plain

こんな感じの画面が出てきます。

f:id:moguno:20150912090748p:plain

セキュリティが強化されたWindowsファイアウォール画面を起動する

ウインドウ左側の「詳細設定」を選択して「セキュリティが強化されたWindowsファイアウォール」を起動します。

f:id:moguno:20150912091155p:plain

この「殺意の波動に目覚めた志保」みたいなネーミング、嫌いじゃないです。

f:id:moguno:20150912090425p:plain

受信規則の作成

それでは本題。mDNSのポート5353/UDPを許可するルールを作ります。

ウインドウ左側の「受信の規則」を右クリックして「新しい規則」を選択します。

f:id:moguno:20150912091316p:plain

「ポート」を選択します。

f:id:moguno:20150912092145p:plain

  • UDP
  • 特定のローカルポート:5353

f:id:moguno:20150912092341p:plain

「接続を許可する」を選択。

f:id:moguno:20150912092427p:plain

ホスト名解決だけならいいだろうと適用範囲は全部にしました。

f:id:moguno:20150912094514p:plain

適当な名前を付けて完了です。

f:id:moguno:20150912092559p:plain

テスト

上記情報ソースに書かれている様に、別の端末から"ホスト名.local"にpingを打ってIPアドレスが引けているか確認して下さい。

$ ping venue8.local
PING venue8.local (192.168.11.12): 56 data bytes

Mac OSXをお使いの方は、dns-sdコマンドでも確認できます。

$ dns-sd -G v4 venue8.local
DATE: ---Sat 12 Sep 2015---
 9:28:57.904  ...STARTING...
Timestamp     A/R Flags if Hostname                               Address                                      TTL
 9:28:58.218  Add     2  4 venue8.local.                          192.168.11.12                                60

最後に

Windows10のmDNSサポートのおかげで、Mac、*NIX、Windowsを横断したホスト名解決がスマートに実現可能になりました。

家庭内サーバであればIPアドレスを固定することなく運用が可能です。

後はAndroidとルータがmDNSを喋れれば、本当にIPアドレスを意識しない家庭内LANになるんですけどね。

タブが隠せる!史上最強のmikutterプラグインができたよ!

mikutter

なにこれ?

タブを隠すことができます。

はぁ?舐めてんの?

違います!これすっごい可能性を秘めてると思うんですよ!

Bot用のどうでもいいタブを消す

今年の正月に書いたエントリで、時刻を吐くデータソースをトリガにして定期的にツイートを行うBotの作り方をご紹介しました。

moguno.hatenablog.jp

しかしこの方式では「たまに時刻が表示されるどうでもいいタブ」を保持しないといけません。

f:id:moguno:20150909221951p:plain

ダサいなぁ・・・邪魔だなぁ・・・と思いながら9ヶ月。

GTKのマニュアルを見る限りNoteBookのタブを隠すメソッドは無いのですっかり諦めてたんですが、昨日、偶然にもその方法を編み出す(※)事に成功した訳です。

(※別件で英語の知恵袋読んでたら見つけた。)

これで変ちくりんなBotを量産してもタブを圧迫することがなくなりました。いえい。

標準タブを置き換える

このプラグインの可能性は他にもあります。

例えば「オプションで日本語のツイートのみを検索できるタブ」プラグインを作ったとします。

f:id:moguno:20150909222136p:plain

その場合、当然ながら「標準の検索タブ」と「プラグインのタブ」が同居した中途半端な状態になります。

f:id:moguno:20150909222200p:plain

でも、このプラグインで標準の検索タブを隠せば、結果的に標準機能を置き換えたように見えます。

オリジナルmikutterは新しいステージへ。これが何気に大きいと思ってます。

ボスが来た

エッチなタブをお母さんから守ろう!

f:id:moguno:20150909222452p:plain

ておくれを辞めたい

このまま全部のタブを消したら、ておくれの呪縛から解放されるかもしれませんね。

f:id:moguno:20150909222741p:plain

・・・まで書いて、ゆめにっきのエンディングを思い出したよ。なむなむ。

インストール

GitHubからzipファイルをダウンロードして適当なディレクトリに展開して下さい。

moguno/mikutter-hide-tab · GitHub

※mikutterプラグインマネージャ"Packaged"で"moguno"を検索してインストールするのもおすすめです。

使い方

  • タブを右クリックして「タブを隠す」を選択するとタブが隠れます。

f:id:moguno:20150909223119p:plain

  • タブの再表示は、ウインドウ下部のまりもボタンから行います。

f:id:moguno:20150909223222p:plain