レンタルサーバiClusta。PerlでDB（MySQL）接続

## はじめに
GMO社が運営しているiClustaというレンタルサーバ（旧アイル）で運用されているサービスを触る機会がありました。

[iCLUSTA+｜GMOクラウドのレンタルサーバー（旧アイル｜iSLE）](http://shared.gmocloud.com/)

レンタルサーバということで、telnetやsshではサーバにログインできませんし、webのインタフェースでDB操作することも可能ですがSQLを直接書けるわけでもないし手動で手間がかかります。

そこで、cgiを書いてブラウザやtelnetで叩くことになります。
その際にDBに接続する方法にハマったので記録を共有しておきます。
（2015年になってもcgiかよ的な声もあるかと思いますが、一部ではまだまだ使われております）

## 環境
> OS：Linux
> ウェブサーバー：Apache2.2 をベースとしたカスタムバージョン
> PHP：PHP-5.3.17
> Perl-5.8.5
> Python：2.5.4
> Ruby：1.9.3
> MySQL：MySQL5.1

[iCLUSTA+のサーバーのスペック -FAQ](http://help.gmocloud.com/app/answers/detail/a_id/479/kw/%25E3%2583%2590%25E3%2583%25BC%25E3%2582%25B8%25E3%2583%25A7%25E3%2583%25B3/p/8)
（ただし、FAQ、ドキュメントは更新されていないものもあるので信用禁物。）


Perlのモジュールはすでに入っているもの以外は使えません。
iClustaの管理ページ（PLAN MANAGER）にログイン後、ユーティリティの[Perlモジュール検索](https://www.iclusta.com/util/pm/)より検索可能です。
メジャーどころは入っている気がします。

ちなみに、はじめは1.9.3とはいえRubyつかおうかと思ったのですがgemのアップロード、ローカルインストールが手間だったのであきらめました。


## スクリプトの書き方
### 接続先
- 管理ページ（PLAN MANAGER）にログイン後、ユーティリティからデータベース設定を開いてください。
 - [データベース設定](https://www.iclusta.com/util/db/)
 - 注意点は接続ユーザー名とデータベース名が同じことです（ここでデータベース名がわからなくて時間かかった、今見ればちゃんと書いてある・・）。
- 絶対パスは管理ページ（PLAN MANAGER）にログイン後、「個別ユーザー管理」 > 「ユーザー情報」の画面の ウェブ情報 の項目で確認できる。


### スクリプトサンプル
- Perlで書いています。ひさびさに使ってググりまくったのでコメント多めにしています。
 - DBIやPerlの使い方については適宜調べてください。
- まずは公式がわかりやすいです。
[DBD-mysql-2.1026 > DBD::mysql - perlcoc](http://perldoc.jp/docs/modules/DBD-mysql-2.1026/DBD/mysql.pod)

```perl:script.cgi
#!/usr/bin/perl

use strict;
use warnings;
use DBI;

## DBI モジュールの読みこみ
# データソース
## データベース名はユーザ名と同じ（数字、DB名は適当です為念）
my $database = 'DBI:mysql:database=abcdefghijklm;mysql123.in.shared-server.net:12345';

# ユーザ名（数字、DB名は適当です為念）
my $user = 'abcdefghijklm';

# パスワード（数字、DB名は適当です為念）
my $password = 'abcdefgh';

# 出力
## 相対パスの場合、スクリプトを置いているディレクトリに出力される
## 絶対パスの場合は、/home/vuser12/1/1/1234567890/ドメイン名/scripts/result.txtのように記述する（パスの確認方法は上で説明しています）
open(OUTPUT, ">", "result.cgi");

# データベースへ接続
my $dbh = DBI->connect($database, $user, $password, {RaiseError => 1, PrintError => 0, AutoCommit => 0 })
   || die "$!";

# SQL文を用意
## どこかから入力されるパラメータがあるならエスケープしてください。
my $sth = $dbh->prepare("select * from table_name where column = 'target';");

# SQLを実行
$sth->execute();
## allでとっていますが膨大なレコードを取得するのであればfetchrowなどで工夫してください。
my $ary_ref = $sth->fetchall_arrayref();

# 複数レコードをカンマ区切りで出力
for my $record (@$ary_ref) {
  print OUTPUT join(',', @$record) . "\n";
}

# ステートメントハンドルオブジェクトを閉じて切断
$sth->finish;
$dbh->disconnect;

# 出力ファイルをクローズ
close(OUTPUT);

# 最後までエラーがなかった場合にOKを出力する（デバッグ用）
print "Content-type: text/html\n\nOK.\n"; exit(1);
```

### CGIのデバッグ方法
- ローカルで同じバージョンの環境をつくってDBたてて、Perlとして動かす（Vagrantがたいへん便利です）
- デバッグ分 `print "Content-type: text/html\n\nOK.\n"; exit(1);`を挿入すると、ここまでは動いていると確認できる

詳細はこのページがわかりやすいです。
[CGIスクリプトをデバッグするには？ とほほのＷＷＷ入門 ](http://www.tohoho-web.com/wwwcgi7.htm)
（15年前のとほほ先生の記事に助けられるとは・・・


## 配置場所
まず、サーバにFTPで接続します。
ここでアカウント名に@ドメイン名がつくというのがわかりにく困りました。

testというユーザー名の場合下記の情報で接続できます。アカウントはサイト管理者である必要があります。
- FTPホスト名 ：　ftp.ドメイン名（DNSサーバー切り替え前はIPアドレス）
- アカウント名：　test@ドメイン名（メールアドレスの形式と同じです）
- パスワード　：　上記ユーザー用のパスワード

配置場所はどこでもいいですが、仮に、FTP接続した直下にscriptsディレクトリを作成しそこに置くものとして進めます。
注意点としてotherユーザに実行権限をつける必要があります（751などでかまいません）。

*注意点*
レンタルサーバで通常のアカウントの場合、apacheの公開ディレクトリにしかファイルを出力できないことが多いです！
その場合、特に出力されたファイルやこのスクリプトについてその他のユーザ（Other）に読み取り権限を付加しないようご注意ください。



## 実行方法
手軽にやるならブラウザで下記を入力してください。
http://ドメイン名/scripts/script.cgi


## レンタルサーバの情報について
- レンタルサーバ、あまりノウハウ/情報がインターネットにない
- iClustaの情報は、[よくあるご質問(FAQ)](http://help.gmocloud.com/app/answers/list/p/8)で検索するとヒントがあるかもしれない


## その他
- サービス紹介ページはすごいきれいで整理されているのに、管理ページがわかりにくかったり、リンク切れがあったりあきらか古い情報が載っていたりするSaaSがよくあって残念な気持ちになる。羊頭狗肉ではないけれど釣った魚に餌をやらない的な。
- レンタルサーバ、自由度低すぎてつらいんだけれど環境のメンテしなくていいのは楽でトレードオフ。
 - 継続してサーバのメンテ/セキュリティ対応できる人がいないとVPSは厳しいと思う。
  - もちろん運用されているアプリのセキュリティは運用者の責任です。
 - でもたまに性能劣化してつらい