PSQL Windows ODBC Linux SQL 接続

要約:
DB MagicのBtrieveファイルをPSQLを介して、LinuxのPHPからODBC経由で読み書きできる
なかなか苦労したので、こんなことやる人少ないだろうけど、記しておく

前置き

DOS時代から聞いたことがあったBtrieveというファイル内DBの仕組み。固定長データベースですからなかなかとっつきにくいし、Windows時代になって長いこと過ぎて、既に使われていないのでは…と思ったら結構あるもんですね。DB Magic(UniPaaSを経て今はMagic XPA)で採用されてるからかな。

で、そのBtrieveファイルをもとにSQLとして扱える仕組みが提供されており、だったらPHPからBtrieve読み書きできたりしちゃうんじゃないのーということで、そういう話が始まりまして、結構苦労したので記します。日本語のソースもあんまりなかったし。

Btrieveを使ったDBMSとしてActian PSQLというのがあります(以前はPervasive PSQLでした)。このPSQLエンジンがあれば、バックエンドはBtrieveですが、SQLを使って問い合わせができます。
そしてさらにPSQLはODBCインターフェースを提供しているので、Windowsはもちろん、LinuxでもODBCドライバが存在しています。

ということでWindows側でBtrieve、PSQL、ODBC、Linux側でPSQLドライバ、unixODBC、php-odbcと重ねていくことで、PHPからWindows上のPSQLエンジンを利用することができるわけです。

Windows側の準備

Actian PSQLをセットアップすると大体入ってます。Magic XPA付属のPSQLでも入ってました。適当にBtrieveファイルをもとにPSQLが利用できるようです。

Btrieveデータファイルだけがある状態ではSQLは利用できません。
PSQL Control Centerから「データベースの作成」を行い、データパスにBtrieveデータがあるフォルダを指定してやります。
さらにPSQL DDF Builderを起動し、作ったデータベースのデータパス内から使用するデータファイルを探し出します。そこで右クリック「テーブル定義の作成」です。

Btrieveファイルは固定長データベースですが、デリミタがありませんので、あらかじめ「Xバイト目からはYというフィールドで型がINTEGERだから4バイトです」という定義が必要なのです。データファイルがあるだけではPSQLはこれを知りませんので、定義を別途作ってPSQLに読ませます。この作業をするのがDDF Builderです。きっとData Definition Fileかなんかの略です。

DDFができたらPSQL上でテーブルが扱えるようになっています。初回開くとインデックスが作成されたりしてRDBMSっぽいです。スキーマをエクスポートしておくと、他の環境にデータファイルを持っていった際にDDFをインポートするだけで動くようになります。
ちなみにスキーマの頭には CREATE TABLE “hoge” USING “hoge.dat” なんて書かれていて、ああファイルに対するテーブル定義なんだなぁと確認できます。

WindowsのODBCデータソースからPervasive ODBC Unicode Interfaceなんかのドライバを使ってDSNを作れます。フリーソフトのcse(Common SQL Environment)などで接続すると、DB内にDDFで定義されたテーブルが存在しているように見えるのがわかります。

PSQLはTCPポート1583で動くらしいので、他のマシンからアクセスさせるためにファイヤウォールの解除をしておきます。いまどきはポート指定じゃなくてPSQLエンジンのプログラムを指定したほうがいいんだろうけど、やってないからわかりません。

Linux側の準備

今回はCentOS8上でApache+php-fpmを用意してましたのでこれでやります。
CentOS8上にあるApache2.4はmod_phpじゃなくてphp-fpmを使うようになってますのでそのへんセットアップしておきます。
Apache2.4はデフォルトで全体がdenyされているのではじめてセットアップするとforbiddenの嵐で大抵ハマります。

とりあえずパッケージとして php-odbc unixODBC あと使う人は php-pdo 他使うモノを入れておきます。

Linux用のPSQL Clientをダウンロードしてきます。
PSQL v12 SP1 インストール用ファイル(ダウンロード情報)
64bit Linux rpmをインストールします。あっさり終わりますが、環境設定は自前でやる必要があります。

psqlユーザーが作られているので、~psql/.bashrc に書いてある環境変数をコピーしておけばrootでも動きます。なんかごちゃごちゃ書いてありますが、元のPATHが消えたりしてて困るので必要そうな部分だけコピーして書き直します。

export PVSW_ROOT=/usr/local/psql
export PATH=$PVSW_ROOT/bin:$PATH
export LD_LIBRARY_PATH=$PVSW_ROOT/lib64:$PVSW_ROOT/bin:$LD_LIBRARY_PATH
export MANPATH=$PVSW_ROOT/man:$MANPATH
export BREQ=$PVSW_ROOT/lib
export LD_BIND_NOW=1

