世界QRカウンター(への一歩)

社長:何か面白い事をしたいですね。

開発:たとえば。

社長:たとえば、わざわざそれを人間の手でやるの?という面白さが点描にはあるわけです。その逆に、普通は人間が手作業でやるものだと思われているものを機械的にミリ秒でやってしまう。

開発:まあ実用という言う意味では、設立当初から懸案の電子署名ですね。機械がハンコを押す。でもそれって、すでにSSLとともに実用化しているとは言えるかなと思います。サーバがミリ秒でコネクションにハンコを押すという。

社長:結果が人間にとって面白いというか、見える化されることが重要だと思うんです。結果が揮発性では無く、グローバルであることも。

社長:たとえば、以前少しかじったQRですが、あれは生成するのは今や簡単なんですが、通常は人間の手でパラメータを決めて生成するのに、そこそこの手間をかけている。そうでは無く、たとえばHTTPでリクエストしたら、そこに書いたパラメータを反映したQRのPNGが返る。ミリ秒で。

開発:まあ、我が社の先端CGi技術で(笑)。50ミリ秒で返せると思います。工期は2時間くらいですかね。どういう付加価値を付けるのかが問題かなと思いますが。

社長:そこで思ったのが「世界でひとつのカウンター」です。世界で起きたことの全てに一連番号を付与する。タイムスタンプと電子署名付きです。で、そのシリアル番号と署名情報をQRで返す。署名情報はPNGのコメント的チャンクに入れる。

基盤:日付入りのスタンパーって味があって好きなんですが、あれがQRで出来ているという感じですかね。

社長:それで私は qrstamp というドメイン名を取りました。

経理:.online で経費節約でした。

開発:しかし、我社の500円サーバでは、1秒に10回程度、一日に100万回がせいぜいだと思いますけどね。

社長:one small step for man ですよ。百里の道も一歩から。

開発:じゃま、とりあえずやってみますか。

社長:というか私、お昼にビール2本はちょっときつかったです。また眠くなってしましました。寝てる間にやっといてくれるといいな。

開発:それがそうはいかないのが当社の仕組みになっております。

* * *

開発:さて、QRの生成は go のパッケージで簡単にできることが以前の学習調査でわかっています。なので、この go スクリプトをコピペして、Go run!

開発:あ、パッケージが無いですね。こういう時は、go get パッケージ名、でゲットできることも知っております。go get。

開発:それでは再び Go!? no such file ... ああ、stap じゃなくて stamp ですね。では Go!

開発:所要時間260ms。これは想定どおりです。では go build のちに qrstamp!

開発:ということで、10ms以内の生成、png のファイルサイズは825バイトなので1パケットです。

開発:で、これを CGI から呼ぶわけですが… うーん、人間がテストするにはいきなりPNGでダウンロードになっちゃうのはイマイチですね。やはりHTMLの中に表示したい。あと、.cgi で呼び出してダウンロードするとそのもののファイル名になるから .cgi って何型式ですかって怒る人もいると。そもそも何という名前のファイルにするかというのも考えどころです。これもパラメタで伝えるんでしょうね…

経理:ポーン。アマゾンからメールが来ました。

基盤:めっちゃ色々 attempt しましたしねー。よろこびもひとしおです。

開発:うーん、昨日作った点描のを流用しているんですが、このフォームはめちゃダサいな。やっぱ、点描でもそうだし、色のピッキングの共通ライブラリが必要ですね。

基盤:いくらでも既製のがあるんじゃないですかね。

社長:何でもいいので、とりあえず結果が見たいです。

開発:それではミニマルで。こんな感じですかね。

社長:おお、どれどれ、iPhoneのカメラで覗く…

社長:なんか Hello World のまんまですが。

開発:Goでコマンド引数を受け取る方法をまだ知らないのです。というか、タバコが切れました。買ってきましょうか。

社長:いやその前にそこをなんとか。コーヒーを入れて置きますから。

開発:えー、go command line argument で検索。。ああ、os.Args[] という配列ですね。これでどうでしょう?

開発:あれ?なんか反転してしまいましたね。使える文字に制約があるとか?

開発:おや?

開発:はてな?

社長:あ、未開封タバコ一箱発見。一服しましょう。

* * *

社長:長さ制限とか文字セットでは無いですね。構文?

