WSL(Ubuntu)-PHPからSQLServerへの道のり

2019年5月20日 若干修正


「CentOSからWindows上のSQLServerへの道のり」のつづきです。

LinuxからWindows上の SQLServerへのアクセス方法については、世間的にはあまり需要がないのでしょう。まぁ、Linuxとかのunix系のOSでは、SQLServerなんて採用しないし、逆も然り。。。困ったもんだ。。。

さて、Linuxの各ディストリビューション用のMicrosoft製のODBCドライバが提供されていて手順を踏むと、LinuxからSQLServerへODBC経由でアクセスすることができました。

今度は LAMP環境、PHPから文字化けさせずにCRUDすることができるか、ウェブアプリケーションをちゃんと実装できるか、確認です。とりあえずLinux各ディストリビューション用にマイクロソフト製のODBCドライバをインストールしていることが前提です。

PHPでたとえば、以下のようなコードでテーブルを作成し、SQLServer Management Studioとかで確認すると、日本語が全部文字化けします。
sqlcmdコマンドで日本語交じりのSQL文を発行すると化けないので、おそらく、PHPの問題でしょう。DSNで odbc: を使うのがだめなんでしょうね。odbcドライバをインストールしたんだから、当然odbcプレフィックスを使うものだと勘違いしてまして、これが罠でした・・・。日本語関係の処理が全くされない。。。この辺、よくわからん・・・。知識が圧倒的に足りない。SQLServerのODBCドライバとsqlsvr(PHP SQLServer用のドライバ?)の関係が全然わからない。PHPのマニュアル見てもよくわからない・・・。

// これが間違い
$pdo = new PDO('odbc:Driver={ODBC Driver 13 for SQL Server};Server=localhost;Database=Sample','dbuser','dbpass');
$pdo->exec('CREATE TABLE tbl_hoge(hoge_id int NOT NULL,hoge_txt nvarchar(100))');
$pdo->exec("INSERT INTO tbl_hoge values(1,N'日本語で挿入・・・なんかエロいな')");

接続文字列でエンコーディング関係のパラメータがあるのかなと、調べてみたけどないっぽい。さらにネットでの情報がほとんどなく。。。ヒットするのはFreeTDSを使ったものばかりで、多くはPHP5の情報ばかりで、PHP7以降のものは出てこず。。。