PSQL ClientにDSN追加を命じます(内部的に何をしているのかわからんけど、少なくともodbc.iniファイルを置くだけではダメなのでコマンド実行は必須のようです)
# dsnadd -dsn=MYDSNNAME -db=DBNAME -host=WindowsHostIP
/usr/local/psql/etc/odbc.ini が作成されるので、これを /etc/odbc.ini に追記しておきます。
また /usr/local/psql/etc/odbcinst.ini を同様に /etc/odbcinst.ini に追記しておきます。

お気づきかもしれませんが、PSQL関連の環境変数がないとPSQL ClientおよびODBCドライバは動作しません。なのでphp-fpmに環境変数を渡す必要があります。
CentOS8ではphp-fpmはsystemd経由で動いてますので、 /etc/systemd/system/php-fpm.service.d/ の中に pvsw.conf とでもファイルを作成して、環境変数を渡してやります。

[Service]
Environment=LD_LIBRARY_PATH=/usr/local/psql/lib64:/usr/local/psql/bin:/usr/lib Environment=PATH=/usr/local/psql/bin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:/sbin:/usr/sbin:/root/bin
Environment=PVSW_ROOT=/usr/local/psql
Environment=BREQ=/usr/local/psql/lib

設定ファイルの変更ということになるので
# systemctl daemon-reload
# systemctl php-fpm reload
しておきます。

ここまでで準備完了です。適当にコードを書いて走らせてテストしましょう。

$conn = odbc_connect('MYDSNNAME', '', ''); // user/passは空で良い
$odbc_q = odbc_exec($conn, "SELECT * FROM sometable;");
$odbc_r = odbc_fetch_array($odbc_q);

なお、Windows側は文字コードがsjisですので、SQL文は適宜mb_convert_encodingなどしてやる必要があります。文字コードが適切なら日本語カラム名もクォート等なしで通るようです。

CentOS8にはOpenDKIMがないのでEPEL7から拝借

愕然。しかもググっても日本語情報がない。
このためだけにCentOS7に入れ直そうかと思っちゃった。

CentOS8になってsendmailが削除されたのだが(もともとpostfix推奨)、OpenDKIMはsendmail-develに含まれるmilter関係のコードが必須で、それも削除されちゃってるもんだから無いという理屈のようです。英語の掲示板ではOpenDKIMをソースから構築しようにもsendmail-develがねぇじゃんという書き込みがありました。

ならばOpenDKIMが含まれるCentOS7用のEPELから入れればいいじゃないかというので実施。
CentOS 8: Not Ready for Prime Time Mail Server for Us!

※CentOS8ですがまだ慣れてないのでyum使ってます
# yum remove epel-release
↑8.xが削除される
# yum install https://download-ib01.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
↑7用EPELを導入
# yum install opendkim
↑OpenDKIMを導入
# yum remove epel-release
↑7.xが削除される
# yum install epel-release
↑再度8用EPELを導入

警告も出るのでこれがそのまま使えるとは限りませんが、とりあえずOpenDKIM設定して起動はできたし署名もつきました。

ちょっと他のサーバーでは使いづらいな…

CentOS8で名前解決できない(RTX830の下)

新規環境でCentOS8を入れてみたら、名前解決ができない。
digコマンドをたたいてもFORMERRと出て解決できない。
mxが引けないのでメールが送れない…

LAN内でのIPv6が悪いのか?などと思ったが違った。
dig +noedns example.com と、+noednsをつければ引ける。

EDNS、EDNS0という拡張プロトコルで問い合わせをする方式。
digコマンドでは+noednsによってEDNSを使わないで問い合わせする。

つまり、このCentOS8の上位のネームサーバーがEDNSに対応していないことが問題だった。
となれば疑うは上位のルーター。今回はYAMAHA RTX830。

27.4 DNS サーバーを通知してもらう相手先情報番号の設定

ばっちり、ファームウェアアップデートでEDNS対応していた。
Windowsからtftpでrtx830.binを送ってやる。

アップデート完了後
dns server pp 1 edns=on
と設定し、CentOS8側でも名前解決できるようになりました。

NEC Lavieのレスキュー、リカバリ PC-LS150BS1TB

古いPCでも未だに使えている方はたくさんいらっしゃって、Windows7にOfficeでたまに文章を作りするだけならば10年前のパソコンでも十分だったりするのでしょう。
しかしセキュリティやらなんやらを考えたら、このへんの世代のPCなら非対応パーツもそんなにないでしょうし、Windows10にアップグレードして使い続けるのが良い選択しかもしれません。