開発:手動テストに切り替えましょう。go run qrstamp.go 1234567890-... うーん、不思議。どういう規則でしょう? 200x200 なのがまずいとか。400x400。変わらないですね。まあ200x200で入りきならいはずが無い。os.Argsの問題?でも無いですね。定数で与えても同じ。

社長:以前 JavaScriptでPNG 生成というのを見ましたね。あれではどうでしょう?

開発:問題なしですね。

基盤:それにしてもこの、一文字入れるごとに生成されるデモ、何度見てもインパクトありますね。

開発:ということは、Go の QR パッケージに何かありますね。MacOS版ではどうかな…

基盤:なんと、問題なし。

開発:go のバージョンは…

基盤:気が遠くなるほど古い?てか日付がわからない。

開発:一応 apt upgrade。うーん、1.10.4 が最新でございます。というか、こういう基本的っぽいプログラムにとって、昔の版とか関係しますかねぇ。

基盤:Goの本家を見てみます。うーん、go1.14.4 が最新だとありますね。tarball を落としてインストールしましょう。っていうか、これなら xso にもそのまま持ってけますね。おやー、scp めっちゃ遅い。1.1MB/s。ライトセールはポートごとにチョークを変えてるんですかね?

基盤:ではインストール手引の仰せのとおりに。というか、今現在の Go って何者?

開発:骨董品ですね。

基盤:では仰せのとおりに /usr/local/go にインストールをば… てか、-C ってオプション。こういうのがあるといいなというか、あるはずだとは思ってたんですよね…

基盤:では。

開発:では、まずは /usr/local/go/bin/go run qrstamp.go 1234...。できたかな?ダウンロードして見る。

基盤:ばっちりですね。

開発:じゃCGIに。

開発:・・・ あれー、だめだな。ライブラリとの整合性?GOROOT環境変数とかかな…

開発:だめだ。本家の人の解説が見つからない。わからん。

社長:ちょっといっぷくしましょう。

* * *

開発:さっきうまく行ったように見えたのはダウンロードしたやつで… カメラで撮ってみる。

開発:う、そうか。枠が無いと、データによっては識別できないということか。つまり、あの青背景が邪魔をしていたのではあるまいか。白背景にしてみるとどうか。

基盤:当たり。

開発:例題をもっと簡単にしましょう。1234567890abcde。

1234567890abcde のQRコード

開発:これは枠なしで生成されてしまうので、カメラで認識できない。一方、1234567890abcd。

1234567890abcd のQRコード

開発:これは枠が生成されるので、カメラで認識される。

基盤:QRって枠というか外との境界に弱いんですかね。意外。

開発:問題は、この Go の QR パッケージは外枠を生成する場合としない場合があること。意図したものでは無いように思われます。いわゆるバグってやつ?

基盤:常に枠を出さないというのなら、それはそれで一貫していると思うんですけどね。

社長:だいぶ見えてきましたね。いっぷくしましょう。

* * *

開発:それにしても意外なところでつまづきました。