で、困ったときはグーグルで検索・・・ではなく、まずマイクロソフトの公式のドキュメントを漁りましょうってことですね(^^;
ググらなくても最近のマイクロソフトはちゃんとドキュメントを用意してくれてます。(MSも変わったな。。。)

Build an app using SQL Server


上記サイトの PHP ⇒ UBUNTU をクリックすると、Linux版 SQL Serverのセットアップから詳細な手順が書かれています。英語ですが、簡単な英文なので読みましょう!英語は喋れなくても、聴き取れなくても一向に問題はないけど、英語の読解能力は必須!ちゃんと読めるようにしましょう!!!
日本人がいくら優れたシステムを作れたとしても、英語で説明できなければ、世界には通用しませんし、この先世界中の開発者がこぞって日本語を理解してくれるとは到底思えないからです。

今までSQLServer用のODBCドライバとPHPでのSQLServer用のドライバ、それぞれが別々に説明がされてて、一体何がどうなってってるのか理解できなかったけど、上記サイトで Ubuntu + PHP では、この手順、Redhat系では、この手順、という風にまとめて手順が説明されているので、これで悩まなくて済むようになった。PHP7以降限定ですけどね。 まぁPHP5系はこの先消えていく(deprecated)のでまぁいいか、という感じ。

要するに ODBCドライバに加えて、peclでsqlsvr/pdo_sqlsvrをインストールすれば完了。やっと 非Windows環境でも労せずSQLServerへフツーにアクセスできるようになりました。

上記マイクロソフトのサイトには、Linux用のSQL Serverのセットアップから説明されていますが・・・SQLServerは Windows用のものをインストールしましょう。というか、開発マシンがWindowsの場合は、素直にWindows用のSQLServer Developper Editionをインストールした方がいいです。開発目的ならライセンスフリーですし。(サーバー環境で運用はできないけど)
開発マシンがMacやLinuxの方は・・・そもそもSQLServerに接続するような仕事してないでしょ?w

WSL(Ubuntu)でPHPをインストールしていない場合、aptで適当にphp7系をインストールしてください。その際、php-dev パッケージは必須です。
また、最新のsqlsrv,pdo-sqlsrvドライバはphp7.0をサポートしないので、最新に拘る人はphp7.1以上にするべし?php7.0をサポートするMicrosoftのsqlsrv/pdoドライバのバージョンは5.3です。最新は確か5.6だったかな?
システム要件:https://docs.microsoft.com/ja-jp/sql/connect/php/system-requirements-for-the-php-sql-driver

$ sudo apt install php php-cli php-dev php-... (必要なパッケージ)
# apacheで動作するには必要
$ sudo apt install libapache2-mod-php

1, 先に マイクロソフトのサイトからODBC Driver for SQLServer をインストールしておく(上述)

2, sqlsrv/pdo_sqlsrv のインストール (ubuntu 1804 の場合)

$ sudo apt install php-dev
$ sudo pecl install sqlsrv
$ sudo pecl install pdo_sqlsrv
$ sudo su 
# echo "extension=pdo_sqlsrv.so" > /etc/php/7.2/mods-available/pdo_sqlsrv.ini
# echo "extension=sqlsrv.so" > /etc/php/7.2/mods-available/sqlsrv.ini
# exit
$ sudo phpenmod -v 7.2 -s ALL  pdo_sqlsrv sqlsrv

apache2な人は再起動するべし。
参考リンク:the installation instructions on Microsoft Docs.

3, PHPで確認
PDOで、DSNのプレフィックスをodbc: ではなく sqlsrv: で。

$pdo = new PDO('sqlsrv:Server=localhost;Database=Sample','dbuser','dbpass');
$pdo->exec('CREATE TABLE tbl_サンプル(hoge_id int NOT NULL,hoge_txt nvarchar(100))');
$pdo->exec(sprintf('INSERT INTO tbl_hoge values(1,N%s)',$pdo->quote('日本語で挿入・・・なんかエロいな'));

参考リンク: https://github.com/Microsoft/msphpsql/tree/master/sample

文字列リテラルをNプレフィックスをつけずにINSERTとすると絵文字が化ける。文字列リテラルの場合は Nプレフィックスを忘れずに。。。
ただ、プリペアドステートメントを利用する場合、自動的にNプレフィックスはつけてくれるみたい。SQLServer Data Profilerで実際実行されたSQL文を確認すると、PDO::execでは自動的にNプレフィックスはつけてくれないみたい。まぁ当たり前といえば、そうなんだけど。。。

あと、東京オリンピックまでには、apt install php-sqsrv / yum install php-sqlsrv とか標準のリポジトリでインストールできるようにしてほしい。。。

\(^o^)/

前途多難な、ぼっちWEBシス担のグッチ―

他所の部署で、取引先のシステム制作会社と共同で開発されていた、とある(半分w)ウェブアプリのリプレースを突然?指名され担当になる。。。よその部署なのに・・・。

とはいえ、昔僕が健康面で悪い時に、見放さずお世話になった経緯もあって、むげに断るのもどうかとも思い、引き受けたはいいけど・・・取引先寄りの前担当者からは「こんなやつに!」と猛反対されつつも、昔お世話になったんだからと・・・手を差し伸べて助けよう、と首を突っ込んだけど、まさかの、その差し伸べた手を振り払われて当惑している、ぼっちウェブ担です。

共同で開発した、というと聞こえはいいが、そう安くは無い金額の開発資金をこちらの会社が出し、両者で勉強しながら(大笑)、開発してもらう、とかいう、滅茶苦茶ぶり。
OSがWindows10になり、当然ながら開発当初主流だったInternet Exporerは、マイクロソフト自身「もう使うな!」との詔(みことのり)を発せられたInternet Explorer以外のモダンブラウザに対応してくれ! と、そのシステム会社に依頼するも「できない、むずかしい」と言われ、会社の上層部からは「追加のお金は出せない」と宣告され、にっちもさっちもいかなくなって、おいらにお鉢が回ってきた。まぁ、要するに信用がないんだな(^^;;;

その共同開発wしたという、システムをみた感じ、「これでよく、ウェブシステム」と言ってたな!という有り様。なんと、フル機能を使うには、開発した専用ウェブブラウザが必要!、さらに、エクセルのインストールも必須! という、ありえないものだった。

ローカルディスクにアクセスしないといけない、プリント機能もなぜかエクセルが必要、Accessで組んだ業務アプリをウェブシステムに置き換えるとき、真っ先に切らないといけない仕様を、全部盛り込もうとするから、専用ウェブブラウザとかいう、謎のアプリの配布が必要になってくる。まだ中身を見てないから何ともいえないけど(出し渋ってるので)、おそらくIEのウェブブラウザコントロールを貼り付けて、必要な機能を付けたしたアプリケーションだと思うが・・・。

この際だから、好きなようにやらせてもらおうと、いろいろ実験(笑)をしながら組んでいこう。
考えている構成は・・・

Windows Server 2019 + SQLServer + Hyper-V ( CentOS7 / httpd)

ホントは全部 CentOS7 + MySQL という構成が僕も扱いやすいのですが・・・社内的に Windows しか認めてくれない雰囲気。
時間がもっとあれば、C# とかで組みたいけど、半年ぐらいしか時間がないので・・・手っ取り早く言語はPHP。

いや待てよ、PHPで組むんだったら、

Windows Server 2019 + SQLServer + WSL (UBUNTU / Apache2)

でもいいんじゃないか? HyperVと仮想マシンで組むより、オーバーヘッドが少ないかもしれない。WSLはまだ開発途上でこの先マイクロソフトがどのような展開をするのか不明な点もあるし。Windows10のようなクライアントOSだとWSLはウェブ開発ツールの一つと捉えることができるが、 Windows Serverでの WSLの立ち位置がイマイチどのように考えているのかわからない。

Windows向けの PHP と IIS いう構成も考えてみたけど、なんせ過去の経験から IIS + PHP はどうにもこうにも扱いづらい。特に IIS の なんちゃらプールIDとかなんちゃらプロセスとか・・・アクティブドメインがなんちゃらとか、Windows認証がなんちゃらとか、全く理解不能の用語連発で嫌になる。

それだったら、HyperVで仮想マシン作ってそこにシステムを作りこめば そのVHDをピーコするだけで、実稼働できる、という手軽さを選んだ。
すこし前から、HyperVで内部用の仮想スイッチでネットワーク組んでも、NAPTで仮想スイッチを組めば内部のネットワークにぶら下がっているゲストOSにポート変換で外側からアクセスできる。だから 外側のIPアドレスも消費しないし、完全に環境を封じ込める。

今の懸念材料としては、 この構成で実運用に耐えるのかな・・・と。。。Azure運用だと金さえ積めばいくらでも性能アップできるんだが・・・オンプレミスでやるのは経験がないので正直怖い面もある。

Inconsolata + BIZ UDゴシック

新しい iPad Pro 発表されましたな。
1TBのやつが欲しいけど、さすがに18万は高いなー、

閑話休題

Windows10 1809(October 2018 Update) から BIZ UDフォントが標準搭載されたので、gVimで試す。
ASCII文字(guifont)を Inconsolata、日本語(guifontwide)をBIZ UDゴシックに設定しましたが、なかなかイイ感じです。


(全景)

エディタによって BIZ UDフォントを指定すると、半角英数の文字幅が強制的に2倍になってしまって悲しい感じになるんですが・・・これどーすればいいの???(^^;;;

ごーごごー

Surface Go、社内販で買いました。Officeなし版を買うには会社で買うしかない、ということで仕事で使うという大義名分で(実際に仕事でも使うが)注文してもらいました(^^;

今はほとんど見向きもされないSurface3のリプレースです。
会社では 常時 OneNoteを立ち上げて、完全にメモ帳用途で使ってるので、Surface Goのサイズ感と絶妙のCPUチョイスがハマって、Surface3を捨て速攻で買い替えです(^▽^)/

最近知ったんですが、アメリカの Amazon でもカートに入れると日本円で表示される仕様になってるっぽい(設定する必要はあるが)。日本のAmazonアカウントのまま、アメリカのAmazonでカートに入れた商品の決済画面に進むと配送先(Delivered to)が自動的に日本のamazonアカウントで登録されている住所になり、「クレジットカード番号を入れろ!」 画面がフツーに出るやん・・・。
日本では英語配列のタイプカバーはブラックのみなので・・・アメリカのamazonで買おうかなー、と思ったけど・・・アメリカからの送料とか配送期間とか考えると高くなるのでやめた・・・・

ってなことはさておき・・・
かねてからメモってた Surface Go買ったらやることリストを遂行

  1. WSL有効に & Ubuntu インストール(サーバー関係、ツール/ビルド関係
  2. 仕事環境インストール(gVim/chrome/FireFox/Visual Studio/Adobe Illustrator/Photoshop/ネットワークツール)
  3. そのままだと英語配列のキーボードが日本語配列として認識されるので設定変更
  4. キーボードドライバを101ドライバからAXキーボードドライバに変更(IMEトグルを右ALTキーに)
  5. タイピング環境構築 xkeymacsインストール、CAPS⇔CTRL入替)
  6. タッチパッドの設定で「シングクリックするには1本の指でタップします」のチェックを外す
    タイピング時の親指での誤タップを抑止

んで、僕的にいいところ、気に入らないところを列挙。

Surface Go のいいところ。

(1) まず何より小さい!
久しく使ってなかったカメラバック、Retrospective5 に入れてみる・・・

入るやん!!! これから通勤用のバッグにしよ。。。

(2) Surface Pro 譲りのつくりがイイ!
Windows Hello 対応のフロントカメラと、無段階で角度を調整できるキックスタンド、Surface ProのPenが使える。
Surface Penの書き心地がかなり良くなってることに驚いた。もうちょっと引っかかり(抵抗)があっても良さそうだけど、ツルツルで滑って書きにくい・・・ということはない。イイ感じ。

(3) 充電ポートが二つ!
付属している充電コードとアダプタは一体化されていて Surface Connectポートにつないで充電する仕様。しかもこのアダプタが微妙にデカいので・・・こんなの持って歩けないよ・・・ってな人は USB Type-Cのコードさえあれば USBポートから充電できてしまう!(問題点あり後述)

(4) Atomプロセッサじゃない!(^^;
Core i3 には及ばないけど、まずまずの性能。ブラウザとかオフィスソフトはフツーに使えます。
というか、この機種で性能を求めるのはアホの所業ですが、正直 Atom プロセッサは遅すぎた。。。
普通に動画もサクサクみれますし・・・でもクリエイティブ系のソフトは動けばいいや、的な感じ。
Visual Studio 入れたいけど・・・普通に使えるのかな??? Autumn Updateと同時に今度入れてみよう。

(5) ストレージの性能が良すぎ?
8GB/128GB版のSurface Goのストレージは SSD。特にシーケンシャル・リードが1GB/s 越えてます・・・。ライトはフツーなんですが・・・リード性能が飛びぬけて良いみたい。

(4)と(5)からすると、CPU(Pentium Gold)がそこそこの性能でも、SSDとCPU内臓のGPUのパフォーマンスの高さでカバーしてるから、そこそこ使えている感じがする、というのが実情じゃないかと・・・

でもPhotoshopとかのAdobe ソフトも起動の速さはそこそこ普通。起動にもっと時間がかかると思ってたけどいい意味で裏切られた感じ ^^

で・・・今度は気に入らないところ

(6) タイプAの普通のUSBポートが欲しかったな・・・。
Appleとかだとレガシーになりそうなものはバッサバッサと切っちゃうんだけど、マイクロソフトはそういうのやめて欲しいな・・・というのが正直な感想。死守して欲しかった。。。
せめて、USB Type-AとType-Cの変換アダプタ一個ぐらい標準付属品にして欲しかったな。

(7)タイプカバーの英語配列を日本でもフツーに売れよ!
Surface Proでもそうなんですが、日本ではタイプカバーは基本的にJIS配列ものしか商流にのらないです。英語配列のものがありますが、カラーバリエーションがブラック一つのみ。日本で英語配列が売れないの分かりますが・・・せめてマクロソフトの直販サイトでは全てのカラーバリエーションで英語配列をラインナップにそろえて欲しい。

(8)シャットダウンするとUSB Type-C経由の充電はできない!
起動中もしくはスリープ状態でないとUSB充電はできないみたい。そもそもSurfaceはシャットダウンするな! ってことなんでしょうね・・・。

(9) タイプカバーのキーピッチがやっぱり狭い・・・
まぁ、これはサイズ的にはしょうがない。僕の癖なのか、キーピッチが狭いと T と Yの打ち間違えが頻発・・・なかなか指が補正できない・・・これは慣れていくしかないな・・・。

2~3日使ってみてこんな感じかな・・・。とりあえず、USBケーブルをほぼ全部買いなおし or 変換コネクタを買いにいく。Type-Cのハブを買った方が安くつく感じだな・・・。

gvim(+kaoriya) + WSL Part3

:prev の続き

※この内容は事前に Part1で記述したように shell,shellcmdflagとかの変数をWSL用に変更する必要があります。

とりあえず、gVim(+kaoriya) と WSLの連携をある程度スムーズにできるようになりましたが、問題が一つ発生。
ローカルドライブだと問題はないのですが、リムーバルディスクとかネットワークドライブだと、WSL内の /etc/fstab に記述して自動マウントしてても、Windows10アプリケーションからWSLに移行した時点でカレントディレクトリが引き継げません。

ネットワークドライブを ドライブレター(Z: とか)にアサインして、cmd.exeで cd /d z: としてカレントディレクトリを変更し、bash.exe(or wsl.exe)しても、ホームディレクトリに飛ばされます。。。
カレントディレクトリを引き継いでくれるのは、c:ドライブとか、ローカルハーディスクだけのようです。ディスクタイプによって判断しているんでしょうか・・・。

これが一番困るのは、:grep コマンド。:grep コマンドの結果をQuickFixで開けるようにしているけど、カレントディレクトリ以下でローカルドライブだとなんとか使えるけど、リムーバルドライブとか、ネットワークドライブだと、パスの関係で全滅。WSLのフルパスで検索対象を渡せば grep は機能するが、QuickFixウィンドウに表示されるのはWSL側のフルパスなので 当然 gVim ではそのパスが理解できないので、結局使えない。

解決方法は、3つ。

(1) :grep をあきらめ、:vim(grep) で代替。
  ⇒ (ネットワークドライブだと特に)遅い。常用できないほど遅い。

(2) Msys の grep.exe で代替
 ( _vimrc にて set grepprg=/mnt/c/Msys64/usr/bin/grep.exe\ -n

  ⇒ WSLのみでなんとかする、という最初の趣旨から外れてしまうが・・・しょうがない。

(3) WSL側に grepの結果からパス名部分を変換するフィルタスクリプトをかます
 ( _vimrc にて set grepprg=grepwsl\ -n

  ⇒ ネットワークドライブ内のファイルを編集している時だけ検索パスをフルパス(WSL)を指定しないといけない。
  ⇒ また、若干遅くなるが、許容範囲内。。。WSLだけで完結できる。

というわけでとりあえず しばらく(3)を常用することにした。すでに Msys入れている場合は(2)の方が簡単かも・・・。ネットワークドライブのときだけ検索パスを絶対パスにする必要があるが、まぁしょうがない。

まずネットワークドライブ(例: Y)をドライブレターにアサインし、 sudo mkdir /mnt/yでディレクトリを作成し、/etc/fstabに登録する。

# /etc/fstab
LABEL=cloudimg-rootfs   /        ext4   defaults        0 0
Y: /mnt/y drvfs defaults,noatime,uid=1000,gid=1000 0 0

WSL側のpathが通っているところに(たとえば /usr/local/bin/ とか)grepwsl を作成しsudo chmod +x /usr/local/bin/grepwsl

#!/bin/sh
##############################################################################
#  wslgrep  .... WSLに入っているwslpathコマンドを使用してパスを変換 
#  2018/08/29 絶対パスに変換するオプション(-a)を追加/正規表現ちょい修正
##############################################################################
grep $@ | perl -pe 's/^([^:]+)/`wslpath -m -a $1 | tr -d "\n"`/e;'

これは単にgrepの結果を perl に渡して変換処理をしてるだけ。sedでもawkでもなんでも。単にperlに慣れているだけ。

んで、~/_vimrc に追記

;;; ~/_vimrc
set grepprg=grepwsl\ -n

ってなけで、とりあえず、なんとかなった!(^^;