で、私の手元に依頼されたPC-LS150BS1TB、LS150/Bという機種ですが、2010年6月発売。Windows7 Homeの32bitと64bitが選べる時代のもの。
Windows10にアップグレードして数日使っていたら、ブルースクリーン(Windows10のブルースクリーンはQRコードとか出るんですね!)で起動できず、ntfs.sysがおかしいとか出てくる。

こりゃHDDの故障かなーということで、このHDDは取り外し、リカバリすることに(NECはリカバリと言わずに再セットアップというらしい)。
しかし!持ち主はリカバリディスクを作成しておらず、そしてWindows10にアップグレードしてしまったPCは起動時にF11やら押してもリカバリモードに入れないのだとか!

240GBのSSD。今どき5千円もしない。

途中さまざまな試行錯誤をしたものの、最終的には下記の手順でレスキュー。
・新SSDを装着
・旧HDDのリカバリ領域の中身をコピー。Windows REとNEC-RESTOREの2つの領域があるので、どっちも
・急場しのぎの仮リカバリディスクを作成、工場出荷時に戻す
・ディスク作成ツールで本来の再セットアップディスクを作成
・リカバリ領域なしで全部Cドライブにして再セットアップ
・Windows10へアップグレード
・旧HDDのユーザー領域からデータをコピー、レスキュー

リカバリ領域から再セットアップディスクを作るまで

Windows RE領域もNEC-RESTORE領域も、普段は見えないのだが、これはドライブレターが割り当てられてないためにそうなっているようだ。
とりあえず読めれば良いので、USBメモリにUbuntuを入れてそこから起動、各パーティションの中身を他のUSBメモリにコピーして、別PCに持っていく。

再セットアップディスクはDVD-Rで4枚になるはずだが、とりあえず適当に分割。
disk1には boot、EFI、sourfces、TOOLS32、TOOLS64、bootmgr、BKW7_32.GHO、BKW7_64.GHOを入れておく。
disk2以降はGHSファイルだけ入れておき、最後のディスクにもsources、TOOLSは入れておく。
中身はノートンゴーストなんですねぇ。

Windows PEの起動ディスクを作るための環境を整える。Windows ADKをインストール。
Windows PE (WinPE) – Windows 10 hardware dev
「展開およびイメージングツール環境」を起動し、disk1を起動できるように作る。

Tools>oscdimg -u1 -bC:\LS150B\disk1\boot\etfsboot.com c:\LS150B\disk1\ c:\LS150B\recovery1.iso


OSCDIMG 2.56 CD-ROM and DVD-ROM Premastering Utility
Copyright (C) Microsoft, 1993-2012. All rights reserved.
Licensed only for producing Microsoft authorized content.
Scanning source tree
Scanning source tree complete (224 files in 24 directories)
Computing directory information complete
Image file is 2071724032 bytes
Writing 224 files in 24 directories to c:\LS150B\recovery1.iso
100% complete
Final image file is 2072229888 bytes
Done.

このisoイメージをDVDに焼いて1枚目とする。2枚目以降はただのファイルコピーなのでisoにする必要はない。

この仮ディスクでSL150/Bを起動すると、再セットアップが始まった。
途中で何度かディスクの入れ替えを要求されるが、中のファイルが見つからない場合は全てのディスクで試してみれば、そのうち当たる。


最後のディスクにTOOLSが必要なのは、ノートンゴーストを起動するためなんだろうなぁ。

HDDからSSDでスピードアップするとまだ全然使える気にになりますね!
ということであとは特にトラブルなくインストールが進みました。

Windows7インストール用USBメモリを作る

Windows7機のリカバリの際にWindows7のインストールが必要になり、手元にISOはあれどDVD-Rが無い、ということでUSBメモリからインストールすることに。

Windows 7のインストールUSBメモリを作る(Windows 7 USB/DVD Download Tool編):Tech TIPS – @IT
作成自体は参考記事の通りでできる…はずなのですが、最後に「bootsectを実行できませんでした」とエラーが出でしまう。

Windows 7 のUSBインストーラ作成 ( Windows ) – Web備忘録 – Yahoo!ブログ
bootsect.exeをツールと同じフォルダに置けば良いということだが、やはりうまくいかない。

コマンドプロンプトを管理者権限で起動して、そこからbootsectを実行する。/helpで内容を見れば使い方が書いてある。今回はWindows7(64bit)のインストーラを作成しているので/nt60で

bootsect /nt60 E:

これで無事起動できました。

それにしてもUSBメモリは人に貸したりしてるうちにどっかに行ってしまうもので。
16GBぐらいのメモリはOSインストールにお手頃なので複数買いしておきました。