基盤:Goの版とか、寄り道をしました (^-^;

社長:でもそれが面白いです。自力インストールの勉強にもなったし。

基盤:まあ、ダウンロードして展開するだけということがわかりましたw

開発:最初、枠なしのやつが「反転している」ように見えたのですが、枠なしだとそれだけ人間の視覚的にも認識が動揺するってことですかね。

開発:Goのパッケージの仕様としては、枠あり、無しを明示指定できるのが良いのでしょうね。というかおそらく、QRの仕様として枠の仕様が規定されているんだろうと思います。

基盤:どういうコーディングなんですかね。っと。

ns0% cd ~/go/src/github.com/boombuler/barcode/qr
ns0% wc *
   66   186  1426 alphanumeric.go
   44   184   978 alphanumeric_test.go
   23    87   573 automatic.go
   30    90   806 automatic_test.go
   59   195  1784 blocks.go
   36   482  2332 blocks_test.go
  416  2321 15495 encoder.go
  134   298  2529 encoder_test.go
   29    79   639 errorcorrection.go
   60  1981 10157 errorcorrection_test.go
   56   160  1136 numeric.go
   26   132   783 numeric_test.go
  166   508  3309 qrcode.go
  126   340  2353 qrcode_test.go
   27    84   681 unicode.go
   18    80   473 unicode_test.go
  310  1540  9417 versioninfo.go
  157   562  4310 versioninfo_test.go
 1783  9309 59181 total

基盤:コンパクトですね。テスト用のコードを除けば 1,152行。

ns0% wc *go
   66   186  1426 alphanumeric.go
   23    87   573 automatic.go
   59   195  1784 blocks.go
  416  2321 15495 encoder.go
   29    79   639 errorcorrection.go
   56   160  1136 numeric.go
  166   508  3309 qrcode.go
   27    84   681 unicode.go
  310  1540  9417 versioninfo.go
 1152  5160 34460 total

開発:うーん、しかしこれ、仕様書を読みながらゼロからCで書いてたらと思うと、ぞっとしますね。

社長:そういえば、スケスケで色付きのとか虹色のQRってどう作るんでしょうね。

開発:PNGにする前にいじるか、PNGにしてからいじるかですね。二値画像ですから、どっちにしても簡単だと思いますが。使いでがあるっていう意味では、PNGの加工のほうが何にでも使えて良いですね。でも、せっかくだからQRのレベルでやるとすると…

func main() {
	// Create the barcode
	qrCode, _ := qr.Encode("Hello World", qr.M, qr.Auto)

	// Scale the barcode to 200x200 pixels
	qrCode, _ = barcode.Scale(qrCode, 200, 200)

	// create the output file
	file, _ := os.Create("qrcode.png")
	defer file.Close()

	// encode the barcode as png
	png.Encode(file, qrCode)
}

開発:qrCode というのを最終的に png.Encode してます。これは barcode.Barcode という型ですね。これは png.Encode が入力とする image.Image をラップしたもののようです。

開発:ところでこのパッケージ全体は barcode という名前なんですが、QRの他に通常のバーコードとか、PDF417とかを実装しているようです。え、PDFってあのAdobeのPortable Document Format?って一瞬ドキドキしたのですが、Portable Data File の略だそうです。

社長:そういえば海外から何か購入した時に見たような記憶もあります。

開発:1991年に発案されたそうですから、2次元バーコードとしては、1994年発明のQRコードより少し先輩ですね。

開発:それで、image.Image というのは何かというと、こういう定義です。

type Image interface {
    // ColorModel returns the Image's color model.
    ColorModel() color.Model
    // Bounds returns the domain for which At can return non-zero color.
    // The bounds do not necessarily contain the point (0, 0).
    Bounds() Rectangle
    // At returns the color of the pixel at (x, y).
    // At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
    // At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
    At(x, y int) color.Color
}

開発:この辺を Go QR がどうしているかというと、qrcode.go のこのあたりのようです。

func (qr *qrcode) ColorModel() color.Model {
        return color.Gray16Model
}

func (qr *qrcode) Bounds() image.Rectangle {
        return image.Rect(0, 0, qr.dimension, qr.dimension)
}

func (qr *qrcode) At(x, y int) color.Color {
        if qr.Get(x, y) {
                return color.Black
        }
        return color.White
}

開発:これを見ると、At で color.White を返しているところを透明?にすれば良いのかなという気がします。その前にまず、Black を返しているところを Blue にしたらどうなるか。… ああ、Blue なんて undefined だと。というか、そもそもGray16Modelです。では White にしてみる。ムジナになりました(笑)では、White と Black を反転してみるとどうか。変な感じになりました。

開発:Black と White の他に color.Transparent というのがあるようです。これじゃないですかね。

Standard colors.
var (
    Black       = Gray16{0}
    White       = Gray16{0xffff}
    Transparent = Alpha16{0}
    Opaque      = Alpha16{0xffff}
)

開発:うーん、真っ黒になっちゃいますね。というか、カラーモデルが Gray16Model なんでどうにもならないのかも。color.RGBAModel というのにしてみます。おっ!

基盤:大成功、ぱちぱちぱちっ。

社長:これだと何とか、iPhone のカメラも認識します。

開発:白抜きではどうでしょう。

社長:iPhoneのカメラはこっちのほうが得意ですね。

基盤:うーん、面白すぎ。

社長:面白くて疲れたのでひと休みしましょう。

* * *

社長:重ねてみましょう。

社長:ずうっとこれがやりたかったのです。構想6週間。

開発:制作半日、改変コード3行。

基盤:ほとんど関係ないところで迷って時間を潰してしまいましたね。

開発:世界征服カウンターまでたどり着けませんでした。

基盤:た~か~の~つ~め~

社長:良いではないですか。我社にとって one giant leap です。

開発:点描空間の素材にも使いたいですね。

基盤:ていうか、しょっちゅう外でゴホゴホ咳をしているおばさん何者ですかね?気になるというか気に触るというか。

開発:あと、枠がなくなっちゃう件は、qr.Encode でパターンを作った後に、barcode.Scale ていうので指定サイズに拡大フィットさせているようなので、ちょうどパディング無しでサイズにフィットすることがあるということかなと思います。もともとフチを作るという考えは無かったのではないかとも思います。構造上昔のバーコードには要らなかったのかなと。

-- 2020-0703 SatoxITS

ダメ銀行なの?

経理:こんなメールが来ました。

経理:そんなに限度額を低くしてるんですか?

社長:んなこたあない。

基盤:だいたい、今月 AWS から300ドルなんていう請求が来るはずがありません。3.00ドルならわかります。それにこのメール、いつもの .00 もついてないし、非常におかしい。

経理:きちんと電子署名されたメールですから、釣りとか冗談ではないと思いますが。

開発:この銀行、お買い物のアマゾンは通ってますよね。あれって日本国内での送金なんですかね?

経理:JPYになってます。

開発:あそうか。日本のアマゾンだし円で買い物してますね。

経理:円以外で払う場合の限度額とかの設定では無いですか?

社長:そんな設定あったかな?

開発:これ、ライトセールの料金ですよね。払わないと止められちゃいます。

社長:それは非常にまずい。今やライトセールは我社の生命線ですから。

基盤:ライトセールのコンソールにこのような悲しい事を書かれてます。

経理:コンソールのページのリンクから払えますね。

基盤:幸いまだ、ライトセールは止められてはいません。とてもにこやかです。

開発:Gmail なんて金払いが間に合わなかったら瞬時に止められましたよね。恐ろしい。

社長:まずは限度額の設定ですが… どうやるんだろう?おお、この機能検索は素晴らしい。やっぱりこのウェブサイト、よく出来てますね。… うーん、円以外での限度額設定があるようには見えないですね…

社長:うーん、メールをもう一度確認。ああ、このリンク先で設定しろと。おや?「海外ショッピング、限度額0円」になってる、これですかね?かちゃかちゃ、ぷち。これでどうでしょう?

経理:では「確認して支払う」をぽちっ。「支払いを完了する」をぽちっと。

社長:おっと、メールが来ましたね。

基盤:AWSのコンソールではこのように。

開発:めでたし。

経理:銀行からのメールです。

開発:これがそれになったと。

経理:ただいまの時刻、1ドル107.52円です。

基盤:3.07 * 107.52 ... 330.0864 円のはず。

開発:なんで9円多いんでしょう?さっきより円が下がった?

経理:引き落としがされたのが 10:17 でしたが、その時点でも 107.52 よりは高かったと思われます。

開発:うーむ、いつの時点のレートなのやら。あるいは何か手数料が?

基盤:総額の約3%なので、カード手数料っぽいですけど、それってこっちに盛られるわけ?

経理:要確認です。

社長:いやあ、でもとりあえず一件落着といいますか。私的には「限度額」の謎が解けてスッキリしました。USD 3.07 のはずが USD 307 と表示されてましたが、メールの後半にこのようにあります。

基盤:いったいどうやったらそういう画期的にヘマなシステムが実現できるんでしょうね??

経理:限度額だけの問題ではなくて、$3.07 は払えませんでした、限度額を上げたら、339.00円引き落としました、っていう展開は、わかるけど不連続に感じます。

基盤:「元の請求は $3.07 」であったことの明示と、それがなぜ 「引き落とし339.00 円」になったのかの説明が必要ですね。

社長:限度額の件もですね。「海外ショッピングの」利用限度額にかかったとか。でも実はUSD 300と誤認識されて、それが日本円に換算されて、限度額にかかった可能性も無くはないかなと思います。

経理:そういえば昨日、水道代の請求書が来たんですが、コンビニ払い用の請求書ですから、バーコードをスマホの PayB でぴってやって終了です。そういう意味でも、やはり PayB にも対応しているあっちの銀行が当社のメインバンクにふさわしいと思います。

社長:当社にふさわしい銀行(笑)それはともかく、アマゾンAWSがドルでっていうところにも問題の一端があると思いました。

-- 2020-0703 SatoxITS

専属ホスト

社長:/etc/hosts のユーザ版があると良いのにと思います。

開発:自分なりにホストに名前を付けたいことは多いですからね。

!!!

基盤:うわっ、またMacMini落ちた。

経理:そう言えば中にiMacの入ってるはずの台形ダンボールが玄関のオブジェ化してますね。ちょっと邪魔だし。我が社最初の固定資産なのに。

社長:オブジェ指向。

開発:開けたら中からカルロスさんが出てきたりして。

社長:しかし驚くのはこの、Mission Control の仮想デスクトップとそれぞれに配置されてたアプリのウィンドウがちゃんと回復することです。

開発:特にターミナルについては、まあセッションは切れちゃいますけど、やってきた作業の履歴が見れるのが助かりますね。

基盤:そもそも落ちなきゃいいっていう話ではありますけどね。ひょっとして熱暴走ですか?あと、Mission Control については、Desktop 1, 2, 3とかじゃなくて、ユーザに名前つけさせろって世界中で非難ゴーゴーです。

開発:まあゴーゴーするほどこれの愛用者が居るかって話ですけどね。そもそも仮想デスクトップは固定的な名前を付けられるような安定した存在なのかというところが疑問です。

社長:デスクトップごとに、ここはソフト開発用デスクとか、ログ監視デスクとか、社長のブログ執筆机とかw,固定してアプリを配置して、そのままずっと使い続けたいですね。

開発:普通に ~/Desktop の他に ~/Desktop1, ... 式にディレクトリを作ればいいんじゃないかって気もしますよね。

社長:それを言うなら、全てのディレクトリがデスクトップであり得ても良いですよね。単に、このディレクトリはデスクトップ的なビューで表示できます、てなスイッチがあってくれれば。で、そのディレクトリを開くと仮想デスクトップが開く。うーん、それともディレクトリの中でコンテクストメニューを開くと「デスクトップ型式で表示する」でも良いかな。

開発:それと、このデスクではタイル型のウィンドウ配置とか、サムネール置き場とか、デスクトップごとにウィンドウのマネージメントの方式を変えたいですね。ドックとかタスクバーなんかも、デスクトップごとに定義できる。

経理:デスクトップごとに、セキュリティ上のタイムアウトとかスクリーンセーバとか変えられたら安心です。

開発:昔は複数ユーザの間をシャカシャカ切り替えたりもしましたけどね。

社長:うちもいつかそっち方面にも手が出せると良いですね。

* * *

社長:昔はホストに短縮名を付けたり、階層的なドメイン名の省略規則を使ったものですが、最近ではそういう事はほとんどされなくなったように思います。

開発:はじめは /etc/hosts で、そのうち YP、NISが普及して、最終的にはDNS一色になりました。DNSではせっかく階層的になってても、参照する側はFQDNとしてしか使わなくなりましたね。

基盤:というかWindowsの人たちはWORKGROUPみたいなグループの中で名前を付けてましたね。WINS?

社長:そういえば私の先輩は今でも、自分のPCをetlxxxというホスト名にしてます(^^)

開発:GUI化して手打ちでホスト名を入れることがほとんど無くなったという事もあるでしょうね。管理上は、グローバルにいつも同じ名前表記で参照されることが望ましいし。

基盤:ですがインフラの管理作業ではターミナルを使うことが多いので、手打ちでホスト名を入れることも多くて、短い alias があったほうが助かります。

開発:その alias という単語を良く使ってたのは、おそらくYPでのホスト名の alias の事だったように思います。おぼろげな記憶ですが。

社長:短縮名やニックネームを一意に意図する対象に結びつけるというのは、特にコンピュータの世界では根幹ですね。

開発:DNSではドメイン名が直接最終的なアドレスまで変換されるわけですが、名前が多段階にマッピングされる場合もある。ファイル名のシンボリックリンクとか。

社長:まあサーバのマウントというのもまさにそれなんですが。HTTPの世界ではリバースプロキシという特殊な呼ばれ方をしますが。

開発:プログラミング言語の世界では名前のスコープとか寿命とかが明確に規定されていて有用なわけですが、あれと同じような名前の管理をもっと一般的に適用したら面白いと思います。

基盤:ホスト、ファイル、デバイス、ユーザ、それぞれに名前の管理システムが違うのはいかがなものかという気はします。

開発:それは昔なら /etc/hosts であり、/etc/services であり、/etc/passwd であり、/etc/fstab であり、とかしたわけですね。

社長:ユーザ名の識別もDNSでやったら良いのにと思いましたよね。なんでも階層化しちゃう。

開発:ユーザ名とホスト名の間が @ であるというのは、わかりやすくも有り、不連続で嫌だな感も感じはします。

基盤:@はマシンと人間の境界なんだと思いますが。あー、でも人間である必要は無いか。

開発:そこにポート番号を入れられたらいいのにと思いますね。だって、user@host.domain:port って、表記の位置関係が不自然ですよね。何にしても、@より左側の表記方法が定式化されていないのはつまらないと思います。

社長:そういえばドメイン名って、左から右に向けてローカル化する記法ってありませんでしたっけ?

基盤:名前をUUIDに変換するというようなDNS的なものはあるんですかね?まあDNSを使っても良いと思いますが。MACアドレスも逆引きできるといいですね。

開発:何にしても、ものには全てフィジカルに結びついた物理的なIDと、サイバーで論理的でマッピングしたり変換できるIDがあると良いんだろうなと思いますね。

社長:研究としてそういう事をやっているかやってた人は絶対居ると思います。

* * *

社長:それで、ホスト名をユーザが簡単に決めて、自分から見える世界ではいつでもどこでもそれを使えるようにしたい。/etc/hosts以外に簡単な方法はあるでしょうか?

基盤:というかDNS的ならベタファイルじゃなくて、ドメインの階層に従ったディレクトリになるんじゃないですかね。

開発:トップダウンなドメイン名の階層と、横紙破りなaliasの関係がよくわからないですね。

基盤:alias も階層化されるんでしょうね。

社長:それで私は、現行のシステムでホスト名がどう解決されるのか知りたかったわけです。で、strace telnet xxxxx とかして見たのです。で、名前解決のためにどんなファイルとかサービスを見てるのだろうって。

社長:あ、コマンド + +/ー でターミナルの拡大縮小ができるようになりました。さっきリブートするまで効かなくて、なんだろうって思ってたんですが。あれ?拡大が出来ない… おっと、コマンド+Shift+ +でした。なんでこうなるの?

経理:iMac にちゃんとしたMac用のキーボード付属してきてますよね。あとお絵かき用のパッドも。

開発:お絵かき用のパッドで、オレオレ手書きフォント作りたいですね。

基盤:点描に打ち込むんじゃないんですか?

社長:それで、grep -e xxxxx -e open なんてすると、こういう事になってました。

社長:47番に /etc/hosts が出てきてます。それより後はDNS/UDPです。

社長:で、思い出したんですが、何をどういう順序で見るかは、/etc/host.conf で定義できたようなという事。

社長:さらに man host.conf すると、trim というキーワードでローカルドメインのマッチングを制御できるということです。

社長:それで、order に何が書けるかというと、bind, hosts and nis なんですね。私もこれに習ってリゾルバの順序を規定するパラメータを作ったんだと思います。なんで dns じゃなくて bind なのかとか、nis ってまだあるのかしら?とか引っかかりは感じます。

社長:そして man hosts。残念なことに /etc/hosts 以外を見てくれる気配は微塵も無いですね。でも「In  modern  systems, even though the host table has been superseded by DNS, it is still widely used for: bootstrapping, NIS, isolated nodes」という事でした。/etc/hosts に #include とか書けるといいのにな。うーん、Google IMEのショートカットまで変になってきた。

経理:実際このキーボードが終わりかけなんでは。

基盤:怪奇現象に出会ったら物理層を疑えの法則。

開発:ユーザの使う共有ライブラリをすり替えて、openを引っ掛けて、/etc/hosts を read-only で開いたら、/etc/hosts と自分の ~/.hosts をマージしたものを返すとかでどうですかね。

基盤:まあ自分専用のリゾルバを立てるのが自然かなとは思いますが。

社長:そして!最初のほうに出てくる nsswitch というのに見覚えがあったので、man nsswitch.conf してみたら、これがまさに色んな名前のリゾルバーのスイッチだったわけです。で、こっちでは hosts は dns, file, nis だよとあります。そして、db というので何かできる感じはします。というか、/lib/libnss_xxxx.so を参照することになってるんですが、そういうライブラリってもう絶滅しているかも知れないので、自分たちで復活させても被らずに済むかなと言う感じがします。何にしても、昔の人は名前の解釈について統合的に考えてたように思いますね。

基盤:find するとlibnssありますね。x86_64-linux-gnu の下とか。

社長:まあ、既存の共有ライブラリを自分用にラッピングするという話であれば、gethostbyname()だとは思います。

-- 2020-0703 SatoxITS

レンタルWordPressサーバでCGI

開発:さて、それでこのCGIをXSOのWordPressサーバで動かしたいと思うのですが。

基盤:WordPress cgi でググる。・・・ なんだかよくわからないですね。でも、これって単に apache サーバだと思いますから、WordPress のお世話になる必要も無いかと。

開発:まあそうですね。

基盤:ただし!xsoのサーバには Go がありません。su にはなれませんから、apt とかではインストールできません。まあ、手作業でインストールすれば良いとは思いますが。

* * *

開発:xso のレンタルサーバって実体は何なんですかね?

基盤:Linuxで、カーネルは3.10のようです。

xso% uname -a
Linux xso 3.10.0-962.3.2.lve1.5.24.8.el7.x86_64 #1 SMP Fri Jan 4 06:55:54 EST 2019 x86_64 x86_64 x86_64 GNU/Linux

基盤:/usr/lib に yum なんちゃらがあるので、RedHat 系なのかなという気配がします。

xso% ls -ld /usr/lib/yum*
drwxr-xr-x. 2 root root 198 Jan 23 2019 /usr/lib/yum-plugins

基盤:ちなみにうちはレンタルサーバの最安プランでストレージの使用可能総量は300GBという契約になっていますが、このWordPressサーバぶんで物理的には8TBまでは行けるようです。

xso% df .
df: Warning: cannot read table of mounted file systems: No such file or directory
Filesystem 1K-blocks Used Available Use% Mounted on
8415360000 457725056 7957634944 6% /home/oreore

開発:これってSSDという話でしたっけ?8TBの塊なんて拝めるとは?

基盤:このマシンに他のどんなお客さんが居るのかはわかりませんが、ロードアベレージが1を超えているのは普通なので、まるでガラ空きというわけではないように思われます。

開発:メモリが26GBというのはなんだか微妙な数字。しかし、up 511 days って、結構な鉄人ですね。

基盤:CPUの処理能力的には並の下みたいな感じですね。

* * *

開発:では、CGIプログラムをこのサーバに置いてみましょう。とりあえず Goが無いので、.go はコンパイルして持っていきます。コンパイルする側のカーネルは5.3ですが、単にテキストファイルを読んでPNGに変換するだけのプログラムだからカーネルとか関係ないと思います。

開発:で、これを ~/public_html/its-more.jp/pointillism の下に置いて、おもむろにアクセス。

基盤:ふつうに動きますね。

開発:ただし。サーバ側でPNGをキャッシュしているらしく、打った点を含んだPNGがなかなか帰って来ません。

基盤:応答コードがほぼ 304 になりますね。Apacheかnginxの設定なのかな?そういえば、xso のWordPressにサーバ側のキャッシュを無効にするというプラグインが入ってて、有効にしてあります。「サーバーキャッシュの設定を有効にしたままで、新規の投稿をすぐに確認できるようになります。」という説明です。てことは、「そもそものサーバのキャッシュの設定を無効にする」のが簡単な対処法かなと思います。

開発:どういう設定なんですかね。

基盤:nginx server side cache で検索。… これですかね。

https://blog.runcloud.io/nginx-fastcgi-cache/
How To Use Nginx FastCGI Cache (RunCache) To Speed Up Your WordPress Performance

開発:サーバは xso が抑えてるからユーザには手が出なそうです。.htaccess 的なもので制御できないもんですかね。… そもそも何をキャッシュの対象に設定しているのやら。うーん、考えてみればこの cgi の出力自体は毎回更新されるし、*.cgi は除外されているのかも。じゃあ、生成した png を CGI として返してみましょう。

開発:で、どうかな?ぽち、ぽち、ぽち、…

基盤:作戦成功ですね (^-^)

開発:なるほど。普通に使えそうですね。自分の知らないCGIを勝手にキャッシュするような横暴はしなそうですから、これは一般的に通用する解決法と思います。

開発:というかそもそも、今どきのサーバでも普通に .cgi が使えるとは知りませんでしたけどね。

基盤:Go の処理系も持ってきてみますかね。さすがにカーネルの版が遠すぎるのが不安ですが。

開発:そうですね、いずれ手が空いたら試しましょう。

-- 2020-0703 SatoxITS

CGIでうっかりエラー

社長:今ポインティリスムで打刻しようとしたらこんな事になってしまいました。

開発:あれ?昨日から何も変えてないと思うんですが。しかし、ソースを見ればわかるとは言え、適当に書いたソースが直にこう出てきちゃうと恥ずかしいですね。

基盤:HTTP DeleGate のログにはこう出ています。

開発:ああ、その文字列はCGIの標準出力に吐いた記憶があります(笑)。なるほど、HTTPヘッダを吐くより前にエラーメッセージを吐いちゃったということか。

社長:CGIではそういうことをしちゃいがちでしたね。

基盤:何のエラー?

開発:((bad-XY)) と出しているのがDeleGateのログに記録されていますが、要するにHTTPリクエスト・メッセージ中の x, y 座標情報が変だ、特にこの場合には情報が無いというエラーです。キャンバスをクリックしてこのページを呼んだ場合でないと、そうなります。エラーというより、単なるテスト・デバッグ用の情報です。

社長:CGIでは、ヘッダだろうがボディだろうが、一連のストリーム出力でしか無いという事ですね。

開発:何にしても私は、ページ全体を作るのには今どきCGIではいかがなものかという気はしますが、個別部品を作るぶんにはCGIで全然問題ないと思うんです。

社長:ページ固有なCSSを生成するぶんにも問題ないですね。

開発:できることが基本クライアントとの情報交換だけで、自分の実行環境のことを知らないから、逆に環境独立というか、どこに持っていっても動くという強みはあるかなと思います。

社長:インタフェースは最少最小が良いという原則でもありますね。

-- 2020-0703 SatoxITS

WordPressでぞっとするエラー

基盤:ダッシュボードでこういうのが出ました。

ダッシュボード

基盤:編集状態のウィンドウではこういう状態になっています。

投稿編集

開発:同じようなエラーが、XSOで http と https を切り替えた時に出ましたね。ぞっとしました。

基盤:タブを複製しても出ます。ところが、新規にウィンドウを作って同じアドレスにアクセスすると、このように問題なく表示ができるわけです。

新規ダッシュボード

開発:Cookieの違いですかね。ウィンドウ毎に別のものを持っているんでしょうか??

基盤:それで、各ウィンドウでクッキーを見ると、このような違いがあります。

基盤:Cookieを覗いてみると、一つは wp-admin のセッション情報で、これを削除すると当然ログアウト状態になりました。面白いのは、それによって他のウィンドウのCookieも更新されたのです。

基盤:でこの状態でリロードをすると、エラーを表示していた画面が回復しました。

ダッシュボード
投稿編集

基盤:この状況から考えると、問題は2つ。一つは、WordPress が不適切なエラーメッセージを返している。特にedit.php においては、単に必要な Cookie が無いことが異常の根源だと思うのですが「PHPがー、MySQL がー」異常だと、人を恐怖に陥れるデマのような返答をしてくる。index.php にしてもそうです。要は Cookie が腐ってるということでは無いかと思いますが、その可能性について検討も言及もしていない。

基盤:もう一つの問題はVivaldi側。Cookieの更新やタイムアウトをウィンドウ間でシェアするところに不具合があるようにも思われます。まあ、エンドユーザ側のフロントエンドはあらぬ嫌疑をかぶる被害者であることは多いですが。

社長:放送側の問題であっても、映らんといってテレビ受像機がガンガン叩かれてたり。

開発:システムからのメッセージというのは非常に重要ですね。特にエラーメッセージは。

基盤:XSOの「失敗しました。」は傑作でしたが。

社長:そこのところが、有史以来ないがしろにされている感がずっとするのです。正常系は作るけど、異常系の手当に力が入れられていない。もっとも、想定外の異常は正常の場合よりはるかに広いでしょうからわからなくもないのですが。

開発:我々的にはログを見ればなんとかなる、ならまだ良いのですが、ログすらちゃんと提供しないシステムやツールは多いですからね。

社長:まあ、プログラムを書く時に異常処理を書き始めるとごちゃごちゃ膨らんでしまって嫌だというのはあるんですが、あのあたりを自動化して、しかもエンドユーザにわかるレベルのエラーメッセージを生成できたら、すごいことだと思いますね。

-- 2020-0703 SatoxITS