WebSocketをPHPで使う、ループ処理も

webブラウザにリアルタイムに変化する情報を表示したいなーと思ったら、既存の頭ではAjax通信をSetIntervalするなりして取得する感じでありましたが、なんかHTML5の世はWebSocketなる仕組みが大体のブラウザでサポートされるに至ったようです。

というわけでWebSocketを使って何か作ろうと思い立ちましたが、サーバー側はNode.jsとかを使うのが主流のようで、もう脳内がPHPになっちゃってる人に新規習得させるのもちょっとコストだな、ということでPHPで作ります。クライアント側はJavaScriptだからjQueryでもなんでも良い。

PHPでWebSocketというとRatchetというのが出てきますので素直にソレを使います。というかRatchetしかないよね。

そんなわけでPHP Ratchetで検索するといろんなQiitaとかblogが出てきます。そのままコピペするとバージョン違いで死ぬので参考程度にしておいて、ちゃんと本家のドキュメントでInstallationとHello Worldまで追いかけましょう(英語だけど)。私は孫引きして2時間ぐらい遠回りしました。
Ratchet – What is a WebSocket?

手順的にはcomposerを用意して、ratchetを取得、使うところでrequireしてやります。

# composerの取得
curl -sS https://getcomposer.org/installer | php

# composerの設定
# vi composer.json
{
"autoload": {
"psr-4": {
"MyApp\": "src"
}
},
"require": {
"cboden/ratchet": "^0.4"
}
}
# 0.4にしなくても * 指定で最新指定のようです

# ratchet取得
php ~/composer.phar require cboden/ratchet

あとはとりあえずHelloWorldからコピペして作ります。
telnetで通信するバージョンと、WebSocketで通信するバージョンができますので、違いを学ぶと良いです。
シリアルポートやSocketの通信をしたことがある方はあっさりと理解できると思います。要はSocket通信がWeb上でできるということですので。

server.php側は手続き型のPHPなのにイベントドリブンな書き方になるのでちょっと戸惑いますが、監視ループで処理していく以上はそうなります。

で、HelloWorldではメッセージの送受信が発生して、それに伴う処理を行うところまではできましたが、サーバー側で何かを監視して、サーバー側発でメッセージを送りたい場合はどう書くのか。ググってもなかなか出てきません。

Hello World的には無名関数を即時生成しています

<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;

require dirname(__DIR__) . '/vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
$server->run();

onほげほげメソッド以外に常に何か動かしたい場合、ループ処理の中で実行するコードをChatクラスの中に定義し、$serverに定期的に実行させれば良いのです。

この辺は日本語ソース見つからず、stackoverflowで見ました。
web services – How do I access the ratchet php periodic loop and client sending inside app? – Stack Overflow

<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;

require dirname(__DIR__) . '/vendor/autoload.php';
$chat = new Chat();
$server = IoServer::factory(
new HttpServer(
new WsServer(
$chat
)
),
8080
);
$server->loop->addPeriodicTimer(5, function () use ($chat) {
$chat->someMethod();
});
$server->run();

$chatを複数箇所で指定する必要があるので、事前にnewしておきます。
$serverのloopにaddPeriodicTimerを使って繰り返し処理を作成、別途Chatの中に呼び出すメソッドを作っておけばOKです。
addPeriodicTimerは小数も設定できるので、ミリ秒単位で実行することもできるみたいですが、正確にミリ秒にはならないかも。
とりあえず0.01秒ごとにmicrotime()の結果をクライアントにだらだと流してみましたが、飛び飛びな感じでした。実機・VMなどの環境にもよるだろうなぁ。

今回、PHPは7.0で実行しました。

IIS ISAPI 32bit/64bit でハマった

新しいWindowsはほとんど64bitだから32bit時代のISAPI向けDLLをIISで動かそうというときはアプリケーションプールの詳細設定で32bit対応をtrueにしないといけないよ!
という話。

Windows Server 2003の緊急リプレースに呼ばれ、当然OSだけじゃなくて乗っているソフトウェアも移行せねばならず、とっくに各種ソフトのサポートも切れており、しかもカスタムされたソフトウェアなのでメンテナンス向けマニュアル類が貧弱な環境。とりあえず元サーバーのファイル構成から見よう見まねで組み上がり…ました!

が、IISの部分だけどうしても動かない。
dllをISAPIでハンドリングさせてやれば良いはずなのだが…
最初は403エラー、権限の設定で実行が入っていないためだとわかったが、実行に入れてやると500エラー。しかもdll本来のエラーメッセージではないのでIISからISAPIでハンドリングする部分がおかしいようだ。ここでハマり。

アプリケーションプールを.NET 2.0で作成、その後IIS管理ツールの右側にある「詳細設定」から「32 ビットアプリケーションの有効化」をtrueに…
あっさり動いた。こんな項目があること自体が頭から抜けてたわ…

ということで、業務系システムはメンテナンスできるところを確保しながら延命するか、延命できないなら次のシステムに乗り換えるか考えないといけません。元の開発会社だって当時のメンバーがもういないので無理ですってパターンもありますからね。
大手企業だったらそのへん大丈夫でしょうけど、中小企業はどうしたってカスタマイズから頼むとなると中小ベンダや個人事業主に頼らざるを得ない。

伝説の「小川マシンエレクトロ」さんじゃないですが、いざというときの選択肢として、ソフトウェア会社以外の、横断的知識を持った、ハッカー的な人材、能力者がほしいですね…
いや、ウチに頼んでくれてもいいんですけども。

sambaでグループが見つかりません

sambaにアクセスしようとしたらグループが見つかりませんと言われる。
サーバー側でログを見ると「NT_STATUS_NO_SUCH_GROUP」ですって。
samba groupも存在してるしunix groupも存在してる。

ググるとmsdfsが原因だとか書かれていたが、関係なかった。

Error While Trying To Connect To Samba Share: NT_STATUS_NO_SUCH_GROUP

force groupに指定している名前が
samba groupとunix groupで同一名だとうまく動かないみたい。

force group = "Unix Group\hogegroup"

と Unix Group\ をつけてやるときちんと動いた。

上記例はSUSE Linuxだったが、CentOS7でも同様でした。

ファイルの大量削除@さくら

「WPにファイルがアップロードできないんです」
「WPのアップデートもできないんです」
「WPの動作がおかしいんです」
さくらのレンタルサーバーをご利用で、長期にわたってほっとかれたサイト。
容量限界まではずいぶん余裕がある。
SFTPで適当なファイルをアップロードしようとしてもエラー。
要は新規ファイルが作れないようです。

一旦バックアップのために全部ダウンロードしようとしたら、
ファイル数が膨大すぎて無理な感じ!
キャッシュ系プラグインの吐き出した細かいファイルですねこれ。

とりあえずキャッシュプラグインを止めます。

FTPからの削除も途中で止まっちゃうので困ってしまいましたが、
なんと、さくらのレンタルサーバーはSSHでシェルに入れる!
やったー

ということで入ってみてquotaを見てみると、
確かに300万ファイルの制限が。
ちょとはSFTPで削除できていたので299万+のファイルが残っています。

% rm -rf hoge
さくらのレンタルサーバーでは実行時間が長いプログラムはKillされます。
すばらしい気遣いです。
見てたら55分ぐらいでkillされてました。

いちいち見てられないのでバックグラウンド実行
% rm -rf hoge &
これでログアウトしてもよさげです。

% quota
Disk quotas for user XXXXXXXX (uid XXXX):
Filesystem usage quota limit grace files quota limit grace
/var 4 1048576 1048576 169 100000 100000
/home 15444260 104857600 104857600 1353006 3000000 3000000

何度か実行して削除完了できそうです。

参考にさせていただきました

SSH について – さくらのサポート情報

大量・巨大なファイル操作を低負荷で行う方法 – How old are you?

i8042 no controller found / CentOS7が起動しない

PC Linuxサーバー(HP proliant microserver gen5だったかな)の電源を落とし、
物理的に移動したあとに、とりあえず接続して起動させようとしたら
i8042: no controller found
と出てきて停止してしまう。

このサーバーは外付けUSB HDDをバックアップ用に繋げてあって、
起動時にmountするようにしてあったのだが、
それが接続されていなかった。

接続したら元にもどった。
というか接続しても i8042: no controller found のメッセージは出ていた。
詳しくjournalctlも見てなかったが、本当はi8042のメッセージの後が怪しかったんだろうな。