システム情報科学実習 - IT人材育成iPedia

システム情報科学実習
―OSS に基づく Web システム開発―
目次
第1回
インターネット接続の設定方法
11
第1章
インターネット接続に必要な情報
12
1.1
ドメイン名 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.2
グローバル IP アドレス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
第2章
インターネットへの接続方法とセキュリティ
19
2.1
ファイアウォール
2.2
IP マスカレード . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
第3章
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
サーバの設定
23
3.1
グローバル DNS の設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.2
ファイルパーミッション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.3
サーバへのアクセス方法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
第4章
エディタについて
30
参考文献
35
第2回
サーバ運用管理の目的と内容
37
第1章
構成管理
38
1.1
サーバ設計時の構成管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
1.2
サーバ運用時の構成管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
第2章
ログ管理とセキュリティ管理
46
2.1
ログ管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
2.2
セキュリティ管理
第3章
障害管理
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
47
3.1
障害対策 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.2
障害の早期発見・早期解決 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
第4章
4.1
バックアップ
52
バックアップの種類 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3
4.2
バックアップの自動化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
4.3
シェルスクリプト
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
参考文献
58
第3回
Web サーバのしくみ・構築・設定方法
59
第1章
Web の概要と歴史
60
1.1
WWW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
1.2
Web の歴史と発展 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
第2章
Web サーバ
61
2.1
HTTP(HyperText Transfer Protocol) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
2.2
HTTP メッセージ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
2.3
URL の仕組み . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
2.4
サーバパス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
第3章
Apache の概要と歴史
69
3.1
Apache の歴史 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
3.2
Apache のバージョン . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
第4章
Apache 2.2 による,Web サーバの構築
70
4.1
Apache のインストール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
4.2
Apache のバージョン確認 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
4.3
Apache の起動確認 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
4.4
Web ブラウザによるアクセス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
4.5
Apache の起動・再起動・停止コマンド . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
4.6
Apache のスタートアップ設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.7
Apache の設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
4.8
メインサイトの作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.9
index.html の作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
4.10
アクセスログの確認 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4.11
モジュール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4.12
PHP モジュールの導入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
4.13
PHP5 の設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
4.14
info.php の作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4.15
Perl の導入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
4.16
CGI スクリプトの動作設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
4.17
test.cgi の作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
参考文献
87
目次
4
第4回
メールサーバのしくみ・SMTP サーバの構築・設定方法
89
第1章
電子メール
90
1.1
メール送受信のしくみ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
1.2
メールアドレスのしくみ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
第2章
SMTP と POP/IMAP
92
2.1
メール送受信時の動作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
2.2
SMTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
2.3
POP3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
2.4
IMAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
2.5
MX レコード . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
2.6
mail コマンド . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
第3章
メールサーバの構築
103
3.1
sendmail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
3.2
Postfix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
3.3
Dovecot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
参考文献
117
第5回
サーバにおけるログ管理
119
第1章
ログ管理の重要性について
120
1.1
ログとは . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
1.2
ログの運用管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
1.3
ログの収集 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
第2章
syslog の導入・管理
125
2.1
ログ制御システム (syslog) とは . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
2.2
syslog の歴史と今後の展望 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
2.3
syslog の運用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
2.4
syslogd の代替ツール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
第3章
ログ管理ツールの導入
128
3.1
logrotate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
3.2
swatch,logwatch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
参考文献
137
第6回
セキュリティ対策と運用方法
139
第1章
セキュリティとは何か
140
1.1
セキュリティの概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
5
1.2
第2章
セキュリティ上の問題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
セキュリティポリシー
146
2.1
セキュリティポリシーとは . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
2.2
法律との違い . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
2.3
セキュリティポリシーの作成
第3章
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
セキュリティ上の問題への対策方法
148
3.1
サービス実行状況の確認 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
3.2
システムログのチェック . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
3.3
ネットワークの監視 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
3.4
システムのアップデート . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
3.5
通信の暗号化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
3.6
システムパスワードのチェック・保護 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
3.7
ファイアウォールの設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
第4章
4.1
第5章
セキュリティ上の問題への対処方法
150
コンピュータウイルスに感染後の対処 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
セキュリティ対策ツールの導入
151
5.1
chkrootkit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
5.2
iptables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
5.3
Tripwire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
参考文献
157
第7回
オープンソースの開発ツール
159
第1章
OSS とは
160
1.1
第2章
ライセンス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
開発ツール
162
2.1
コーディングサポート . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
2.2
テストツール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
第3章
開発ツールの紹介
163
3.1
エディタ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
3.2
ビルドツール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
第4章
ソフトウェア品質
184
4.1
バグ収束曲線 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
4.2
ソフトウェアテスト . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
参考文献
195
目次
6
第8回
ドキュメント作成支援
197
第1章
ドキュメンテーションとは
198
1.1
ドキュメントの種類 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
1.2
ソフトウェアドキュメンテーション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
1.3
ソフトウェアドキュメンテーションの重要性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
第2章
ソフトウェアドキュメンテーション
201
2.1
Doxygen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
2.2
Javadoc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
2.3
nroff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
参考文献
216
第9回
バージョン管理システムの特徴,主なツールと利用方法
217
第1章
バージョン管理システムとは
218
第2章
バージョン管理の方法
219
2.1
集中型のバージョン管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
2.2
分散型のバージョン管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
2.3
リポジトリの管理
2.4
ワークフロー . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
第3章
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
バージョン管理システムの種類
227
3.1
CVS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
3.2
Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
3.3
Subversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
第4章
Subversion
231
4.1
Subversion の導入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
4.2
Subversion の利用方法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
4.3
キーワードアンカーテキスト
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
参考文献
第 10 回
第1章
238
バグ追跡システムの目的・機能と利用方法・Trac の利用
バグ追跡システムとは
239
240
1.1
バグ追跡システムの特徴 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
1.2
バグ追跡システムのワークフロー . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
第2章
2.1
バグ追跡システムの種類
242
Bugzilla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
7
2.2
Trac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
2.3
その他のツール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
第3章
Trac の導入と利用方法
244
3.1
Trac の導入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
3.2
Trac と Subversion との連携 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
3.3
Trac の利用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
参考文献
第 11 回
第1章
259
PHP の特徴と埋め込みプログラミング
PHP の概要
261
262
1.1
歴史 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
1.2
特徴 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
1.3
動作環境 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
1.4
ライセンス形態 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
第2章
基本構文と,主な型/演算子/制御構文
264
2.1
基本構文
2.2
変数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
2.3
配列 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
2.4
演算子 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
2.5
制御構文
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
2.6
デバッグ
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
第3章
3.1
第4章
4.1
埋め込みプログラミング
HTML ファイルに PHP スクリプトを埋め込む . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
パッケージの使い方
291
HTML QuickForm のインストール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
参考文献
第 12 回
第1章
286
297
Python の特徴と連想配列
Python の概要
299
300
1.1
歴史 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300
1.2
ライセンス形態 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
1.3
代表的な利用方法
1.4
Python の特徴 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
1.5
Python プログラミング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
1.6
Python 開発環境 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
目次
8
第2章
基本構文/主な型/演算子/制御構文
309
2.1
基本構文 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
2.2
変数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
2.3
Python のデータ型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
2.4
演算子 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
2.5
制御構文 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
2.6
デバッグ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
第3章
連想配列(辞書)
323
3.1
辞書とは . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
3.2
辞書の基本 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
3.3
辞書の操作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
第4章
標準ライブラリを使う
326
4.1
モジュールとパッケージ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
4.2
モジュールのインポート . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
4.3
実際に標準ライブラリを使ってみる . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
参考文献
第 13 回
第1章
333
Web サービス入門
Web サービス
335
336
1.1
Web サービスとは . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
1.2
Web サービスの定義 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
1.3
Web サービスの技術 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
第2章
XML
340
2.1
XML の基本要素 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
2.2
XML 文書の構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
2.3
XML 宣言 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
2.4
DTD(文書型定義) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
2.5
XML インスタンス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
2.6
XML 名前空間 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
2.7
XML 文書の正しさ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
第3章
XML の実装例
363
3.1
XHTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
3.2
SVG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
3.3
MathML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
3.4
複数の XML 規格の混在 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
第4章
4.1
SOAP
372
SOAP の構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
9
第5章
5.1
標準化技術
376
標準化団体 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
参考文献
第 14 回
第1章
379
マッシュアップ入門(1)
マッシュアップ
381
382
1.1
マッシュアップとは . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
1.2
マッシュアップサイトの特徴
1.3
マッシュアップの構成要素 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
第2章
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
JavaScript
384
2.1
JavaScript の概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
2.2
(X)HTML 文書への記述 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
2.3
JavaScript の記法の特徴 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
第3章
Ajax
390
3.1
Ajax の登場 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
3.2
従来の Web アプリケーションとの違い . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
3.3
Ajax の特徴 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
3.4
通信の制約 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
第4章
XML データの操作
393
4.1
DOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
4.2
DOM ツリーの操作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
参考文献
第 15 回
第1章
400
マッシュアップ入門(2)
プロトコル
401
402
1.1
RPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
1.2
XML–RPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
1.3
SOAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
1.4
REST
第2章
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
データ形式
406
2.1
XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406
2.2
RSS/Atom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406
2.3
RSS 2.0
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
2.4
RSS 1.0
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
2.5
Atom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
2.6
JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
10
2.7
参考文献
目次
JSONP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419
426
第1回
インターネット接続の設定方法
インターネットにサービスを提供するために必要な知識,行うべき作業と設定方法を解説しま
す.ドメインや IP アドレスの取得,インターネットに接続するための設定,信頼性とセキュリ
ティを確保するための運用管理方法などについて説明します.演習では,サーバにリモート接
続し,ネットワーク関係のコマンドのいくつかを実際に使用し,それらの利用方法と動作につ
いて学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
インターネット接続に必要な情報
ネットワークサーバをインターネットへ接続してサービスを提供する場合,ネットワークサーバの所属を識別する
「ドメイン名」とインターネットで利用可能な静的である「グローバル IP アドレス」を取得しておく必要があります.
1.1 ドメイン名
1.1.1 ドメイン名とは
インターネットには Web サーバ,Mail サーバ(以下サーバとする)や,それに接続するユーザなど様々なコンピュー
タが無数に接続されています.これらが互いに通信相手を間違えることなく通信を行うためには,互いの場所を特定す
ることが必要です.その仕組みとして,IP (Internet Protocol) アドレスとドメイン名があります.IP アドレスは 32
ビットのビット列で表されます.人間が扱う場合は 8 ビットずつピリオド「.」で区切り 10 進数で表したものを使用し
ますが,まだまだ扱いやすいというものではありません.そこで,人間がより扱いやすいように個々の IP アドレスに
名前をつけたものがドメイン名です.
ドメイン名と IP アドレスの例として以下のものが挙げられます.
ドメイン名
example.com
IP アドレス
208.77.188.166
IP アドレスを覚えるよりドメイン名を覚えるほうが簡単です.また,今回例に挙げたドメイン名は FQDN (Fully
Qualified Domain Name) という形式です.FQDN は日本語で,完全修飾ドメイン名と呼ばれ,ホスト名やドメイン
名(サブドメイン名)などを省略せずに記述する形式です.
ドメイン名の構造
ドメイン名はピリオド「.」で区切られています.この区切られた 1 つ 1 つの部分をラベルと呼びます.1 つのラベル
の長さは 63 文字以下,ドメイン名全体で 255 文字以下(ピリオドを含む)としなければならない決まりがあります.
ラベルにはアルファベット (A∼Z),数字 (0∼9),ハイフン「–」,を使用することができ,アルファベットには小文字
と大文字の区別はありません.また,図 1.1 のように最も右側のラベルをトップレベルドメインと呼び,以下左へ順に
第 2 レベルドメイン,第 3 レベルドメイン,第 4 レベルドメインと呼びます.
ドメイン名は図 1.2 のように階層構造をなしています.ドメイン名は仮想的に付けられたグループ名の集合体です.
トップレベルドメインから左へ順に大きなグループからその中の小さなグループ(サブドメイン)がピリオドで区切ら
れて並んでいます.このことからも分かるようにドメイン名は階層構造をなしています.トップレベルドメインの上
には全てのドメイン名の根幹となる root ドメインが存在します.root ドメインは省略されるか,ピリオドで表現され
ます.
1.2 グローバル IP アドレス
13
図 1.1
ドメイン名
図 1.2 ドメイン名の構造
1.2 グローバル IP アドレス
1.2.1 IP アドレス
IP アドレスとはインターネットで通信を行う際のプロトコルである TCP/IP において,パケット(分割されたデー
タ)を目的のコンピュータまで届けるための住所となるものです.現在もっとも使われているのは IPv4 (Internet
Protocol version 4) です.IPv4 はアドレスを 32 ビットで管理しているため,2 の 32 乗(約 43 億)通りの IP アドレ
スを使用することができます.IP アドレスは,コンピュータ内部では 2 進数で処理されますが,人間にとって 2 進数
は分かりにくいため,以下のように 8 ビットずつピリオド「.」で区切り 10 進数で表現します.
11010010
210.
11100001
225.
11100101
229.
11010011
2 進数表記
211
10 進数表記
インターネットでサービスを提供する前に,ネットワークに接続するための設定を行う必要があります.ネットワー
クに接続するためには,IP アドレスやサブネットマスク,デフォルトゲートウェイの設定が必要となります.
第1章
14
インターネット接続に必要な情報
IP アドレスは大きく 2 種類に区別されます.インターネットで用いられる「グローバル IP アドレス」とプライベー
トネットワーク(イントラネットなど)で用いられる「プライベート IP アドレス」です.プライベートネットワーク
からは直接インターネットへ接続することはできません.そこで,プライベート IP アドレスをグローバル IP アドレ
スに変換してからインターネットへ接続する必要があります.この技術については 2.2 節で述べます.
1.2.2 プライベート IP アドレス
プライベート IP アドレスとは,プライベートネットワーク内で用いられる IP アドレスです.プライベートネット
ワークとは,インターネットに直接接続しないネットワークです.インターネットが全てに対して開いたネットワーク
なのに対して,プライベートネットワークは外部に対して閉じたネットワークです.プライベート IP アドレスはその
プライベートネットワーク内でのみ有効です.よって,そのプライベートネットワーク管理者が自由に管理することが
できます.プライベート IP アドレスはインターネット上に存在しない IP アドレスであれば,ネットワーク管理者が
任意に IP アドレスを設定することができます.したがって,図 1.3 のように異なるプライベートネットワーク内では
重複した IP アドレスを使用することができます.
図 1.3 プライベート IP アドレスとグローバル IP アドレス
1.2.3 グローバル IP アドレス
インターネットでサービスの提供や利用を行う場合,静的な(重複しないような)グローバル IP アドレスが必要と
なります.プライベートネットワークからインターネットへ接続することはできますが,インターネットからプライ
ベートネットワークへの接続は制限されます.そのため,プライベートネットワーク内で使用されているプライベート
IP アドレスでは,インターネットでサービスを利用できません.また,動的なグローバル IP アドレスを用いた場合,
IP アドレスが替わる可能性があります.そうするとサービス利用者はどこの IP アドレスにアクセスしてよいか分から
1.2 グローバル IP アドレス
15
なくなってしまいます(Dynamic DNS という技術を用いると動的なグローバル IP アドレスでもサービスを提供する
ことができます).
インターネットでのサービスの提供や利用には静的なグローバル IP アドレスがあると便利です.グローバル IP ア
ドレスは重複しないように ICANN (Internet Corporation for Assigned Names and Numbers) によって一元管理さ
れており,日本では JPNIC (Japan Network Information Center) が jp ドメインのグローバル IP アドレスの割り
当てを行っています.図 1.4 のように,ISP (Internet Services Provider) や IP アドレス管理指定業者,または直接
JPNIC からグローバル IP アドレスを取得することができます.
図 1.4
グローバル IP アドレスの取得
1.2.4 サブネットマスクとデフォルトゲートウェイ
サブネットマスク
サブネットマスクはその IP アドレスが所属するネットワーク(サブネットまたはセグメント)を求めるために必要
となる付加情報です.IP アドレスはネットワークアドレス部とホストアドレス部から成り立っています.ネットワー
クアドレス部は自分の所属するネットワークを表し,ホストアドレスはサブネット内のホストを識別するのに用いられ
ます.
通信を行う際に通信相手が同一のサブネット内に存在する場合,自分の所属するネットワーク内のみで通信を完結で
きます.しかしながら,同一のサブネット内にいない場合は,サブネットから出て通信を行わなければなりません.こ
の時,双方の端末が同一のサブネット内に存在するかどうかを判断するためにネットワークアドレスが必要となりま
す.ネットワークアドレスは IP アドレスとサブネットマスクの論理積をとることで求められます.
例 え ば ,図 1.5 の よ う に IP ア ド レ ス が 192.168.200.132 ,サ ブ ネ ッ ト マ ス ク が 255.255.255.0 の 場 合 の
ネットワークアドレスは 192.168.200.0 となります.またサブネットマスクが 255.255.255.240 の場合には,
192.168.200.128 となります.
デフォルトゲートウェイ
インターネットは,実際には小さなネットワークが相互に接続しあった巨大なネットワークです.この小さなネット
ワークをサブネットと呼びます.ネットワークアドレスが示すのがサブネットの住所です.
サブネット同士を結んでいる機器のことをゲートウェイと呼びます.それぞれのサブネットが同じプロトコルを用い
第1章
16
図 1.5
インターネット接続に必要な情報
ネットワークアドレスの計算方法
ているとは限りません.ゲートウェイは,異なるプロトコルでも通信を行うことができるようにデータを相互変換する
役割を担っています.そして,デフォルトゲートウェイとは,経路が不明の場合にパケットを中継するゲートウェイを
指定するものです.
1.2.5 クラスと CIDR
クラス
IP アドレスにはアドレスクラスという分割方法があります.アドレスクラスにはクラス A からクラス E まであり,
それぞれの IP アドレスの先頭部のビット列とネットマスクが異なります.クラス A からクラス C の例を図 1.6 に示
します.
クラス A は IP アドレスの先頭が 0 から始まり,ネットマスクは 255.0.0.0 です.つまり,IP アドレスのうち
0.0.0.0 ∼ 127.255.255.255 がクラス A に相当します.また,ネットマスクが 255.0.0.0 なので,1 つのネット
1.2 グローバル IP アドレス
17
ワークアドレスに対して 2 の 24 乗通り(約 1,600 万通り)のホストを収容することができます.
クラス B は IP アドレスの先頭が 10 から始まり,ネットマスクは 255.255.0.0 です.つまり,IP アドレスのうち
128.0.0.0 ∼ 191.255.255.255 がクラス B に相当します.また,ネットマスクが 255.255.0.0 なので 1 つのネッ
トワークアドレスに対して 2 の 16 乗通り(約 6,500 通り)のホストを収容することができます.
クラス C は IP アドレスの先頭が 110 から始まり,ネットマスクは 255.255.255.0 です.つまり,IP アドレスの
うち 192.0.0.0 ∼ 223.255.255.255 がクラス C に相当します.また,ネットマスクが 255.255.255.0 なので 1 つ
のネットワークアドレスに対して 2 の 8 乗通り(約 250 通り)のホストを収容することができます.
クラス D は IP アドレスの先頭が 1110 から始まります.IP アドレスのうち 224.0.0.0 ∼ 239.255.255.255 がク
ラス D に相当します.クラス D の IP アドレスにはサブネットマスクが存在せず,ホストを持ちません.このクラス
D の IP アドレスは IP マルチキャストに使用されます.IP マルチキャストは特定のグループに所属する全てのホスト
に対してパケットを送信します.つまりクラス D の IP アドレスは 1 対 N や N 対 N の通信に利用されます.
クラス E は IP アドレスの先頭が 1111 から始まります.IP アドレスのうち 240.0.0.0 ∼ 255.255.255.255 がク
ラス E に相当します.ただし,クラス E は実験的な目的から予約されており,実際には使用されていません.
図 1.6
アドレスクラス
CIDR
1990 年代後半まで,各組織への IP アドレスの割り当てはクラス単位で行われていました.1 つのネットワークアド
レスに対して,クラス A は約 1,600 万個,クラス B は約 6,500 個,クラス C は 254 個のホストが収容できます.よっ
て大規模なネットワークにはクラス A を,中規模なネットワークにはクラス B を,小規模なネットワークにはクラス
C を割り当てていました.この IP アドレスの割り当て方は非効率です.例えば 300 個のホストを収容したい場合,ク
ラス C では収容しきれないのでクラス B が必要になります.しかし,クラス B の最大ホスト収容数は約 6,500 個なの
で,約 6,200 個の IP アドレスが使われません.
第1章
18
インターネット接続に必要な情報
このような IP アドレスの非効率な割り当て方を改善したのが CIDR (Classless Inter-Domain Routing) です.
CIDR では任意のビット長で IP アドレスを割り当てることができます.つまり,ネットワーク・アドレス部の長さを
任意に決めることができるので,収容できる最大ホスト数の選択肢が増えます.CIDR では IP アドレスの先頭から何
ビットをネットワーク・アドレス部に割り当てるかを「/ビット数」で表現します.例えば先頭から 8 ビットをネット
ワーク・アドレス部とする場合,/8 と表記します.つまり,これはサブネットマスクが 255.0.0.0 であることを示し
ています.表 1.1 に CIDR での収容可能なホスト数を示します.
表 1.1 CIDR 表記と最大ホスト数
CIDR 表記
10 進数表記
2 進数表記
最大ホスト数
/8
255.0.0.0
11111111.00000000.00000000.00000000
16777214
/9
255.128.0.0
11111111.10000000.00000000.00000000
8388606
/10
255.192.0.0
11111111.11000000.00000000.00000000
4194302
/11
255.224.0.0
11111111.11100000.00000000.00000000
2097150
/12
255.240.0.0
11111111.11110000.00000000.00000000
1048574
/13
255.248.0.0
11111111.11111000.00000000.00000000
524286
/14
255.252.0.0
11111111.11111100.00000000.00000000
262142
/15
255.254.0.0
11111111.11111110.00000000.00000000
131070
/16
255.255.0.0
11111111.11111111.00000000.00000000
65534
/17
255.255.128.0
11111111.11111111.10000000.00000000
32766
/18
255.255.192.0
11111111.11111111.11000000.00000000
16382
/19
255.255.224.0
11111111.11111111.11100000.00000000
8190
/20
255.255.240.0
11111111.11111111.11110000.00000000
4094
/21
255.255.248.0
11111111.11111111.11111000.00000000
2046
/22
255.255.252.0
11111111.11111111.11111100.00000000
1022
/23
255.255.254.0
11111111.11111111.11111110.00000000
510
/24
255.255.255.0
11111111.11111111.11111111.00000000
254
/25
255.255.255.128
11111111.11111111.11111111.10000000
126
/26
255.255.255.192
11111111.11111111.11111111.11000000
62
/27
255.255.255.224
11111111.11111111.11111111.11100000
30
/28
255.255.255.240
11111111.11111111.11111111.11110000
14
/29
255.255.255.248
11111111.11111111.11111111.11111000
6
/30
255.255.255.252
11111111.11111111.11111111.11111100
2
IP アドレスのホストアドレス部には全て 0 と全て 1 は使用することができません.ホストアドレス部が全て 0 では
ネットワークアドレスと同じになってしまうからです.また,全て 1 ではブロードキャストアドレスという特別なアド
レスなので使用することができません.よって,最大ホスト数は 2 のホストアドレス部のビット数乗マイナス 2 となり
ます.例として,/23 の最大ホスト数を計算してみましょう.ホストアドレス部のビット数は 32 − 23 より 9 ビットと
なります.2 の 9 乗は 512 なので,最大ホスト数は 512 − 2 より 510 通りとなります.クラスによる IP アドレスの配
布方法では 3 種類の最大ホスト数のみから選ぶことしかできませんでしたが,CIDR により最大ホスト数の選択肢が増
大しました.このことより,ネットワークの規模に適した IP アドレスを割り当てることができ,IP アドレスを効率的
に運用できるようになりました.
第2章
インターネットへの接続方法とセキュリティ
2.1 ファイアウォール
ファイアウォールとは火災の延焼を防止するための壁ですが,コンピュータセキュリティでは図 2.1 のように不正ア
クセスなどの脅威から組織内のコンピュータネットワークを守るためのものを指します.このファイアウォールをイン
ターネットと組織内のコンピュータネットワークの間に設置することにより,脅威から組織内のコンピュータネット
ワークを守ります.ファイアウォールには,大きく分けて「パケットフィルタリング型」と「アプリケーションゲート
ウェイ型」の 2 つの型があります.
図 2.1 ファイアウォール
第2章
20
インターネットへの接続方法とセキュリティ
2.1.1 パケットフィルタリング型
パケットフィルタリング型ではパケットが正常かどうかを検査し,不正なパケットだと判断した場合破棄されるの
で,不正なパケットが組織内のコンピュータネットワークまで到達することを防止します.パケットは図 2.2 のような
IP ヘッダとデータから構成されており,パケットフィルタリングではその中のプロトコルや送信元 IP アドレスや宛先
IP アドレス,TCP ヘッダのポート番号などを検査します.
図 2.2
IP ヘッダ
2.1.2 アプリケーションゲートウェイ型
アプリケーションゲートウェイ型では通信を中継することによって組織内のコンピュータネットワークを脅威から守
ります.この時通信を中継するアプリケーションゲートウェイを代理サーバ (Proxy Server) と言います.代理サーバ
が通信を代理で行い,受信したパケットをアプリケーションで解釈し,不正なデータやコマンドがないかを検査しま
す.不正があればパケットを破棄し,なければ組織内のコンピュータネットワークへ送られます.
例えば,HTTP Proxy では HTTP 通信を中継することによって,特定の URL へのアクセスを禁止したり,サーバ
からの Cookie 要求を拒否することができます.
2.2 IP マスカレード
プライベートネットワークからインターネットへ接続するためにはプライベート IP アドレスをグローバル IP アド
レスに変換する必要があります.この変換する技術として,NAT (Network Address Translation) と IP マスカレー
ドがあります.
NAT は,プライベート IP アドレスとグローバル IP アドレスを 1 対 1 で変換します.図 2.3 のように,クライアン
ト A が Web サーバ(グローバル IP アドレスが 210.255.229.211 )にアクセスする場合を考えてみましょう.NAT
を利用すると,中継先のルータで送信元がクライアント A のプライベート IP アドレスからルータのグローバル IP ア
ドレスに変換されます.その後,Web サーバにアクセスします.Web サーバは 210.255.229.211 に応答を返します.
2.2 IP マスカレード
21
応答を受け取ったルータはグローバル IP アドレスをプライベート IP アドレスに変換しパケットを送ります.NAT で
は,1 つのグローバル IP アドレスを用いて複数のクライアントが同時にインターネットに接続することはできません.
IP マスカレードでは,プライベート IP アドレスとグローバル IP アドレスを N 対 1 で変換します.図 2.4 のよう
に,クライアント A とクライアント B が同時に Web サーバにアクセスする場合を考えてみましょう.IP マスカレー
ドでは TCP ヘッダのポート番号も使用します.中継するルータで送信元のクライアント A とクライアント B のプラ
イベート IP アドレスはルータのグローバル IP アドレスに変換されます.また,クライアント A のポート番号は 1025
のままですが,クライアント B のポート番号は 1026 に変換されます.IP マスカレードでは IP アドレスとポート番号
を変換することで,1 つのグローバル IP アドレスで複数のクライアントを同時にインターネットへ接続することを可
能にしています.
図 2.3 NAT
22
第2章
図 2.4 IP マスカレード
インターネットへの接続方法とセキュリティ
第3章
サーバの設定
サーバをインターネットへ接続する場合,グローバル DNS の設定やアクセス制限,外部からのアクセス手段といっ
た設定が必要となります.グローバル DNS の設定では自分の取得した IP アドレスとドメイン名を公開するための設
定を行います.ファイルパーミションではコマンドを用いた設定方法について説明します.また,外部からのアクセス
手段では telnet や ssh,sftp について解説します.
3.1 グローバル DNS の設定
3.1.1 DNS とは
インターネットでサービスを提供する場合,サービスを提供する場所を示すドメイン名とグローバル IP アドレスが
必要となります.ドメイン名は人間が扱いやすいようにつけられた名前であり,実際のアクセスはすべて IP アドレス
に基づいて行われます.そこでドメイン名に対応する IP アドレスを調べる必要があります.ドメイン名を IP アドレ
スに変換する処理を名前解決と呼び,この機能を提供するのが DNS (Domain Name System) サーバです.
3.1.2 DNS の歴史
インターネットの起源である ARPANET(Advanced Research Projects Agency Network: 米国国防総省高等研
究計画局)では名前解決に HOSTS.TXT というテキストファイルが用いられており,ARPANET に接続しているコ
ンピュータはこのファイルをダウンロードしていました.HOSTS.TXT は 1 行に IP アドレスとドメイン名が記述さ
れており,このファイルを検索することでドメイン名から IP アドレスを参照していました.
HOSTS.TXT
127.0.0.1
localhost
208.77.188.166
example.com
202.229.63.242
www.ipa.go.jp
HOSTS.TXT は Stanford Research Institute (SRI) の Network Information Center (NIC) によって一括管理され
ていました.ARPANET に新たにコンピュータが接続されたり,IP アドレスが変更された場合は,このセンターでテ
キストファイルが更新され,ARPANET に接続しているコンピュータはそれをダウンロードしなくてはなりません.
しかし,ARPANET に接続するコンピュータが増えるにつれ,ドメイン名と IP アドレスの組み合わせは膨大にな
り,かつ頻繁に追加や変更が発生するため,これらの情報を一括管理するのは現実的ではなくなりました.そこで,新
たな効率的な名前解決の手段として DNS が考えられました.
第 3 章 サーバの設定
24
3.1.3 DNS の仕組み
ドメイン名は図 1.2 で示したように階層構造をなしています.DNS ではこの階層構造の各ノードごとに DNS サー
バ(ネームサーバ)があり,親は子のドメイン名と IP アドレスの対応関係を把握しています.IP アドレスやドメイ
ン名の追加または変更があった場合,階層構造で親にあたるネームサーバに登録し直すだけで済みます.これにより
ARPANET 時代の一括管理に比べて 1 つのネームサーバの負担は激減します.
図 3.1 に,example.com の名前解決の手順を示します.まず,自組織内のネームサーバに問い合わせを行います (1).
このネームサーバに該当するドメイン名がない場合,root のネームサーバに問い合わせます (2).root のネームサーバ
は example.com の IP アドレスの情報を持っていな場合で,かつ com のネームサーバの IP アドレスの情報は持って
いる場合,com のネームサーバに問い合わせるように応答を返します (3).次に com のネームサーバに example.com
の IP アドレスを問い合わせます (4).このネームサーバに,該当するドメイン名が登録されている場合,example.com
の IP アドレスを返します (5).このようにドメインの階層構造を 1 つずつ降りていくように,名前解決を行います.
3.1.4 レジストリ・レジストラ
インターネットでサービスを提供する場合,ドメイン名と IP アドレスが必要です.さらに,取得したドメイン名と
IP アドレスを上位のグローバル DNS に登録する必要があります.ここで登場するのがレジストリとレジストラです.
レジストリは DNS サーバを管理している機関です.jp のレジストリは日本レジストリサービス (JPRS) です.レジ
ストラはレジストリにドメイン情報を登録する機関です.レジストリが各ドメインに対して 1 つしか存在しないのに対
し,レジストラは複数存在します.
ドメイン名と IP アドレスを登録する際には,レジストリへ支払う登録費用とレジストラへ支払う登録手数料が必要
になります.
3.1.5 プライベートネットワークにおける名前解決
プライベートネットワークにおいて名前解決が必要な場合は,ローカル DNS の設置,HOSTS.TXT やブロードキャ
ストによって名前解決を行うことができます.ブロードキャスト名前解決はプライベートネットワーク内の全ての IP
アドレスに対して,名前解決を問い合わせるという方法です.
3.2 ファイルパーミッション
インターネットへ接続する上で,留意すべきことがあります.システムを安全に運用するために,不正利用させない,
見られてはいけない情報を見せないなどに気をつけなければなりません.不正利用させないためにはファイアウォール
の設置や外部からのアクセス方法の制限などが必要です.また,見られてはいけない情報にはファイルのアクセス権限
を設定する必要があります.ファイルのアクセス権限を設定することで,ファイル操作(読み込み,書き込み,実行)
を特定のユーザのみに限定することができます.
3.2.1 chown コマンド
chmod コマンドを用いて権限の設定を行うことができますが,その前に所有者やグループの設定を行う必要があり
ます.ディレクトリやファイルの所有者,グループを変更するには, chown コマンド(以下, chown )を用います.
このコマンドは自分の所有しているファイルのみに対して有効です.
以下は chown の構文です.
3.2 ファイルパーミッション
25
図 3.1 DNS の問い合わせ
$ chown [option] user:group filename
自分のファイル以外に設定を行いたい場合は,スーパーユーザ権限でコマンドを実行しなければならないので, sudo
コマンドを用いて実行します.
$ sudo chown [option] user:group filename
オプションを表 3.1 に示します.user には所有者,group にはグループを記述します.filename にはファイル名(ま
たはディレクトリ名)を記述します.
chown コマンドの使用例を以下に示します.test.txt の所有者を mirai に変更します.
第 3 章 サーバの設定
26
表 3.1 chown オプション一覧
option
内容
-c, --changes
所有者が変更されたファイルのみ詳細表示
-f, --silent,--quiet
所有者が変更されなかった場合でもエラーメッセージを表示しない
-v, --verbo
アクセス権限の変更を詳細に表示する
-R, -recursive
ディレクトリとその中身のアクセス権限を再帰的に変更する
--help
chown コマンドの使用法を表示する
$ chown mirai test.txt
また,test.txt のグループを fun に変更したい場合は以下を用います.
$ chown :fun test.txt
上記 2 つの処理を同時に実行することもできます.
$ chown mirai:fun test.txt
3.2.2 chmod コマンド
アクセス権限を設定するためには chmod コマンド(以下, chmod )を用います.このコマンドは所有者やグループ,
ゲストそれぞれに対して読み込みや書き込み,実行の権限を設定することができます.
以下は chmod の構文です.
$ chmod [option] mode filename
オプションを表 3.2 に示します.mode は誰にどの権限の付加(または削除)を行うかを記述します.記述方法は 2
つあり,記号によるものと数字によるものがあります.filename は権限を変更したいファイル名(またはディレクトリ
名)を記述します.
表 3.2 chmod オプション一覧
option
内容
-c, --changes
アクセス権が変更されたファイルのみ詳細表示
-f, --silent,--quiet
アクセス権がされなかった場合でもエラーメッセージを表示しない
-v, --verbo
アクセス権限の変更を詳細に表示する
-R, -recursive
ディレクトリとその中身のアクセス権限を再帰的に変更する
--help
chmod コマンドの使用法を表示する
記号による mode 記述方法では対象,操作,権限を順次記述します.対象には,u (所有者),g(グループ)
,o(ゲ
スト)
,a(全てのユーザ)があります.操作には,+(後に記述する権限の付加)
,–(後に記述する権限の削除)と =
(後に記述する権限にする) があります.権限には,r(読み込み),w(書き込み) ,x(実行)があります.以上を
表 3.3 にまとめます.例えば,所有者とグループに書き込み権限を与えたい場合は,ug+w となります.また,ゲスト
の実効権限の削除を行いたい場合は o–x となります.ゲストの権限を読み込み権限のみに変更したい場合は,o=r と
なります.
3.2 ファイルパーミッション
27
表 3.3
記号による mode の記述方法
表記法
意味
u
所有者
g
グループ
o
ゲスト
a
全てのユーザ
+
権限の付加
–
権限の削除
=
権限にする
r
読み込み権限
w
書き込み権限
x
実行権限
数字による mode 記述方法は,3 桁の 8 進数で記述します.左から所有者,グループ,ゲストの権限を表します.
表 3.4 は 8 進数と権限の関係を示したものです.例えば,所有者には全ての権限,グループには読み込みと実行権限,
ゲストには実行権限を付加する場合,mode は 731 となります.
表 3.4
数字による mode の表記
表記法
権限
0
---
1
--x (実行)
2
-w- (書き込み)
3
-wx (書き込み,実行)
4
r-- (読み込み)
5
r-x (読み込み,実行)
6
rw- (読み込み,書き込み)
7
rwx (読み込み,書き込み,実行)
使用例として,hoge.bin というファイルに対して全てのユーザに書き込みの権限を付加したい場合を以下に示し
ます.
$ chmod a+x hoge.bin
また,hoge.bin においてゲストから実行権限を削除するには,以下を用います.
$ chmod o-x hoge.bin
hoge.bin において所有者には全ての権限を,グループには読み込みと実行権限を,ゲストには実行権限をそれぞれ与
えるためには以下を用います.
$ chmod 731 hoge.bin
第 3 章 サーバの設定
28
3.2.3 スーパーユーザについて
スーパーユーザとは root 権限を持ったユーザのことです.スーパーユーザは,プロセスやファイルに対してすべて
の権限を持ちます.そのため,入力ミスや判断ミスなどでシステムに対して取り返しのつかない状況を招く恐れがあり
ます.したがって,スーパーユーザ権限を必要としない簡単な設定を行う際は権限の低いユーザで設定を行います.ま
た,スーパーユーザ権限が必要な時のみ sudo コマンドを用いて一時的にスーパーユーザ権限を取得し作業を行います.
スーパーユーザを設定するには/etc/sudoers ファイルに以下の記述を追加します.
ユーザ名 ALL=(ALL)ALL
このユーザ名に指定されたユーザはスーパーユーザとなり,root と同じ権限になります.また一時的にスーパーユー
ザ権限でコマンドを実行したい場合は,その実行したいコマンドの前に sudo をつけます.以下に例を示します.
$ sudo chown root hoge.bin
3.3 サーバへのアクセス方法
サーバにアクセスするには,リモートログインします.リモートログインとは,異なるコンピュータがネットワーク
を通じてサーバなどにログインすることです.telnet や ssh を用いるとリモートログインすることができます.この他
にも,Web 管理ツールを用いて外部からアクセスしサーバの設定を変更することも可能です.
3.3.1 telnet
telnet とはリモートログインするためのプロトコルです.telnet サーバは起動しているコンピュータに対して,
telnet クライアントを使ってログインすることができます.ログインすると,接続先のコンピュータの前にあたかも
座っているかのように CUI (Character User Interface) で操作することができます.
telnet クライアントの操作中はキーボードからの入力が telnet サーバに送信され,telnet サーバは受信したコマンド
を実行し,その実行結果をクライアントへ送信します.
telnet は簡単にサーバを立ち上げリモートログインすることができますが,セキュリティ上,あまり安全とはいえま
せん.なぜなら,ログイン時のパスワードなど全ての通信が平文でインターネット上を流れるためです.この解決策と
して ssh があります.
3.3.2 ssh
telnet と同様に ssh もリモートログインするためのプロトコルです.ssh サーバは起動しているコンピュータに対し
て ssh クライアントを使ってログインすることができます.telnet との大きな違いは安全性です.ssh の場合,全ての
通信が暗号化されてインターネット上を流れます.そのため,パスワードの盗聴などを防ぐことができ,より安全にリ
モートログインすることができます.
ssh は SSL (Secure Socket Layer) という暗号方式で暗号化されています.SSL はインターネット上で幅広く使用さ
れている情報を暗号化するプロトコルです.
3.3 サーバへのアクセス方法
29
3.3.3 sftp
ftp (File Transfer Protocol) はファイル転送を行うためのプロトコルです.ftp は telnet 同様全ての通信が平文で
インターネット上を流れます.そこで,ファイル転送を安全に行うために,暗号化して通信を行う必要があります.
sftp (SSH File Transfer Protocol) は,簡単に言うと ssh + ftp という意味で,ファイル転送に ssh のコネクションを
利用するので安全に通信を行うことができます.
3.3.4 Web 管理ツール
Web 管理ツールに webmin というものがあります.webmin は Linux において GUI でユーザアカウントや Apache,
ファイアウォールなど様々な設定を行うことができます.また,Web ブラウザを用いるため外部からでも設定を変更
することができます.
第4章
エディタについて
演習では vi というエディタを使用することを前提としています.vi は Linux にインストールされていることの多い
軽量なエディタです.他にも,vi の高機能版である vim や emacs, ed などがあります.
vi には 3 種類のモードがあり,文字を入力するインサートモード(図 4.1),編集作業を行うコマンドモード(図 4.2),
範囲指定を行うビジュアルモード(図 4.3)があります.インサートモードからコマンドモードへモード移行する場合
は a または i を入力します.インサートモードからコマンドモードへモード移行する場合は [Esc] を押下すると変更で
きます.表 4.1 は vi の主要なコマンドの一覧です.ビジュアルモードへはコマンドモードで v を入力するとビジュア
ルモードに移行します.表 4.1 のコマンドは vim エディタでも使用することができます.
表 4.1 vi の主なコマンド
動作
コマンド
カーソルを 1 列←に移動
h
カーソルを 1 列→に移動
l
カーソルを 1 行↑に移動
k
カーソルを 1 行↓に移動
j
カーソル位置の 1 文字を削除
x
カーソルがある行を 1 行削除
dd
カーソルがある行をコピーして貼り付け
Y を押した後,貼り付けたい行で P
保存して終了
ZZ(または:wq)
保存
:w
終了
:q
強制終了
:q!
31
図 4.1 vi のインサートモード
図 4.2
vi のコマンドモード
第4章
32
図 4.3 vi のビジュアルモード
エディタについて
第 1 回 演習課題
目標
ネットワーク関係のコマンドを実行し,動作を確認します.
ifconfig, ping, nslookup のコマンドについてインターネット等を用いて調べて下さい.また,調べたコマ
ンドを実行して下さい..
課題 1 リモートログイン
自分のノート PC からサーバ機に ssh でログインし,以下のコマンドを使ってみて下さい.ssh でログインするには
Tera Term を用いるとよいです.
課題 2 ifconfig コマンド
ifconfig コマンドはネットワークインタフェースのステータスの確認や設定を行うコマンドです.端末の IP アド
レスやネットマスクを調べることができます.
2–1
IP アドレスを調べて下さい( IPv4 , IPv6 両方とも).
2–2
ネットマスクを調べて下さい.
課題 3 nslookup コマンド
nslookup コマンドを用いて DNS サーバに問い合わせを行い,以下の IP アドレスやドメイン名を調べて下さい.
3–1
www.fun.ac.jp
3–2
www.yahoo.com
3–3
66.249.89.99
課題 4 ping コマンド
ping コマンドは指定したホストにパケットを送り,生存確認を行うコマンドです.
4–1
自分の IP アドレスにパケットを送り,レスポンスが返ってくるか確認してください.
第4章
34
第 1 回 演習課題
4–2
近くの人のコンピュータにパケットを送り,レスポンスが返ってくるか確認してください.
4–3
66.249.89.99 (または課題 3 で調べたドメイン名)にパケットを送り,レスポンスが返ってくるか確認してくだ
さい.
4–4
0.3 秒間隔で近くの人にパケットを送り,レスポンスが返ってくるか確認してください.
参考文献
[1] 竹下隆史, 荒井透, 苅田幸雄, マスタリング TCP/IP 入門編, オーム社開発局(編), 株式会社オーム社, 2004
[2] 日経 BP 社 ITpro, http://itpro.nikkeibp.co.jp/
[3] 独立行政法人 情報処理推進機構, http://www.ipa.go.jp/
第2回
サーバ運用管理の目的と内容
Linux のネットワークサーバを運用管理する作業の内容と管理対象とする項目,運用管理自体
の重要性などについて解説します.運用管理業務の目的としてシステムやサービスの品質を維
持することと,そのために構成管理,ログ管理,セキュリティ管理,障害管理などの様々な管
理が必要であることを示します.演習では,ログの確認やサーバから NAS への定期バックアッ
プ設定を実際に行い,サーバ運用管理作業について学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
構成管理
サーバのハードウェアやソフトウェアを管理することを構成管理と呼びます.
1.1 サーバ設計時の構成管理
サーバを構築する前に,サーバの性能をどの程度のものにするのか,どのような OS (Operating System) を使用す
るのかなどを,サーバ構築の設計段階で決めておく必要があります.スペック選定には,サーバの利用目的やコスト,
予算などから総合的に判断しなければなりません.以下はサーバのスペックを決める際に考慮するべきものです.
• スループット(単位時間あたりの処理能力)
• 同時アクセスユーザ数
• ディスクの容量
• メモリの容量
• 消費電力
• サーバの重要度
1.1.1 ハードウェアから見たサーバ
サーバのハードウェアのスペックは CPU,メインメモリ(メモリ)で決まります.以下にサーバに必要とされる
CPU やメモリの特徴について述べます.
CPU
コンピュータの基本的な機能(制御,演算,記憶,入力,出力)のうち,制御と演算を行うコンピュータの司令塔に
あたるのが CPU (Central Processing Unit) です.CPU は 1 度の処理で扱えるデータ量によって 8 ビット,16 ビッ
ト,32 ビットなどの種類があり,値が高いほど性能も高くなります.また,同じビット数でも,1 秒間に実行できる処
理の回数が多いほうが性能は高くなります.
CPU はマルチプロセッサ化可能な場合があります.1 つのコンピュータに CPU を 2 個,4 個,8 個またはそれ以上
搭載することで,処理を分散させ全体的な処理の高速化が図れます.また,1 つの CPU に複数のコアを搭載している
マルチコア CPU を使用することで,より処理能力の高いサーバを構築することができます.
メインメモリ
コンピュータの基本的な機能のうち,記憶を担当するのが主記憶装置であるメインメモリです.メインメモリは,
CPU から直接読み書きすることができる記憶装置であり,高速に動作することができますが,高価なため大量にコン
ピュータに搭載することができません.また,メインメモリは電源を切ると内容が失われます.
1.2 サーバ運用時の構成管理
39
メインメモリはコンピュータにおいて,司令塔である CPU にデータやプログラムを 供給する大事な装置です.メ
インメモリにエラーが発生すると,プログラムの停止に加え,OS を巻き込んだ致命的なシステムダウンに陥る可能性
があります.そのため,サーバ用のメインメモリには ECC (Error Check and Correct) 機能付のレジスタードメモリ
がよく用いられます.
1.1.2 OS
サーバを構築するにあたり,どの OS を使用するか決める必要があります.OS は「プロプライエタリ OS」と「オー
プンソース OS」の 2 種類に分類できます.OS 選びでは,特に価格,機能,サポートについて考慮する必要がありま
す.有償の OS の場合,サポートがあるのが一般的です.また,無償の OS でも有償のサポートがある場合がありま
す.以上のことについて考慮し,目的や用途によって適した OS を選ぶ必要があります.
1.2 サーバ運用時の構成管理
運用中の構成管理にはユーザやサーバアプリケーションの追加変更,OS やアプリケーションのアップグレードなど
が含まれます.さらに,HDD やメインメモリの使用状態を監視し,適切な状態を維持するのも構成管理に含まれます.
1.2.1 ユーザの管理
ユーザを追加するには adduser コマンド(以下, adduser )を用います.このコマンドはスーパーユーザでなけれ
ば使用できないため,スーパーユーザ権限で実行します.
以下は adduser の構文です.
$ sudo adduser [option] username
オプションを表 1.1 に示します.username にはユーザ名を記述します.例として,ユーザ ID が 200,グループ名
が group でホームディレクトリが/usr/moge のユーザ hoge を追加したい場合は以下を用います.
$ sudo adduser -u 200 -i group --home /usr/moge hoge
表 1.1 adduser コマンドの option
option
内容
-u, --uid
ユーザ ID を指定する
-g, --gid
グループ ID を指定する
-i, --ingroup
グループ名を指定する
-s, --shell
ログインシェルを指定する
--home
ホームディレクトリを指定する
--help
adduser コマンドの使用法を表示する
1.2.2 更新管理
更新管理にはアップグレードとアップデートの 2 つの種類があります.アップグレードは機能拡張を意味し,実行す
ると大幅な機能拡張が行われます.アップデートは更新を意味し,実行するとプログラムが修正されたり,多少の機能
の向上が行われます.
第1章
40
構成管理
OS やアプリケーションのアップグレードやアップデートがあった場合,実際のサーバに直接アップグレードやアッ
プデートを行うと,依存関係などで動作しなかったり思わぬ悪影響を及ぼす可能性があります.したがって,実際の
サーバの環境と同じテスト環境を構築して,アップグレードやアップデートをテストしてから反映させます.パッチを
適用する場合も同様にテスト環境でテストした後に実際のサーバに反映させるとよいでしょう.
1.2.3 容量確認
df コマンド
df コマンド(以下, df )は HDD などのディスクドライブの空き容量を調べるのに用います.
以下は df の構文です.
$ df [option] [filename]
オプションを表 1.2 に示します.filename を指定した場合,そのファイルが属しているディスクドライブの容量を表
示します.実行例を図 1.1 に示します.
表 1.2
df オプション一覧
option
内容
-a, --all
ダミーのファイルシステムも含めて表示する
-i, --inodes
i ノードの使用量を表示する
-h, --human-readable
容量を適当な単位で表示する
-k
容量を K バイト単位で表示する
-t, --type
ファイルシステムのタイプを指定する
--help
df コマンドの使用法を表示する
図 1.1 df コマンドの実行例
free コマンド
free コマンド(以下, free )はメモリの使用状況を確認するために用います.このコマンドは/proc/meminfo の
内容を整形して表示するコマンドです.
以下は free の構文です.
$ free [option]
オプションを表 1.3 に示します.オプションを指定しないで実行した場合は容量をキロバイト単位で表示します.実
1.2 サーバ運用時の構成管理
41
行例を図 1.2 に示します.
表 1.3 free オプション一覧
option
内容
-b
容量をバイト単位で表示する
-k
容量を K バイト単位で表示する
-m
容量を適当な単位で表示する
-g
容量を G バイト単位で表示する
-s
指定した秒単位で表示を続ける
-t
物理メモリとスワップメモリの合計も表示する
--help
free コマンドの使用法を表示する
図 1.2 free コマンドの実行例
top コマンド
top コマンド(以下, top )は現在のシステム状況を表示するために用います.
以下は top の構文です.
$ top [option]
オプションを表 1.4 に示します. top を実行するとステータスが表示されます.ステータスを表 1.5 に示します.
表 1.4 top オプション一覧
option
内容
-d n
検査間隔を n 秒とする
第1章
42
構成管理
表 1.5 top のステータス
ステータス
内容
PID
プロセス ID
USER
プロセスを実行しているユーザ
PR
優先度(動的優先度)
NI
ナイス値(静的優先度)
VIRT
仮想メモリサイズ
RES
物理メモリサイズ
SHR
共有メモリサイズ
S
ステータス(R:実行可能 S:停止 D:割り込み不可の停止 T:停止
(またはトレース中)Z:ゾンビプロセス W:スワップアウトしたプ
ロセス N:ナイス値が正しい)
%CPU
CPU の占有率
%MEN
メモリの占有率
TIME+
プロセスの実行時間(単位は秒)
COMMAND
コマンド名
1.2.4 その他便利なコマンド
システムを管理していく上で便利なコマンドがたくさんあります.ここでは,代表的な find , grep , cat , head ,
tail コマンドを紹介します.
find コマンド
find コマンド(以下, find )はファイルやディレクトリ検索に用います.
以下は find の構文です.
$ find [option] [path] [条件式]
オプションを表 1.6 に示します.path で指定されたディレクトリ以下が検索対象となります.また,条件式を表 1.7
に示します.
表 1.6 find オプション一覧
option
内容
-follow
シンボリックリンクの参照先を検索する
-xdev
他のファイルシステムにあるディレクトリは検索しない
--help
find コマンドの使用法を表示する
grep コマンド
grep コマンド(以下, grep )は正規表現を用いてファイル中の指定したパターンの文字列を検索するのに用いる
コマンドです.
1.2 サーバ運用時の構成管理
43
表 1.7 find の条件式
条件式
内容
-atime n
最後にアクセスされたのが n*24 時間前ならば真
-empty
空のディレクトリまたはファイルならば真
-group gname
ファイルのグループが gname ならば真
-mmin n
最後にファイルが編集されたのが n 分前ならば真
-name pattern
ファイル名が pattern と一致するならば真(pattern はワイルド
カードで指定)
-type c
ファイルタイプが c と一致するならば真(c はディレクトリの場合
d,ファイルの場合 f,シンボリックリンクの場合 l)
-user uname
ファイルの所有者が uname ならば真
-size n
ファイル容量が n ならば真
以下は grep の構文です.
$ grep [option] pattern filename
オプションを表 1.8 に示します.pattern には正規表現で検索する文字列を指定します.filename には検索対象の
ファイル名を記述します.
表 1.8 grep オプション一覧
option
内容
-c, --count
検索条件にマッチした行数を表示する
-num
マッチした行から前後 num 行を同時に検索結果として表示する
-i, --ignore-case
大文字と小文字の区別せずに検索する
-n, --line-number
各行の前に行番号を表示する
-v, --revert-match
マッチしない行を検索結果として表示する
-x, --line-regexp
行全体で一致するもののみを表示する
--help
grep の使用法を表示する
cat コマンド
cat コマンド(以下, cat )は指定したファイルの内容を表示するために用います.複数のファイルを指定した場
合は,内容を連結して表示します.
以下は cat の構文です.
$ cat [option] filename
オプションを表 1.9 に示します.filename は表示したいファイル名を記述します.複数のファイルを記述すること
もできます.例として,hoge.txt というファイルを行番号を付けて表示したい場合は以下のようにします.
$ cat -n hoge.txt
第1章
44
構成管理
表 1.9 cat オプション一覧
option
内容
-n, --number
行番号を表示する
-b, --number-nonblank
非空白行の行番号を表示する
-E, --show-end
行の最後に"$"を表示する
-T, --show-tabs
タブを"^I"で表示する
-v, --show-nonprinting
改行とタブを除いて制御文字を表示する
--help
cat コマンドの使用法を表示する
head コマンド
head コマンド(以下, head )は指定したファイルの内容の冒頭を表示するために用います.option を付けずに実
行すると冒頭の 10 行が表示されます.
以下は head の構文です.
$ head [option] filename
オプションを表 1.10 に示します.filename には表示対象のファイル名を記述します.hoge.txt のファイルの先頭 5
行を表示したい場合は以下のようにします.
$ head -n 5 hoge.txt
表 1.10
option
-c N, --byte=N
head オプション一覧
内容
ファイル先頭から N バイト分を表示する.(N の後に b を付加する
とブロック単位,k を付加するとキロバイト単位,m を付加すると
メガバイト単位となる)
-n N, --lines=N
先頭から N 行分表示する
-q, --quiet, --silent
ファイル名を表示しない
-v, --verbose
常にファイル名を表示する
--help
head コマンドの使用法を表示する
tail コマンド
tail コマンド(以下,termtail)は指定したファイルの内容の末尾を表示するために用います.オプションを付け
ずに実行すると末尾の 10 行が表示されます.
以下は tail の構文です.
$ tail [option] filename
オプションを表 1.11 に示します.filename には表示対象のファイル名を記述します.hoge.txt のファイルの末尾 5
行を表示したい場合,以下のようにします.
$ tail -n 5 -f hoge.txt
1.2 サーバ運用時の構成管理
45
表 1.11 tail オプション一覧
option
内容
-c N, --byte=N
ファイル末尾から N バイト分を表示する(N の後に b を付加すると
ブロック単位,k を付加するとキロバイト単位,m を付加するとメ
ガバイト単位となる)
-n N, --lines=N
末尾から N 行分表示する
-f, --follow
表示するファイル内容を更新し続ける
-q, --quiet, --silent
ファイル名を表示しない
-v, --verbose
常にファイル名を表示する
--help
tail コマンドの使用法を表示する
第2章
ログ管理とセキュリティ管理
2.1 ログ管理
ログとはコンピュータの利用状況やデータ通信の記録を取ること,または記録そのもののことを言います.ログを監
視することにより,障害や不正アクセスなどを発見しやすくなります.
ログの監視では,主に「ログ取得対象の設定」,「ログの取得」,「ログローテーションの設定」,「ログのスケジューリ
ングの設定」,
「ログの解析」などの作業を実施します.
ログの主な取得対象としてアクセスサーバやファイアウォール,IDS(侵入検知システム),Mail サーバ,Web サー
バなどが挙げられます.これらのログを監視することによって不正アクセスを迅速に発見・対処することができます.
ログはメンテナンスを行わないと肥大化していまうので,ログローテーションさせる必要があります.ログローテー
ションとは一定期間ごとにログファイルの古い部分を別ファイルに移動し,移動させたファイルも一定時間経過したも
のを破棄することでディスクの容量の圧迫を防ぐ仕組みです.
ログは,いざというときに迅速に情報を取り出さなければなりません.そのためにはログの一元的な管理が必要で
す.しかしながら,ログは様々なフォーマットで出力されるため,一元的なログ管理のためにログ解析ツールが必要と
なります.ログ解析ツールを導入することで,ログの解析をスムーズに行うことができます.詳しくは第 5 回で解説
します.
2.2 セキュリティ管理
セキュリティとは情報の機密性,完全性および可用性の維持です.提供するサービスや対象とするユーザを明確にし
セキュリティを確保しなくてはいけません.サーバは盗聴や改ざん,なりすまし,破壊,ウイルスやワーム,DoS 攻撃
など様々な脅威にさらされています.このような,ネットワーク上の脅威の他にも物理的な脅威があります.窃盗や地
震,火災,ちりやほこりも脅威となります.こういった脅威からサーバを守るためにセキュリティ管理をしなければな
りません.
セキュリティ管理では,セキュリティポリシーを明確にする必要があります.セキュリティポリシーとは情報セキュ
リティに関する基本方針のことです.広義には,セキュリティ対策基準や個別具体的な実施手順などを含みます.セ
キュリティポリシーを決めておくことにより,迅速な対応ができ,被害を最小限に留めることができます.詳しくは
第 6 回で解説します.
第3章
障害管理
サーバには必ず何らかの障害が発生します.障害管理の目的には障害対策や早期発見,早期解決が含まれます.
3.1 障害対策
サーバが障害に陥った際にもサービスの提供を続けられるようにするための手段として,サーバの多重化はよく用い
られる手段の 1 つです.サーバの多重化は何を多重化するかによって障害へ対応できるレベルが異なります.多重化の
例として,障害対応のレベルが低い順に,部品の多重化,ハードウェア全体の多重化,ソフトウェアも含めた全体の多
重化があげられます.また,ネットワークの多重化なども検討する必要があります.
3.1.1 部品の多重化
サーバは様々な部品で構成されています.多重化が行われていないサーバでは故障が発生するとサーバは停止してし
まいます.そこで,故障しやすい部品を多重化しておくことで,障害発生を防ぐことができます.
サーバの故障で最も多いのが HDD です.HDD は円盤状の板が高速で回転しているため,磨耗や熱による劣化など
が原因で故障してしまいます.そのため HDD を優先的に多重化する必要があります.HDD を多重化するための技術
として RAID (Redundant Array of Independent Disks) があります.RAID には 0 ∼ 6 までの 7 段階の方式があり,
環境に適した方式を選択する必要があります.
RAID0
RAID0 はストライピングとも呼ばれ,1 つのデータをブロック単位で分割し,図 3.1 のように複数の HDD に分散
して書き込みます.そのため HDD は 2 台以上必要となります.並列処理により書き込み速度は向上しますが,1 台で
も HDD が故障してしまうとデータの修復は困難です.
RAID1
RAID1 はミラーリングとも呼ばれ,図 3.2 のように全ての HDD にまったく同じデータを同時に書き込みます.ミ
ラーリングでは最低 2 台の HDD が必要となります.1 台の HDD が故障しても,他の HDD にデータが保存されてい
るのでシステムは稼動し続けることができます.しかし,HDD の使用可能な容量が構成する HDD が 1 台分の容量に
なるというデメリットがあります.
RAID5
RAID5 はパリティ RAID とも呼ばれ,RAID0 と同様にデータを分散させるのに加え,図 3.3 のようにデータから
パリティ(誤り訂正符号)を生成し,データ同様に分散させて保存します.RAID5 では最低 3 台の HDD が必要とな
ります.HDD が 1 台故障した場合,パリティからデータは復元可能となりシステムは稼動し続けることができます.
第3章
48
障害管理
図 3.1 RAID0
図 3.2 RAID1
RAID0+1
RAID はそれぞれのレベルの RAID を組み合わせて使用することできます.図 3.4 のように RAID0+1 は RAID0
と RAID1 を組み合わせたものです.RAID0+1 では最低 4 台の HDD が必要となります.RAID0+1 は,ストライピ
ングしたものをミラーリングします.RAID0 では 1 台でも HDD が故障してしまうとシステムが停止してしまいます
が,RAID0+1 ではミラーリングしているためシステムは稼動し続けることができます.
3.2 障害の早期発見・早期解決
49
図 3.3 RAID5
3.1.2 全体の多重化
必ずしも,多重化していた部品が故障するわけではありません.万が一に備えてサーバ全体を多重化することで,障
害へ対応することができます.サーバ機器を 2 台用意することで,1 台が故障しても,もう 1 台が稼動することによっ
て安定したサービスを提供することができます.ハードウェア全体の多重化にはコールドスタンバイとホットスタンバ
イの 2 種類に分類することができます.
コールドスタンバイは同じ構成のサーバを 2 組用意します.1 つは本番系で,もう 1 つは予備系です.本番系を通常
通り稼動させ,予備系は稼動させずに待機させます.本番系に障害が発生した場合,予備系が自動的に稼動し本番系の
替わりに処理を行います.コールドスタンバイは 2 台の同期が不要なためコストが低いですが,本番系と予備系の切り
替えに時間がかかり,システムの停止時間が長くなってしまいます.
ホットスタンバイはコールドスタンバイと同様に 2 組のサーバを用意し,本番系を通常通り稼動させますが,予備
系は本番系と同期をとりながら稼動しています.本番系に障害が発生した場合,瞬時に処理の切り替えが行われます.
ホットスタンバイは 2 台の同期が必要なためコストが高くなりますが,本番系と予備系の切り替えには時間がかからな
いため,可用性が高くなります.
3.2 障害の早期発見・早期解決
障害管理において,障害を発生させないように対策をとっておくのはもちろんですが,障害は必ず発生するものなの
で,障害の早期発見・早期解決は重要です.
障害を早期発見するには,障害を検出するための処理を自動化して定期的に実行し,異常があった場合には速やかに
管理者へ通知を行う仕組みを構築することが有効です.処理の自動化として crontab を用います.crontab については
4.2.1 節で詳細を述べます.
また,障害発見の方法は,発見すべき障害の種類によって異なります.発見すべき障害は事前に手順書を作成し,障
第3章
50
図 3.4 RAID01
障害管理
3.2 障害の早期発見・早期解決
51
害の種類と発見方法をまとめておきます.例として以下のようなフローに基づいて手順を考えます.
障害の発見
↓
障害の切り分け
↓
関係者への連絡
↓
障害箇所の切り離し
↓
障害の解析
↓
障害への対応
↓
関係者への連絡
↓
障害の記録
事前に対応手順を定めておき,素早く障害に対処することにより被害を最小限に抑え,復旧までの時間を短くするこ
とができます.
第4章
バックアップ
バックアップは障害からの早期解決に不可欠なものです.リカバリとはハードディスクなどを工場から出荷したとき
の状態に戻すことを言います.また,リストアとはバックアップデータからハードディスクなどをバックアップ時の状
態に戻すことを言います.
4.1 バックアップの種類
バックアップにはフルバックアップ,差分バックアップの 2 種類があります.フルバックアップは,バックアップの
必要があるデータを全て一括で複製する手法です.差分バックアップは前回のフルバックアップから追加,変更された
部分のみ複製する手法です.
フルバックアップは全てのデータをバックアップするため,バックアップに時間がかかります.しかし,一度のリス
トアで復元することができます.
差分バックアップには,フルバックアップされたデータから追加や変更されたデータのみを複製するので時間があま
りかからないという特徴があります.
実際にバックアップを取るときは,あまりシステムの利用の少ない日にフルバックアップを取り,多い日は差分バッ
クアップを取るのが一般的です.バックアップを取る際に tar コマンドや rsync コマンド, pgdump などが用いられ
ます.ファイルのバックアップを取るには tar コマンドを,ネットワーク越しにバックアップを取るには rsync コマ
ンドを用います.データベース (PostgreSQL) のバックアップを取る際は pgdump というユーティリティを用います.
4.2 バックアップの自動化
4.2.1 crontab
crontab とは指定した時刻に指定したコマンドを実行するコマンドです.このコマンドを実行することで,管理作
業を自動化することができます.
このコマンドを使用するには crond というデーモンが必要ですが,通常は OS インストール時に自動起動するよう設
定されています.
4.2.2 crontab の書き方
crontab の設定ファイルを編集するには,以下を用います.
$ crontab -e
vi エディタが起動し crontab の設定ファイルを編集することができます.
crontab の設定ファイルの書式は以下を 1 行で記述します.
4.3 シェルスクリプト
53
分 時 日 月 曜日 コマンド
分には 0 ∼ 59 を指定し,*とすると毎分の設定となります.時には 0 ∼ 23 を指定し,*とすると毎時の設定となり
ます.日には 0 ∼ 31 を指定し,*とすると毎日の設定となります.月には 1 ∼ 12 を指定し,*とすると毎月の設定と
なります.曜日には 0 ∼ 7 を指定し,0 と 7 は日曜日を表しています.コマンドには実行したいコマンドやスクリプト
を指定します. crontab ファイルが見るときはオプションに l をつけます.また crontab ファイルを削除したい場合
はオプションに r をつけます.
例えば以下のように記述します.
0 3 1 10 * /usr/local/bin/hoge.sh
この例では,10 月 1 日 3:00 に hoge.sh を実行します.また,以下のように記述したとします.
0 */2 * * * /usr/local/bin/hoge.sh
すると,2 時間ごとに hoge.sh を実行することになります.
4.2.3 at コマンド
crontab 以外にもコマンドを自動的に実行してくれるコマンドとして, at コマンド(以下, at )があります. at
は指定した時間に指定したジョブを実行するコマンドです.実行結果はメールでユーザに送られます.また,実行させ
るジョブはコマンドの標準入力ではなく,指定したファイルから取得することもできます.
以下は at の構文です.
$ at [option] TIME
オプションを表 4.1 に示します.TIME には実行したい時間を指定します.指定方法を表 4.2 に示します.
表 4.1 at オプション一覧
option
内容
-d
以前にキューに入れたジョブを削除する
-l
実行待ちのジョブの一覧を表示する
-m
ジョブ終了時に出力がなくてもメールを送信する
--help
at コマンドの使用法を表示する
4.3 シェルスクリプト
シェルスクリプトはコマンドをまとめて実行するスクリプトです.バックアップを取るためのシェルスクリプトを書
いて crontab に登録しておけば,自動でバックアップを取ることができます.
第 4 章 バックアップ
54
表 4.2
時間の指定方法
指定方法
内容
絶対時間
MM/DD/YY, DD.MM.YY で日付を指定する.hh:mm で時間を指定する
相対時間
絶対時間 + 遅延時間で指定する.遅延時間は<数値> [minutes |
hours | days | weeks ] で指定する
単語
noon, midnight, teatime, AM, PM, tomorrow で指定する.
バックアップは外部の HDD などに保存します.以下のシェルスクリプトは NAS (Network Attached Storage) に
ネットワーク経由でバックアップを保存します.NAS とはネットワークに直接接続されたファイルサーバです.
4.3.1 シェルスクリプトの書き方
以下のようにシェルスクリプト backup.sh を書きます.
backup.sh
#!/bin/sh
#変数の定義
DATE=‘date ’+%Y-%m-%d-%H%M%S’‘
BACKUPFILE=学籍番号.$DATE.ls-list
#マウントする(ディレクトリ名はアルファベットの大小に注意)
mount -t cifs //192.168.69.119/SHARE /mnt/backup
#バックアップ処理(ここではカレントディレクトリの一覧を保存している)
ls -lha > $BACKUPFILE 2 > /dev/null
mv $BACKUPFILE /mnt/backup
#アンマウント
umount /mnt/backup
backup.sh について説明します.#!から始まる行をシバンといい,スクリプトを実行する際のインタプリタのパスを
その後ろに記述します.スクリプトを書く際は必ず 1 行目にシバンを記述しなければなりません.インタプリタのパス
はシステムによって違う場合があります.そのため,ボーンシェル (Bourne Shell) を用いる場合は以下を実行しパス
を調べる必要があります.
$ which sh
次に DATE と BACKUPFILE という名前で変数を定義して,バックアップファイル名として使用しています.そ
して,ネットワーク上にある NAS をマウントします.マウントするディレクトリ (/mnt/bkup) は予め mkdir コマン
ドを用いて作成しておきます.その後,tar コマンドを用いて/etc 以下を全て圧縮し,バックアップとして NAS に保
存します.#の行はコメントとなります.記述したシェルスクリプトを実行するには以下のようにします.一度実行
し,正しくスクリプトが記述されているかを確認します.
4.3 シェルスクリプト
55
$ sh backup.sh
正しく動作していることが確認されたら crontab に登録し,定期的にバックアップを取るように設定します.
但し,このシェルを使用するには samba が必要です.そのため,以下のコマンドを用いて,samba のインストール
を行ってからシェルを実行してください.
$ sudo apt-get install smbfs
もし,シェルがエラーを返した場合は,インストールされているかどうかを確認してください.
第 2 回 演習課題
目標
crontab コマンドを用いて NAS にバックアップを保存します.
adduser, find, cat, head, tail コマンドを試して下さい.また,節 4.3.1 シェルスクリプトの書き方に
ある backup.sh を記述し, crontab に登録して下さい.
課題 1 adduser コマンド
adduser コマンドはユーザを追加するコマンドです.
1–1
自分の学籍番号 (ex. b1007999) がユーザ名のユーザを追加して下さい.パスワードは任意に設定して下さい.
1–2
作成したユーザのホームディレクトリがあることを確認して下さい(ex. /home/b1007999 は存在するか).
1–3
ホームディレクトリの所有者,グループを確認して下さい.
1–4
作成したユーザをスーパーユーザに追加して下さい.
課題 2 find, cat, head, tail コマンド
2–1
/以下にある syslog という名前のファイルを検索して下さい.
2–2
2-1 で検索したファイルのうち,/var 以下にあるものを結合させて表示させて下さい.
2–3
2-1 で検索したファイルのいずれかの先頭から 3 バイト分を表示して下さい.
2–4
2-1 で検索したファイルのいずれかの末尾から 2 行を表示して下さい.
課題 3 crontab コマンド
3–1
4.3.1 シェルスクリプトの書き方にある backup.sh を作成して下さい.
3–2
57
crontab に毎日 1 回 backup.sh が実行されるように登録してください.時間は確認のために現時刻の 3 分後程度に
設定するとよいでしょう.
参考文献
[1] 竹下隆史, 荒井透, 苅田幸雄, マスタリング TCP/IP 入門編, オーム社開発局(編), 株式会社オーム社, 2004
[2] 小関 裕明,小野 哲,サーバがわかる本, 株式会社オーム社, 2003
[3] 日経 BP 社 ITpro, http://itpro.nikkeibp.co.jp/
[4] 独立行政法人 情報処理推進機構, http://www.ipa.go.jp/
第3回
Web サーバのしくみ・構築・設定方法
WWW の発展と Web サーバの機能や役割,CGI によるアプリケーション実行や拡張について
説明します.OSS による Web サーバ実装の歴史と背景,代表的なサーバの特徴についても述
べます.また,HTTP の概要と通信方式を解説します.演習では,Apache2 の設定について解
説し,HTML ページ,CGI,PHP による簡単なプログラムを実際に作成・動作させることによ
り,Web サーバの動作について学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
Web の概要と歴史
インターネット上では,World Wide Web (WWW) というドキュメントシステムが標準的に用いられています.
World Wide Web を短縮し,一般に Web と呼ばれています.World Wide Web はハイパーリンクによって,相互的
に網目状につながれた様子がクモの巣を連想させることから,クモの巣− Web と名付けられたと言われています.
1.1 WWW
Web で用いられるドキュメント(Web ドキュメント)の記述には,HTML (Hyper Text Markup Language) など
のマークアップ言語が用いられており,ハイパーリンクと呼ばれる文書の参照によって,他のドキュメントとの相互参
照ができます.また,ハイパーリンクを用いて,ドキュメント同士を結びつける仕組みのことをハイパーテキストと呼
びます.
ハイパーリンクによる参照の際に用いられる参照先を示す識別子を URL (Uniform Resource Locator) と呼び,ド
キュメント転送のためのプロトコルを HTTP (HyperText Transfer Protocol) と呼びます
1.2 Web の歴史と発展
Web は欧州原子核研究機構 (CERN) の Tim Berners-Lee 氏により,研究所内の文章閲覧システムとして考案され
ました.当時としては画期的でしたが,発足当初の Web は HTML 文章の閲覧が主な目的であり,文章編集などの付
加機能はありませんでした.しかし,1991 年に一般公開されたると,90 年代中ごろのインターネットの発展とともに
爆発的に普及し,技術面でも様々な発展を遂げました.
現在の Web でのサービスは,文章を閲覧するだけではなく WebDAV によるサーバ上のファイル操作や,ストリー
ミングによる動画配信など多岐に渡っています.これらの技術は,Web のサービス提供機器である Web サーバやド
キュメント転送プロトコル HTTP の発展により実現されました.Web で用いられる技術は現在も進化しており,標準
化団体 W3C (World Wide Web Consortium) によってその標準化が進められています.
第2章
Web サーバ
Web システムのサービス提供機器を Web サーバと呼びます.WWW はクライアントサーバ方式のシステムであり,
Web クライアントの要求を Web サーバが返答することによって処理を行います.
代表的な Web サーバアプリケーションには Apache HTTP Server や Microsoft 社の IIS (Internet Information
Server) などがあります.また,Web クライアントの内部で Web ページの閲覧を目的としたものを,Web ブラウ
ザ (Internet Explorer や Mozilla Firefox などが有名です) と呼びます.
2.1 HTTP(HyperText Transfer Protocol)
HTTP は Web サーバとクライアント間でのデータ送受信に用いる,ハイパーテキスト転送用プロトコルのことです.
Web サーバは HTML で記述された Web ドキュメントを自身に保存しています.Web サーバは世界各地に多数存
在しており,どこの Web サーバの何というファイルかを特定するために URL が用いられます.クライアントは URL
で目的のサーバとファイル名を特定し,目的の Web サーバへ転送要求を行います.要求を受け取った Web サーバは
クライアントに対象となる HTML データを転送します.この要求,及び転送の際に使用するプロトコルが HTTP で
あり,一連の動作を行うシステムを WWW と呼びます.
サーバとクライアントは,一般的に図 2.1 のように HTTP でやり取りを行っています.
図 2.1 HTTP のアクセス概念図
第 2 章 Web サーバ
62
2.2 HTTP メッセージ
プロトコルとは,他者と通信をする際の手順などといった決まりごとを定めたものです.どの情報をどのような順番
で送信するか,プロトコルで厳密に定めることで通信が成り立っています.HTTP/1.1 の規約は,標準化団体 IETF
のワーキンググループによって策定された文書 RFC2616 によって規定されています.HTTP はプロトコルですので,
通信には様々な条件があります.ここでは HTTP の決まりごとである,HTTP メッセージについて説明します.
図 2.2 に,メッセージの概要を示します.HTTP メッセージは開始行,メッセージヘッダ,メッセージ本体という
3 つの部分からなります.それぞれの部分は改行で区切られます.まず,開始行にはクライアントからサーバへの要
求やそれに対するサーバからの返答が記述されます.ここは HTTP メッセージの本体とも言える部分であり,クライ
アントからの要求やサーバからの返答によって様式が変わります.クライアントからの要求時の HTTP メッセージを
HTTP Request メッセージ,サーバからの返答時の HTTP メッセージを HTTP Response メッセージと呼びます.
メッセージヘッダは複数個からなり,より詳細な要求内容やサーバへの伝達事項が記述されますが,これらは省略可
能です.また,HTTP のバージョンによって記述内容が変わります.最後のメッセージヘッダの後には改行コードが
入り,メッセージ本文が記述されます.ここにはサーバから送信される HTML の本文や初回の要求時にクライアント
が送信するログイン名,パスワードなどが記述されます.
図 2.2 HTTP メッセージの構成
2.2.1 HTTP Request メッセージ
図 2.3 に HTTP Request 開始行の構成を示します.メソッドにはサーバに要求する動作を記述し,パスには要求す
るファイルのパス,もしくは URL を記述します.HTTP バージョンにはクライアントが使用できる最も高い HTTP
のバージョン情報を記述します.それぞれの項目毎にスペースが挿入され,改行で終了します.
ここで記述されたパスで指定した Web サーバ上のファイル(またはディレクトリ)へ,メソッドに記述した動作
を要求します(2.4 節で解説するように,URL で指定するパスと実際のサーバ上でのパスは若干異なります).また,
使用可能なメソッドは HTTP のバージョンによって異なるため,HTTP バージョンの項目で Web サーバに使用し
2.2 HTTP メッセージ
63
図 2.3
HTTP Request 開始行の構成
ているプロトコルのバージョンを指定しています(2009 年現在,主流なバージョンは HTTP/1.1 です).メソッドの
一覧を表 2.1 に挙げます.主に使用されるメソッドは GET, HEAD, POST の 3 種類です.これら以外のメソッドは
HTTP1.1 未満では使用できません.
実際の Request メッセージの内容は,以下のようになっています.
GET /index.html HTTP/1.1
Accept: image/gif, image/jpeg, */*
Accept-Language: ja
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 5.1; ja;) Gecko/Firefox/3.0.1
Host: fun.ac.jp
Connection: Keep-Alive
1 行目が開始行,2 行目から 7 行目がメッセージヘッダ部分です.開始行に注目すると,クライアント側の実行可能
な HTTP バージョンが 1.1 で,要求するファイルのパスが /index.html,メソッドが GET となりページ,つまり
index.html を送るよう要求していることが分かります.
表 2.1
メソッド一覧
メソッド
説明
GET
サーバに対してページの取得を要求する.最も一般的に使用されるメソッド.
HEAD
サーバに対してヘッダのみの情報を要求する.
POST
CGI でよく使用されるメソッド.サーバ上の指定した場所にデータを転送する.
PUT
WevDAV 等で使用されるメソッド.サーバ上にファイルを作成する (HTTP1.1 以降).
DELETE
WevDAV 等で使用されるメソッド.サーバ上のファイルを削除する (HTTP1.1 以降).
OPTIONS
サーバに対して利用可能なメソッドを尋ねる (HTTP1.1 以降).
TRACE
経由先を調べるために使用されるメソッド.サーバに対してループバックを起こす (HTTP1.1 以降).
CONNECT
経由先にトンネリングを要求する (HTTP1.1 以降).
2.2.2 HTTP Response メッセージ
図 2.4 に HTTP Response 開始行の構成を示します.HTTP バージョンにはサーバが使用可能な最も高い HTTP
のバージョンを記述します.ステータスコードにはクライアントからの要求に対する結果を表す 3 桁の数字を記述しま
す.また,応答フレーズにはステータスコードの説明を記述します.HTTP Response 開始行の構成は,Request メッ
セージと同様に項目毎にスペースが挿入され,改行コードで終了します.
第 2 章 Web サーバ
64
図 2.4 HTTP Response 開始行の構成
HTTP バージョンには,サーバが扱える HTTP のバージョンが記述されます.ステータスコードには 3 桁の数字
が記述され,応答フレーズにはステータスコードと対になるメッセージが記述されます.ステータスコードの数字は
HTTP によってあらかじめ定められており,要求に対する返答を数字で表しています.応答フレーズのメッセージに
は,その数字ではなく文章で表現したものでサーバ側でその内容を変更することができます.あらかじめ応答フレーズ
を定めておくことで,返答を受け取ったユーザがそのエラー内容を理解しやすくする目的があります.
ステータスコードと応答フレーズによって,クライアントは要求の成否を知ることができます.また,エラー発生時
にはエラーの内容を知らせるメッセージが送信されるため,クライアントは再送などのエラー対策を行うことができま
す.実際の Response メッセージの内容は,以下のようになっています.
HTTP/1.1 200 OK
Date: Sun, 11 Jan 2004 16:06:23 GMT
Server: Apache/2.2.8 (Unix) (ubuntu/Linux)
Last-Modified: Sun, 07 Dec 2008 12:34:18 GMT
ETag: "1dba6-131b-3fd31e4a"
Accept-Ranges: bytes
Content-Length: 1234
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html
<html>
:
</html>
Request メッセージと同様に 1 行目が開始行で,2 行目から 10 行目がメッセージヘッダ部分です.開始行に注目す
ると,サーバの HTTP バージョンが 1.1 で,ステータスコードが 200,応答フレーズが OK となっていることから,ク
ライアントからの要求は成功だったということが分かります.また,12 行目以降には HTML によって記述された本文
が記述されています.
HTTP/1.1 までで定義されるステータスコードと,その応答フレーズの一覧を表 2.2 と表 2.3 に示します.ステー
タスコードは 200 番台で成功したことを表し,400, 500 番台では失敗を表すなど,3 桁の番号の 1 桁目で大まかな
分類ができます.この分類をクラスと呼びます.成功や転送要求など,正常にサービスが行われている場合は表面
に出ませんが,404–NotFound(要求したページが見つからない)や,403–Forbidden(アクセス不可,認証失敗),
503–ServiceUnavailable(サービス利用不可)などのステータスコードと応答フレーズは Web ブラウザによっては表
示されるため,目にしたことがあるかもしれません.
2.3 URL の仕組み
65
表 2.2 ステータスコードと応答フレーズ・正常の応答
分類
ステータスコード
応答フレーズ
説明
情報
100
Continue
処理を継続中.続きのリクエストを送信して
ください.
101
Switching Protocols
Upgrade ヘッダで指定したプロトコルに変
更して再要求してください.
成功
200
OK
成功.
201
Created
Location ヘッダで指定した場所に新しいコ
ンテンツが作成されました.
202
Accepted
要求は受理されました.ただし処理は完了し
ていません.
203
Non-AuthoritativeInformation
応答ヘッダはオリジナルサーバーが返したも
のとは異なりますが,処理は成功.
204
NoContent
コンテンツはありませんが,処理は成功しま
した.
205
ResetContent
要求を受理したので,現在のコンテンツ(画
面)を破棄してください.
転送
206
PartialContent
コンテンツを一部のみ返却します.
300
MultipleChoices
コンテンツ入手方法について複数の選択肢が
あります.
301
MovedPermanently
Location ヘッダで指定された別の場所に移
動しました.
302
Found
Location ヘッダで指定された別の場所に見
つかりました.そちらを見てください.
303
SeeOther
Location ヘッダで指定された他の場所を見
てください.
304
NotModified
更新されていません.If-Modified-Since ヘ
ッダを用いた場合に返却されます.
305
UseProxy
Location ヘッダで指定したプロキシを使用
してください.
306
307
(Unused)
TemporaryRedirect
未使用.
別の場所に一時的に移動しています.
2.3 URL の仕組み
URL は,図 2.5 のように構成されています.
プロトコル名には,http や ftp などといったプロトコル名を記述し,通信形式を明示しています.
ドメイン名には,接続するサーバ名(ホスト名)を記述します.インターネット上ではサーバの IP アドレスをドメ
イン名で表すことができるため,ここにドメイン名が記述された場合 DNS によって IP アドレスに変換して接続を行
います.IP アドレスが記述されている場合,DNS による名前解決をする必要はありません.ポート番号には,アクセ
第 2 章 Web サーバ
66
表 2.3
ステータスコードと応答フレーズ・エラーの応答
分類
ステータスコード
応答フレーズ
説明
クライ
400
BadRequest
要求が不正です.
401
Unauthorized
未認証.
402
PaymentRequired
支払いが必要.
403
Forbidden
アクセスが認められていません.
404
NotFound
見つかりません.
405
MethodNotAllowed
指定したメソッドはサポートされていませ
アント
エラー
ん.
406
NotAcceptable
許可されていません.
407
ProxyAuthenticationRequired
プロキシ認証が必要.
408
RequestTimeout
リクエストタイムアウトしました.
409
Conflict
リクエストがコンフリクト(衝突・矛盾)し
ました.
410
Gone
要求されたコンテンツは無くなってしまいま
した.
411
LengthRequired
Content-Length ヘッダを付加して要求して
ください.
412
PreconditionFailed
If-ヘッダで指定された条件に合致しませんで
した.
413
RequestEntityTooLarge
要求されたエンティティが大きすぎます.
414
Request-URITooLong
要求された URI が長すぎます.
415
UnsupportedMediaType
サポートされていないメディアタイプです.
416
RequestedRangeNotSatisfiable
要求されたレンジが不正.
417
ExpectationFailed
Expect ヘッダで指定された拡張要求は失敗
しました.
サーバ
500
InternalServerError
エラー
サーバーで予期しないエラーが発生しまし
た.
501
NotImplemented
実装されていません.
502
BadGateway
ゲートウェイが不正.
503
ServiceUnavailable
サービス利用不可能.
504
GatewayTimeout
ゲートウェイタイムアウト.
505
HTTPVersionNotSupported
この HTTP バージョンはサポートされてい
ません.
2.4 サーバパス
67
ス先の Web サーバが利用している TCP のポート番号が入ります.HTTP でのアクセスには通常 80 番ポートを用い
ますが,この場合はポート番号を省略することができます.
/パス/ファイル名には,リクエストするファイルのサーバ内でのパス,及びファイル名を/ で区切り記述します.本
来は,/パス/ファイル名を厳密に指定しなければ,対象ファイルへのアクセスはできません.しかし,Web サーバに
はパス名及びファイル名の補完機能があり,URL の不足部分を補う場合があります.
図 2.5 URL の構成
例えば,以下の URL を http://example.com/ としても,本来の URL である http://example.com/index.html
にアクセスが可能です.
http://example.com/index.html
これは Web サーバの機能によって,/index.html が補完されているからです.
これらを踏まえて,実際の URL を見てみると,プロトコルは http を使用しており,接続先のドメイン名は.com,使
用する TCP ポート番号は 80(省略している)
,要求するファイルのパスは / で,ファイル名は index.html だという
ことが分かります.
2.3.1 URL と URI
URI (Uniform Resource Identifier) とは RFC (Request for Comments) 文書によって規定された,コンピュータ
上で利用できるリソース(資源)に与えられた識別子の概念のことを指します.URI を,より実用的に具現化したもの
が URL (Uniform Resource Locator) と言えます.
URL は Web 上の特定の場所や特定のファイルを表すものです.しかし,Web 標準化団体 W3C は,URL は過去の
概念であると主張しています.Web 上にあるとはいえコンピュータで利用できるリソースなのだから,他のリソース
と同様に識別子を統一すべきだ,という考えから URL を包括する概念である URI に呼び名を統一させているのです.
2.4 サーバパス
2.2.1 節で述べたように,URL で指定するパスとサーバでのパスは若干異なる場合があります.これは,URL 記述
が長くならないための配慮やセキュリティ面での対応によるものです.
実際,Web サーバは自身が持つ全てのディレクトリやファイルを Web に公開しているわけではありません.外部に
公開すべきでないファイルは数多くあります(例えば,自身の設定ファイル)
.そこで,Web サーバは Web サーバアプ
リケーションの設定により,外部に公開するディレクトリを決定しています.その後,サーバ内でのパスを Web サー
バアプリケーションに登録し,外部からのアクセスに応じて自動的にパスを付加することでサーバへのアクセスを可能
としています.図 2.6 は /index.html という URL に,/public/home というパスを付加して接続処理を行う例を示し
ています.
第 2 章 Web サーバ
68
図 2.6
パス付加の流れ
第3章
Apache の概要と歴史
Apache (Apache HTTP Server) は,現在広く利用されているオープンソースの Web サーバソフトウェアで,小規
模な自宅サーバから商用の大規模サーバまで幅広く利用されています.このソフトウェアは非営利団体 Apache ソフ
トウェア財団 (The Apache Software Foundation) に所属する Apache HTTP Server Project によって開発されてい
ます.
3.1 Apache の歴史
Apache は,1995 年当時最も利用されていた Web サーバアプリケーションである NCSA httpd 1.3 をベースに開発
が始まり,Linux を含む UNIX 系 OS を中心に幅広い人気を獲得しました.Apache は無償で公開され,世界中のプロ
グラマたちの手によって,長年に渡り開発が続けられています.Apache は元々 NCSA httpd の細かいバグを修正し
たり,新しい機能を追加するためのパッチ集として公開されていましたが,途中から単体の Web サーバソフトウェア
として公開されました.
3.2 Apache のバージョン
Apache は従来の 1.3 系や新しく開発された 2.0 系,最新の 2.2 系の 3 種類のバージョンをサポートしています.最
近では,2.2 系が主流のバージョンとなっており,2.2 系で行われたバグ修正が 2.0 系や 1.3 系に反映されないこともあ
ります.また,1.3 系では機能拡張のバージョンアップはされず,ほぼセキュリティ関係の修正のみとなっています.
1.3 系
安定志向を好むユーザーに利用されています.
2.0 系
新しい機能を使いつつも安定志向を好むユーザーに利用されています.
2.2 系
2009 年 10 月時点で,Apache ソフトウェア財団が最も利用を推奨するバージョンです.現行リリースされている
Apache で最高のバージョン,と銘打って公開されています.
本講義では,Apache 2.2 を用いて演習を行います.
第4章
Apache 2.2 による,Web サーバの構築
Apache 2.2(以降 Apache)を用いた Web サーバの構築方法について解説します.
4.1 Apache のインストール
演習用の PC には,Apache が既にインストールされています.参考としてコマンドを記載します.
参考)以下のコマンドを実行するとインストールが開始されます.
$ sudo apt-get install apache2
4.2 Apache のバージョン確認
以下のコマンドで,バージョンが確認できます.
$ apache2 -v
Server version: Apache/2.2.8 (Ubuntu)
Server built:
Jun 18 2009 08:43:38
4.3 Apache の起動確認
Apache が起動しているか,実行中のプロセスを表示させることで確認します.以下のコマンドで,全てのプロセス
を表示します.
$ ps ax
以下のように,実行中のプロセスに/usr/sbin/apache2 -k start という項目が含まれていれば,Apache が起動中
です.
PID TTY
STAT
1 ?
Ss
0:00 /sbin/init
2 ?
S<
0:00 [kthreadd]
3 ?
S<
0:00 [migration/0]
…
TIME COMMAND
4.4 Web ブラウザによるアクセス
71
6151 ?
Ss
0:00 /usr/sbin/apache2 -k start
6155 ?
S
0:00 /usr/sbin/apache2 -k start
6156 ?
S
0:00 /usr/sbin/apache2 -k start
6157 ?
S
0:00 /usr/sbin/apache2 -k start
6158 ?
S
0:00 /usr/sbin/apache2 -k start
6159 ?
S
0:00 /usr/sbin/apache2 -k start
6162 pts/0
R+
0:00 grep apache2
4.4 Web ブラウザによるアクセス
OS 起動時,またはインストール完了時に Apache が自動的に起動する設定がなされているので,Web ブラウザを用
いて動作確認を行います.Web ブラウザを起動し,URL に http://localhost/ と入力します.図 4.1 の画面が表示
されれば Apache は起動しています.
図 4.1
Apache の動作確認
4.5 Apache の起動・再起動・停止コマンド
Apache の起動や停止,再起動には以下のコマンドを用います.
第4章
72
Apache 2.2 による,Web サーバの構築
起動
$ sudo /etc/init.d/apache2 start
再起動
$ sudo /etc/init.d/apache2 restart
停止
$ sudo /etc/init.d/apache2 stop
確認のため,停止コマンドを実行します.以下のメッセージが出たら,Apache は停止状態になっています.
* Stopping web server apache2
4.3 節と同様の手順で,実行中のプロセスを確認します.実行中のプロセスに /usr/sbin/apache2 -k start が無けれ
ば,Apache は停止しています.
$ ps ax
PID TTY
STAT
TIME COMMAND
1 ?
Ss
0:00 /sbin/init
2 ?
S<
0:00 [kthreadd]
3 ?
S<
0:00 [migration/0]
…
/usr/sbin/apache2 -k start
が無いことを確認
この状態で Web ブラウザから http://localhost/ にアクセスすると,アクセスに失敗し,図 4.2 のような画面が
表示されます.
4.6 Apache のスタートアップ設定
Apache 2.2 ではインストール完了時に自動的に起動するよう設定されています.設定が必要な場合は,以下のよう
に設定を行います.
参考)Ubuntu 系のディストリビューションでは,OS 起動時の設定を行うツールとして sysv-rc-conf を使用します.
sysv-rc-conf は標準でインストールされていないため,以下の操作でインストールを行う必要があります.
$ sudo apt-get install sysv-rc-conf
sysv-rc-conf のインストール後,以下の操作で Apache のスタートアップ設定,サービスの確認が行えます.
$ sudo sysv-rc-conf apache2 on
$ sudo sysv-rc-conf ?list | grep apache2
apache2 0:off 1:off 2:on 3:on 4:on 5:on 6:off
Apache を自動的に起動したくない場合の操作は以下の通りです.
4.7 Apache の設定
73
図 4.2
Apache の停止確認
$ sudo sysv-rc-conf apache2 off
$ sudo sysv-rc-conf ?list | grep apache2
apache2 0:off 1:off 2:off 3:off 4:off 5:off 6:off
4.7 Apache の設定
Apache2 の各種設定ファイルは,/etc/apache2 に格納されています.図 4.3 及び表 4.1 に初期状態でのディレクト
リの構造とその概要を示します.
表 4.1 /etc/apache2 概要
ファイル名
説明
apache2.conf
apache2 の全体設定用ファイル
ports.conf
待ち受けポート番号の設定用ファイル
mods-available
モジュールファイルが置かれるディレクトリ
mods-enabled
使用するモジュールへのリンクファイルが置かれるディレクトリ
sites-available
ホスト名など,サイト定義ファイルが置かれるディレクトリ
sites-enabled
使用するサイト定義ファイルへのリンクファイルが置かれるディレクトリ
第4章
74
図 4.3
/etc/apache2 ディレクトリ構造
Apache 2.2 による,Web サーバの構築
4.8 メインサイトの作成
75
4.8 メインサイトの作成
Apache2 のインストール直後には,デフォルトサイトとして sites-available/default が登録されています.先ほど
Apache の起動確認を行った図 4.1 の It Works が表示されるページは,このディレクトリに格納されています.この
項目ではデフォルトページを無効化し,新たにメインサイトを作成していきます.
メインサイト用のサイト定義ファイルを作成
以下の操作で,sites-available ディレクトリ内に b1007000 というサイト定義用のファイルを新規作成します.
$ cd /etc/apache2/sites-available/
$ sudo vi b1007000
以下の内容を入力し保存します.
NameVirtualHost *
<VirtualHost *>
ServerAdmin webmaster@b1007000
#管理者のメールアドレス
DocumentRoot /home/www/b1007000/public_html
#公開するドキュメントディレクトリ.ここに index.html を作成.
ServerName b1007000
#サーバのホスト名
ErrorLog "/home/www/b1007000/logs/error_log"
#エラーログを記録するファイル
CustomLog "/home/www/b1007000/logs/access_log" combined
#アクセスログを記録するファイル
<Directory "/home/www/b1007000/public_html">
Options None
AllowOverride None
Order allow,deny
Allow from all
</Directory>
#公開ディレクトリに関する設定
</VirtualHost>
第4章
76
Apache 2.2 による,Web サーバの構築
VirtualHost について
上記のサイト定義ファイルでは,Apache の特徴的な機能の 1 つである VirtualHost を使ってホストを定義していま
す.VirtualHost とは,その名の通り仮想的なホストによるサービスを提供する機能のことです.通常,Web サーバア
プリケーションに割り当て可能なドメイン名と IP アドレスは 1 種類に限られます.この場合,複数のドメインに渡る
サービスを扱うためには,図 4.4 のように各ドメインにつき 1 台ずつサーバを用意するか,または,図 4.5 のように
NIC (Network Interface Card) に複数の IP アドレスを割り当て,ドメインの数だけ Web サーバアプリケーションを
起動させるなどの対策が考えられます.
ここで挙げている例の他にも,複数のドメインに渡るサービスの提供には様々な解決法があります.その中の 1 つ
が図 4.6 に示す Apache の VirtualHost です.VirtualHost では複数の仮想的なドメインを立ち上げ,それぞれにド
メイン名,もしくは IP アドレスを割り当てることによって,複数のドメインに渡るサービス提供を実現しています.
ここで,仮想ホストの管理は Apache 自身が行っているため,Web アプリケーションを複数起動するといったリソー
スの無駄使いも生じません.4.8 節で作成したサイト定義ファイル (/etc/apache2/sites-available/b1007000) では,
b1007000 というドメイン名を受け付ける VirtualHost を起動するように設定しています.
デフォルトサイトの無効化及びメインサイトの有効化
デフォルトサイトを無効化し,メインサイトを有効化するために次の操作を行います.
以下の操作で,デフォルトサイトを無効化します.
$ cd sudo a2dissite 000-default
先ほど作成したメインサイトを有効化します.
$ sudo a2ensite b1007000
4.9 index.html の作成
公開ディレクトリの作成
Web に公開するディレクトリを作成します.
$ sudo mkdir /home/www
$ sudo mkdir /home/www/b1007000
$ sudo mkdir /home/www/b1007000/public html
ログディレクトリの作成
ログファイルを保存するディレクトリを作成します.
$ sudo mkdir /home/www/b1007000/logs
index.html の作成
公開ディレクトリ内に index.html を作成します.
$ cd /home/www/b1007000/public html
$ sudo vi index.html
以下の内容を入力し,保存します.
4.9 index.html の作成
77
図 4.4
複数ドメイン割り当ての例 1
図 4.5
複数ドメイン割り当ての例 2
図 4.6 VirtualHost の概要
第4章
78
Apache 2.2 による,Web サーバの構築
<html>
<head>
<title>example</title>
</head>
<body>example</body>
</html>
Apache の再起動とブラウザでの表示確認
以下の操作で,Apache を再起動します.
$ sudo /etc/init.d/apache2 restart
再起動後,図 4.7 のように,Web ブラウザを用いて index.html が表示されていることを確認します.
図 4.7 index.html の確認
4.10 アクセスログの確認
79
4.10 アクセスログの確認
4.8 節の設定では,b1007000 へのアクセスログ,及びエラーログは/var/log/b1007000 に保存されます.4.9 節で
b1007000 へアクセスを行っていますので,アクセスログの内容を確認します.以下のコマンドで,ログをターミナル
上に表示させます.
$ cat /home/www/b1007000/logs/access log
127.0.0.1 - - [05/Oct/2009:18:17:21 +0900] "GET /index.html HTTP/1.1"
200 74 "-" "Mozilla/5.0~(X11; U; Linux i686; ja; rv:1.9b5)
Gecko/2008 050509 Firefox/3.0b5"
上記のログから 2009 年 10 月 5 日の 18 時 17 分に,127.0.0.1 へのアクセスがあり,index.html の GET を受けた
ことが分かります.さらに,レスポンスコードが 200 であることから,この GET 要求は成功していることが分かり
ます.
次に,エラーの場合を確認します.ブラウザから,http://localhost/brank.html へアクセスします.存在しな
い HTML ファイルへのアクセスなので,ブラウザにはエラー画面が表示されます.ここで再度アクセスログを確認し
ます.
$ cat /home/www/b1007000/logs/access log
127.0.0.1 - - [05/Oct/2009:18:18:18 +0900] "GET /brank.html HTTP/1.1"
404 325 "-" "Mozilla/5.0~(X11; U; Linux i686; ja; rv:1.9b5)
Gecko/2008050509 Firefox/3.0b5"
上記のログから 127.0.0.1 へのアクセスがあり,brank.html の GET 要求を受けたことが分かります.レスポン
スコードは 404 であることから,存在しないファイルへのアクセスであり要求は失敗したことが分かります.
さらに,エラーログも確認します.
$ cat /home/www/b1007000/logs/error log
[05/Oct/2009:18:18:18 +0900][error] [client 127.0.0.1] File does not ex
ist: /home/www/b1007000/public_html/brank.html
このログには,エラーが発生した時刻やアクセス元,エラー発生時に要求されたパスが記載されています.
4.11 モジュール
モジュールとは部品を意味し,それぞれのモジュールが組み合って 1 つの製品となる構造をモジュール構造といいま
す.Apache はモジュール構造を採用しており,必要な機能をその都度追加していくことができます.以下のコマンド
を実行することで,現在 Apache に組み込まれているモジュールを表示できます.
$ apache2ctl -M
Loaded Modules:
core_module~(static)
log_config_module~(static)
logio_module~(static)
mpm_prefork_module~(static)
...
第4章
80
Apache 2.2 による,Web サーバの構築
4.12 PHP モジュールの導入
PHP を動作させるため,Apache に PHP モジュールを導入します.
演習用の PC には,PHP5 (PHP Version 5) が既にインストールされていますが,参考としてコマンドを記載し
ます.
参考)以下のコマンドを実行すると.インストールが開始されます.
$ sudo apt-get install php5 libapache2-mod-php5
4.13 PHP5 の設定
PHP5 の動作は /etc/php5/apache2 ディレクトリ内にある設定ファイル (php.ini) に依存します.ここでは,PHP
実行時にネックとなりやすい,アップロードファイルの最大サイズを設定します.
PHP が動作するサーバの環境は様々です.大きすぎるファイルを受け付けると,サーバのリソースを浪費し,動作
が不安定になる可能性があります.そのため,初期状態ではアップロードファイルの最大サイズは 2MB に設定されて
います.
しかし,画像ファイルなどをアップロードしたい場合にはこのサイズでは小さすぎるため,より大きなサイズを設定
します.例えば,これを 8MB などの大きな値に設定するとします.すると,アップロードファイルの最大サイズ変更
に伴い,POST データの最大サイズ,スクリプトに割り当てるメモリ領域のサイズも変更する必要があります.
それぞれの項目名は以下の通りです.
表 4.2 php.ini の項目名
項目名
説明
upload max filesize
アップロードファイルの最大サイズ
post max size
POST データの最大サイズ
memory size
割り当てメモリ領域のサイズ
PHP のマニュアルでは,upload max filesize ¡ post max size ¡ memory limit となるような設定を推奨しています.
これにしたがい,ここでは upload max filesize を 8MB に,post max size を 16MB に,memory limit を 32MB に
設定します.
以下の操作で,php.ini を開きます.
$ cd /etc/php5/apache2
$ sudo vi php.ini
以下の個所を変更します.また,このファイルは長大なファイルなので,検索機能などを利用して編集した方がよい
でしょう.
…
…
;;;;;;;;;;;;;;;;;;;
; Resource Limits ; 260 行目付近
4.14 info.php の作成
81
;;;;;;;;;;;;;;;;;;;
max_execution_time = 30
; Maximum execution time of each script, in seconds
max_input_time = 60
; Maximum amount of time each script may spend parsing request data
;max_input_nesting_level = 64
; Maximum input variable nesting level
memory_limit = 16M ← 32M に変更
; Maximum amount of memory a script may consume (16MB)
…
…
;;;;;;;;;;;;;;;;;
; Data Handling ; 450 行目付近
;;;;;;;;;;;;;;;;;
…
…
; Maximum size of POST data that PHP will accept.
post_max_size = 8M ← 16M に変更
…
…
;;;;;;;;;;;;;;;;
; File Uploads ; 550 行目付近
;;;;;;;;;;;;;;;;
; Whether to allow HTTP file uploads.
file_uploads = On
; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
;upload_tmp_dir =
; Maximum allowed size for uploaded files.
upload_max_filesize = 2M ← 8M に変更
…
…
4.14 info.php の作成
PHP5 の動作確認のため,簡単な PHP のプログラムを作成します.info.php というファイルを作成し,phpinfo()
関数を動作させてみます.phpinfo() は,サーバで動作している PHP のバージョン情報や設定など,動作している
PHP に関する情報を表示する関数です.
第4章
82
Apache 2.2 による,Web サーバの構築
以下の操作で,公開ディレクトリ内に info.php を作成します.
$ cd /home/www/b1007000/public html
$ vi info.php
以下の内容を入力し,保存します.
<?php
phpinfo();
?>
http://localhost/info.php に Web ブラウザでアクセスし,図 4.8 のように info.php が表示されていることを確認
します.4.13 節で変更した設定もこの画面で確認できます.
図 4.8 info.php
4.15 Perl の導入
演習用の PC には,Perl5 が既にインストールされていますが,参考としてコマンドを記載します.
参考)以下のコマンドを実行すると,インストールが開始されます.
$ sudo apt-get install perl5
4.16 CGI スクリプトの動作設定
83
4.16 CGI スクリプトの動作設定
4.8 節で作成したサイト定義では,サーバでの CGI スクリプトの動作は許可されていません.そこで,サイト定義
ファイルに設定を追記します.
$ cd /etc/apache2/sites-available/
$ sudo vi b1007000
以下のように編集します.
NameVirtualHost *
<VirtualHost *>
・
・
<Directory "/home/www/b1007000/public_html/cgi-bin/">
Options +ExecCGI
AllowOverride None
Order allow,deny
Allow from all
</Directory>
AddHandler cgi-script .cgi
・
・
</VirtualHost>
Options の設定により,cgi-bin 以下に設置されている CGI スクリプトが動作可能となります.また,AddHandler
cgi-script の項目で動作を許可する拡張子を追記することにより,CGI スクリプトとしてその拡張子を持つファイルを
読み込むようになります.上記設定では,.cgi という拡張子のファイルを CGI スクリプトとして認識するようになっ
ています.
サイト定義ファイルの編集後は Apache の再起動が必要となるため,以下の操作で再起動します.
$ sudo /etc/init.d/apache2 restart
4.17 test.cgi の作成
Perl5 の動作確認のために,簡単な CGI スクリプトを作成します.test.cgi というファイルへのアクセスで,スクリ
プトを実行します.
以下の操作で,公開ディレクトリ内に CGI 用ディレクトリ cgi-bin と,CGI ファイル test.cgi を作成します.
$ cd /home/www/b1007000/public html/cgi-bin
$ sudo vi test.cgi
以下の内容を入力し,保存します.
第4章
84
Apache 2.2 による,Web サーバの構築
print "Content-type: text/html; charset=iso-8859-1\n\n";
print "\n";
foreach $v (sort(keys(%ENV))) {
$x = $ENV{$v};
$x =~ s|\n|\\n|g;
$x =~ s|"|\\"|g;
print "${v}=\"${x}\"<BR>\n";
}
この CGI スクリプトには実行環境のマシン,この場合は Apache が動作しているサーバの環境変数を取得し,表示
する命令が書かれています.
CGI はサーバ上で動作するプログラムです.アクセスしたユーザが,サーバ上で実行する形になります.test.cgi
を作成した直後では他ユーザの実行は認められていません.このままアクセスするとパーミッションエラーが発生し
て,HTTP 500 エラーが返信されてしまいます.
以下の操作で,test.cgi のパーミッションを変更して他ユーザに実行権を割り当てます.
$ sudo chmod 755 /home/www/b1007000/public html/cgi-bin/test.cgi
http://localhost/cgi-bin/test.cgi にアクセスし,ブラウザで図 4.9 のように test.cgi が表示されているこ
とを確認します.サイト定義の不備などで CGI が実行できない環境では,図 4.10 のような画面が表示されます.これ
は,CGI のソースがそのまま表示されています.
図 4.9 test.cgi の実行例
4.17 test.cgi の作成
85
図 4.10 test.cgi の失敗例
第 3 回 演習課題
目標
Web サーバを立ち上げます.
Apache 2.2 を用いて,HTML,CGI,PHP の各種閲覧サービスを提供するサーバを立ち上げて下さい.
課題 1 公開ディレクトリの作成
4.9 節を参考に,Web 公開用のディレクトリを作成して下さい.公開ディレクトリは /home/www/(学籍番
号)/public html として下さい.
課題 2 メインサイトの作成
4.8 節を参考に,サイト定義ファイルを /etc/apache2/sites-available ディレクトリ内に作成して下さい.サイト定
義のファイル名は,各自の学籍番号(b1007000 など)として下さい.サイト定義ファイルの作成後,作成したサイト
定義を有効にして下さい.
課題 3 index.html の作成
4.9 節を参考に index.html を作成し,公開ディレクトリ内に配置して下さい.index.html は,タイトル,本文
ともに,学籍番号を表示するようにして下さい.ブラウザより,http://
(IP アドレス)/index.html へアクセスし,
index.html の表示を確認して下さい.
課題 4 test.cgi の作成
4.16 節,4.17 節を参考に,test.cgi を作成して下さい.CGI 配置用ディレクトリ cgi-bin を public html 内に作
(
成し,CGI ファイルは /home/www/b1007000/public html/cgi-bin へ配置して下さい.ブラウザより,http://
IP アドレス)/cgi-bin/test.cgi へアクセスし,test.cgi の動作を確認して下さい.
課題 5 info.php の作成
4.14 節を参考に,info.php を作成して下さい.info.php ファイルは,/home/www/b1007000/public html へ配
置して下さい.ブラウザより,http://(IP アドレス)
/info.php へアクセスし,info.php の動作を確認して下さい.
参考文献
[1] Paul G. Sery & Jay Beale 有限会社ヴァインカーブ (監訳), Red Hat Linux Internet Server, ソフトバンクパブ
リッシング, 2003
[2] The Apache Software Foundation, http://httpd.apache.org/
第4回
メールサーバのしくみ・SMTP サーバの構築・
設定方法
メールサーバの基本的な構成を解説し,メールを送信する SMTP,受信したメールをクライア
ントにダウンロードする POP3,IMAP など関連するプロトコルと技術を紹介します.Linux で
動作する SMTP サーバおよび POP サーバの構築・設定手順を解説します.演習では,mail コ
マンドによるメール送信や Web アプリケーションからのメール送信を実際に試し,メールサー
バの動作について学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
電子メール
電子メール(以下メール)は,ネットワーク上で提供されるサービスの 1 つです.サービス提供装置であるメール
サーバの働きによって,クライアント同士でのメール送受信が可能になります.
1.1 メール送受信のしくみ
メール送受信のしくみは,私たちが慣れ親しんだ現実世界の郵便のシステムとほぼ変わりません.図 1.1 と図 1.2
で,郵便とメールを比較しています.まず送信者は,自分が知っているメールサーバにメールを送信します.受信した
メールサーバはあて先(メールアドレス)を参照して,あて先のメールサーバへ転送を行います.受け取ったメール
サーバはメールを保管(保管しておく場所をメールボックスと言います)しておき,受信者が受け取りに来たらメール
を渡します.
MTA (Message Transfer Agent) と MUA (Mail User Agent)
メールの送受信を行うソフトウェアは,MTA と MUA の 2 種類に分けられます.MTA はメールサーバ上で動作し,
メールサーバ間でのメールの転送処理や受け取ったメールのメールボックスへの保管処理を取り扱います.代表的なソ
フトウェアに sendmail や Postfix,Dovecot などがあります.これらは 3 章で詳しく紹介しています.
対して MUA はクライアント上で動作し,メールの読み書きやメールサーバへの送信,メールボックスからのメール
の受信を取り扱います.メールクライアントソフトは,一般にメーラと呼ばれています.代表的なオープンソースソフ
トウェアとして Thunderbird などが挙げられます.
1.2 メールアドレスのしくみ
図 1.3 にメールアドレスの概要を示します.ローカル部には,メールを受信するユーザのアカウントやユーザ ID な
どが記述されます.@で区切り,あて先のメールサーバのホスト名,またはメールサーバが所属するドメイン名を記述
します.ドメイン名でも送信可能となるのは,DNS によって送信先の IP アドレスを参照することができるからです.
詳細は 2.5 節に記します.
これらを踏まえて,メールアドレスを見直すと,以下に示す実際のメールアドレスでは,アカウント名が b1007000,
あて先ドメイン名が example.jp であることが分かります.
[email protected]
1.2 メールアドレスのしくみ
91
図 1.1
図 1.2
郵便のしくみ
メールアドレスのしくみ
図 1.3 メールアドレスの概要
第2章
SMTP と POP/IMAP
メールの送受信は,いくつかの段階に分けて行われます.段階に応じて SMTP や POP,IMAP というプロトコル
がそれぞれ用いられます.また,あて先の特定には DNS も利用されます.この章では,メール送受信時に用いられる
各プロトコルの詳細や,あて先特定の仕組みについて解説します.
2.1 メール送受信時の動作
メール送受信の動作を段階的に分けて考えます.
1. 送信者が MUA によりメールを作成して,送信する.
2. メールを受け取った MTA はメールアドレスを確認して,あて先近くへの MTA へ転送する.
3. あて先の MTA は,受信者アカウントのメールボックスへ受信したメールを保存する.
4. 受信者が MUA を使い,MTA にある自分のメールボックスからメールを受け取る.
図 2.1 メール送受信時の動作
1 の動作ではメールの送信が行われ,2 の動作では転送が行われています.3 の動作ではメールボックスへの転送(保
存)が行われています.メールボックスとは MTA が管理するメールの一時保管庫で,自身が受け持つクライアントあ
てのメールを一時的に保存しておく場所です.4 の動作では,受信側の MUA がメールボックスに保存されているメー
ルを受け取っています.
それぞれの動作に用いるプロトコルはあらかじめ決められており,送信や転送,メールボックスへの保存(1 から 3 の
動作)には SMTP が用いられます.MUA がメールボックスから受信する際(4 の動作)には,POP または IMAP と
いうプロトコルのいずれかが用いられます.これらのプロトコルを扱うソフトウェアを総称して MTA と呼び,MTA
ソフトウェアを動かすサーバを一般的にメールサーバと呼びます.これら一連の,SMTP 及び POP/IMAP を考慮し
たメール送受信の動作を図 2.2 に示します.
2.2 SMTP
93
図 2.2
プロトコル別のメール送受信動作
2.2 SMTP
SMTP (Simple Mail Transfer Protocol) とはメールを送る(転送する)際に使われる,RFC2821 で定義されるプ
ロトコルです.SMTP の動作の概要は 2.1 節で述べた通りですが,ここではさらに詳細な動作を説明していきます.
SMTP はコマンドレスポンス型のプロトコルです.一般的には TCP25 番ポートでセッションを確立し,通信を行
います.SMTP の代表的なコマンドを表 2.1 に,主なレスポンスを表 2.2 に示します.
表 2.1 SMTP の主なコマンド
コマンド名
説明
HELO
セッション接続開始
EHLO
HELO の拡張版セッション接続開始
MAIL
メールの送信元
RCPT
メールのあて先
DATA
メールの本文
QUIT
セッション切断
これらのコマンドとレスポンスを参考に,実際のメール送信時のサーバとクライアントのやり取りを確認します.
example.jp のユーザ b1007000 から,example2.jp のユーザ b1008000 宛てに送信した場合の例を示します.
1.
220 smtp.example.jp … SMTP ready
2.
HELO b1007000.example.jp
3.
250 OK
4.
MAIL FROM:<[email protected]>
5.
250 OK
6.
RCPT TO:<[email protected]>
第2章
94
SMTP と POP/IMAP
表 2.2 SMTP の主なレスポンスコードと系
レスポンスコード
説明
及び系
7.
250 OK
8.
DATA
9.
250 OK
1xx
正常・レスポンス待ち系
2xx
正常系
220
準備完了・受信応答
221
切断
250
コマンド正常終了
3xx
正常・追加のコマンド待ち系
354
本文入力待ち
4xx
一時的なエラー系
421
サービス利用不可による切断
450
メールボックスでの一時的なエラー
5xx
恒久的なエラー系
500
構文エラー
501
コマンドパラメータエラー
502
コマンド利用不可(未実装)
550
メールボックスでの恒久的なエラー
551
ユーザが見つからない
10. 354 Enter mail, end with “.” on a line by ltself
11 .… 本文 …
12. …
13. .
14. 250 OK
15. QUIT
16. 221 derivering mail
1 行目は SMTP での接続を受け付けたことを示す,サーバからのレスポンスです.2 行目以下に,コマンドとレスポ
ンスのやり取りが続きます.
セッション開始後,2 行目で,まずクライアントは HELO または EHLO を送信します.HELO または EHLO に続
けて,クライアントのホスト名を送信します.3 行目で,サーバから OK レスポンスが返信されると,4 行目でクライ
アントは MAIL コマンドで送信元のメールアドレスを送信します.さらに 5 行目の OK を待って,6 行目で RCPT で
送り先メールアドレスを送信します.その後,クライアントは 8 行目のように DATA を送信します.
DATA を受け付けたサーバは 10 行目のように 354 を返信してメール本文入力待ちの状態に移行し,クライアントか
ら送信される本文を順次記録していきます.13 行目で,本文を記述し終わったクライアントはドット (.) を送信し,本
文の終了を伝えます.正常に本文を受け付けたサーバは 14 行目で OK を返信します.
2.3 POP3
95
15 行目で,全て伝えた終わったクライアントは QUIT を送信し,サーバへセッション終了の合図を送信します.16
行目で,サーバは 221 を返し切断を了承し,セッションを切断します.以上で,メールの送受信が終了します.途中で
エラーが発生した場合,サーバは 4xx や 5xx のレスポンスでエラーを通知し,クライアントは再送などそれに見合っ
た対処を行います.
このやり取りは,MUA から MTA へのやり取りでも,MTA 同士のやり取りでも変わりません.MTA 同士でのや
り取りの場合は,メール送信を受け付けたサーバがクライアントとして転送先サーバに接続することになります.
EHLO
現在のメールは,単に文章を送るだけのものではありません.ファイルの添付や本文の暗号化など,求められる機
能は様々です.HELO はセッションの開始を伝えるためだけのもので,付加機能はほぼありません.EHLO では添付
ファイルの許容サイズや暗号化機能の有無などを,セッション開始と同時に接続先サーバへ質問します.回答を受け
取ったクライアントはそれに見合ったデータを送信することで,メールの機能拡張が可能となります.以下に,EHLO
へのレスポンスの例を示します.2 行目から 13 行目までで,SMTP サーバが使用可能な拡張機能を回答しています.
1.
>>> EHLO b1007000.example.jp
2.
250- smtp.example.com Hello localhost [127.0.0.1], pleased to meet you
3.
250-ENHANCEDSTATUSCODES
4.
250-PIPELINING
5.
250-EXPN
6.
250-VERB
7.
250-8BITMIME
8.
250-SIZE
9.
250-DSN
10. 250-ETRN
11. 250-AUTH DIGEST-MD5 CRAM-MD5
12. 250-DELIVERBY
13. 250 HELP
14. >>> VERB
15. 250 2.0.0 Verbose mode
16. >>> MAIL From:<b1007000.example.jp> SIZE=45 AUTH= test.fun.ac.jp
17. 250 2.1.0 <b1007000.example.jp>... Sender ok
・
・
2.3 POP3
POP3 (Post Office Protocol Ver.3) とはメールボックスからメールを取り出す際に使われる,RFC1939 で定義さ
れるプロトコルです.通常,TCP110 番でセッションを確立し,SMTP と同様にコマンドレスポンスでの通信を行い
ます.
POP3 の後ろに付いている数字の 3 はバージョンを表しています.POP はバージョンアップによって機能拡張や不
具合の修正が行われています.現在使用されている POP は原則としてバージョン 3 であり,古いバージョンのものは
第2章
96
SMTP と POP/IMAP
使用されていません.本テキストで扱う POP についてもバージョン 3 とし,以降,単に POP とある場合には POP3
を示すこととします.
POP のセッションは 3 つに分かれていて,それぞれ認証ステート,トランザクションステート,更新ステートと呼
ばれます.認証ステートで,クライアントからサーバへの接続,トランザクションステートでメールの受け渡しや削除
チェック,更新ステートでセッション切断と転送済みメールの削除といった処理を行います.コマンドはそれぞれのス
テートにより異なりますが,レスポンスは +OK と –ERR の 2 種類のみとなっています.表 2.3 から表 2.5 にそれぞ
れのステートのコマンドを示します.
表 2.3
認証ステートのコマンド
コマンド
説明
USER
ユーザ名でのセッション開始
PASS
ユーザのパスワード
APOP
サーバに APOP での認証を要求
AUTH
サーバに AUTH=で要求した認証を要求
QUIT
セッション切断
表 2.4 トランザクションステートのコマンド
コマンド
説明
STAT
メールボックスの状況を要求
LIST
メールリストを要求
RETR
指定したメールの転送を要求
DELE
指定したメールに削除マークを付ける
NOOP
何もしない
RSET
削除マークを解除
QUIT
セッション切断
表 2.5 レスポンスコード
コマンド
説明
+OK
了承
-ERR
拒否
これらのコマンドとレスポンスを参考に,実際のサーバとクライアントのやり取りを確認します.ユーザ b1007000
が POP サーバからメールを受信する際の例を示します.
1.
+OK Dovecot ready
2.
… 認証ステート開始 …
3.
USER b1007000
4.
+OK
5.
PASS password
2.4 IMAP
6.
+OK
7.
… トランザクションステート開始 …
8.
STAT
97
9 . +OK 5 500
10. LIST 1
11. +OK 5 100
12. RETR 1
13. +OK
14. … ここでメッセージを受信 …
15. .
16. DELE 1
17. +OK
18. … メールの数だけ続く …
19. DELE 5
20. +OK
21. QUIT
22. … 更新ステート開始 …
23. +OK
24. … 削除完了後にセッション切断 …
1 行目から 5 行目までが更新ステートです.ユーザ名とパスワードのチェックを行い,test が存在するユーザであれ
ば認証を行って,トランザクションステートに移行します.
トランザクションステート移行後,8 行目で,クライアントは STAT でメールボックスの状態を確認します.9 行目
と 11 行目で,サーバは +OK に続けて,メールの数や総容量を返答します.この例では,メールが 5 通,それらの総
容量は 500byte であることが分かります.
12 行目で,クライアントは RETR 1 によって,1 番目のメールの転送を要求します.13 行目から 15 行目で,サー
バは +OK の後に本文を転送し,最後にドット (.) を送信します.その後,19 行目でクライアントは DELE によって,
受信したメールに削除マークを付けます.
12 行目から 20 行目のように,RETR と DELE のやり取りがメールの数だけ続いた後,21 行目でクライアントは
QUIT を送信します.これを受信したサーバは,削除マークが付けられたメールを削除します.サーバは削除処理が完
了後,クライアントとのセッションを切断します.以上で,メール転送を完了します.
POP では,基本的にメールボックスの中身を全て取得した後,メールボックスのデータを削除,つまり,メールボッ
クスを空にします.一度の接続で全てのメールを受信するので,メールの取得に時間がかかりますが,メールボックス
へ保存するデータ量を抑えられたり,サーバに負担がかからないといった利点があります.
2.4 IMAP
IMAP(Internet Messages Access Protocol:現行のバージョンは IMAP4rev1)とは,POP と同様にメールをサー
バから取得する際に使われる,RFC2060 で定義されるプロトコルです.TCP143 番でセッションを確立し,コマンド
レスポンスで通信を行います.
IMAP は POP の機能拡張版と考えることができます.POP ではメールボックス内のメールに対して転送のみを行
うのに対し,IMAP にはメールボックスの操作やメールの編集などの機能が備わっています.
第2章
98
SMTP と POP/IMAP
IMAP のセッションは 4 つに分かれています.それぞれ,未認証ステート,認証済みステート,選択済みステート,
ログアウトステートと呼ばれます.それぞれのステートごとで利用可能なコマンドと,全てのステートで利用可能なコ
マンドがあります.レスポンスも数種類あり,POP に比べてやや複雑な動作になります.表 2.6 から表 2.10 にそれぞ
れのステートで利用可能な主なコマンドを示します.
表 2.6 IMAP の常時有効なコマンド
コマンド
説明
CAPABILITY
サーバのサポートするプロトコル一覧を要求
NOOP
何もしない(タイムアウト防止などに用いる)
LOGPUT
セッション切断要求
表 2.7
IMAP の未認証ステートで有効なコマンド
コマンド
説明
LOGIN
特別なプロトコルを使用しないログイン要求
AUTHENTICATE 認証プロトコルを指定してのログイン要求
セッション切断要求
LOGPUT
表 2.8 IMAP の認証済みステートで有効なコマンド
コマンド
説明
SELECT
アクセスするメールボックスの選択
CREATE
新しいメールボックスを作成
DELETE
指定したメールボックスを削除
LIST
メールボックス一覧の要求
STATUS
指定したメールボックスのステータスを要求
表 2.9 IMAP の選択済みステートで有効なコマンド
コマンド
説明
STORE
メッセージに指定したフラグを立てる
EXPUNGE
削除フラグを付けたメッセージを全て削除
SEARCH
メールボックス内の検索
FETCH
指定したメッセージを取得
CLOSE
認証済みステートに戻る
POP と異なり,それぞれのステートは段階的に進むだけではありません.図 2.3 のように,認証後は認証済みス
テートと選択済みステートを行き来して処理を行います.認証済みステートでは主にメールボックスに対しての操作を
行い,選択済みステートでメールの読み取りなどメールボックス内のメールの操作を行っています.
実際のサーバとクライアントのやり取りを確認します.ユーザ test の,IMAP サーバからのメール受信時の例を以
下に示します.
2.4 IMAP
99
表 2.10 IMAP のレスポンスコード
コマンド
説明
OK
コマンド正常終了
NO
コマンド異常終了
BAD
エラー発生
PREAUTH
すでに認証済みである
BYE
サーバ側からの切断
図 2.3
1
*OK Dovecot ready
2
3
… 未認証ステート開始 …
4
5
10 LOGIN test password
6
10 OK LOGIN completed
7
8
… 認証済みステート開始 …
9
10 20 LIST ‐/MAIL/ %
11 *LIST()”/”-/mail/MLbox
12 20 LIST completed
13 SELECT -/mail/MLbox
14 20 OK [READ-WRITE] SELECT completed
15
IMAP ステートの移行
第2章
100
SMTP と POP/IMAP
16 … 選択済みステート開始 …
17
18 30 FETCH 1 BODY[]
19 * 1 FETCH (BODY[] {480}
20 … ここでメッセージを受信 …
21 30 FETCH completed
22 40 LOGOUT
23 *BYE
24
25 … ログアウトステート開始 …
26
27 40 OK LOGOUT completed
おおよその流れは POP と同様です.要求と認証の繰り返しによってステートが変わって処理が進んでいきます.18
行目の FETCH コマンドで,1 番目のメッセージを要求しています.POP と異なる点は,メッセージ受信後に削除
要求を行わない点です.IMAP では削除要求は個別に行うため,受け取り後もメールボックス内にメッセージは残り
ます.
2.5 MX レコード
DNS サーバには様々な情報が登録されています.メール送信の際に参照される DNS からの情報が MX (Mail
eXchanger) レコードです.1.2 節で説明した通り,本来はメールアドレスの @ 以降にはメールサーバのホスト名が入
ります.しかし,私たちが通常目にするメールアドレスはほとんどがドメイン名であり,相手先メールサーバ名を意識
することはほとんどありません.MX レコードが活用され,ドメイン名での送信が可能となるからです.
MX レコードには DNS サーバが受け持つドメインのメールサーバに関する情報が記述されています.MX レコード
は nslookup コマンドによって参照することができます.
$ nslookup -type=mx example.jp
以下のような情報が表示されます.ここでは実行例を示します.
1. Server:
2. Address:
192.168.10.1
192.168.10.1#53
3.
4. Non-authoritative answer:
5. example.com
MX preference = 10, mail exchanger = smtp.\ example.com
6.
7. smtp.example.jp
internet address = 208.77.XXX.XXX
5 行目の mail exchanger = の部分に,example.jp のメールサーバ名が記述されています.この場合は,smtp.
example.jp がメールサーバの名前です.また,7 行目にはメールサーバの IP アドレスが記述されています.メール
サーバは送信の際,DNS で相手先のドメインに MX レコードを問い合わせます.ここで受け取った情報を元にメール
を送信するため,ドメイン名でもメール送信が可能になります.
2.6 mail コマンド
101
また,5 行目の MX preference = の部分には,プリファレンス値が記述されています.プリファレンス値とは,ド
メイン内のメールサーバの優先順位を表す値です.ドメイン内にメールサーバが複数台存在する場合,プリファレンス
値が小さいサーバを優先し,配送エラー時の代替とします.上記の例では,メールサーバが 1 つしかないため意識する
ことはありませんが,大規模サービスを提供するドメインでは複数台のメールサーバを設置しているため,メール配送
の際にはプリファレンス値を基準にして,送信するサーバを特定します.
なお,メール送信に DNS のサービスを用いる理由は様々です.SMTP 本来の動作では,メールは転送を重ねて相手
先メールサーバへ配送されますが,DNS を利用することで転送を行わずに相手先へ直接送信することが可能にとなる
という点が理由の 1 つです.また,転送ドメイン内構成の秘密化や,メールアドレスの短縮化(ホスト名はドメインに
内包されるため長くなる傾向がある)などが他の理由として挙げられます.
2.6 mail コマンド
mail コマンドはメールの送受信を行うためのコマンドです.SMTP が動作していれば,メーラを使用せずにコマン
ドライン上でメールの送受信が可能となるため,動作テストなどに有効に利用できます.
$ mail
上記の mail コマンドを実行すると,内部コマンドの待ち受けに移行して,プロンプトが&に変わります.この状態
で実行できるコマンドを,表 2.12 に示します.
表 2.11
mail 内部コマンド一覧
コマンド
説明
+ , n , Enter
次のメールに移動
-
前のメールに移動
d
表示中のメールに削除フラグを立てる
e
メールを編集
f
ヘッダーを表示
h
メール一覧を表示
m
メール送信
q
削除を確定して終了
r
To 及び Cc に返信
R
To に返信
s
メールを指定したファイルに保存
t
メールを表示
u
削除フラグ解除
x
削除を確定しないで終了
数値
指定した番号のメールを表示
なお,未読のメールは /var/mail/ユーザ名 に,既読のメールは /home/ユーザ名/mbox にそれぞれ保管されてい
ます.
メールの送信は以下のコマンドを用いて行います.メールアドレスの前に,オプションを付ける事も可能です.
$ mail メールアドレス
第2章
102
SMTP と POP/IMAP
表 2.12 mail オプション一覧
コマンド
説明
-v
送受信状況の詳細を表示
-c アドレス
指定したアドレスを CC に設定
-b アドレス
指定したアドレスを BCC に設定
-s 件名
メールの件名を指定
実行すると Subject と表示されるので,ここで件名を入力します.入力後に ENTER 押下で本文入力待ちになりま
す.Subject に何も入力せずに ENTER を押下すると,件名無しのメールになります.ctrl-d(コントロールキーと D
キーを同時に押下)で本文入力を終了し,Cc の入力待ちになります.再度 ctrl-d で送信を行います.
実際に操作を行ってみます.メールの送信者は [email protected] ,あて先は [email protected] ,件名
は testmail,本文は test としたメールを送信します.
$ mail -v [email protected]
& Subject:
testmail
& test
& Cc:
また,今回は -v オプションを付けてメールを送信しています.コマンド実行後に以下のように表示され,SMTP
サーバとの通信内容が確認できます.
[email protected]... Connecting to [127.0.0.1] port 587 via relay...
220 ubuntu-vm ESMTP Sendmail 8.14.2/8.14.2/Debian-2build1;
・
・
>>> EHLO
example
250- example Hello localhost [127.0.0.1], pleased to meet you
>>>MAILFrom:<[email protected]>SIZE=45
250 2.1.0 <[email protected]>... Sender ok
>>> RCPT To:<[email protected]>
>>> DATA
250 2.1.5 <[email protected]>... Recipient ok
354 Enter mail, end with "." on a line by itself
>>> .
・
・
[email protected]... Sent
Closing connection to [xxx.xxx.xxx.xxx]
>>> QUIT
第3章
メールサーバの構築
MTA が動作するサーバを総称して,メールサーバと呼びます.この章では MTA のうち,sendmail と Postfix,
Dovecot によるメールサーバの構築を行います.
3.1 sendmail
sendmail は現在最も広く利用されている MTA の代表格で,SMTP によるメールの送信や転送を行います.1982 年
に Eric Allman 氏によって開発され,OSS として公開されました.sendmail をベースとした MTA も数多く存在し,
事実上 MTA のデファクトスタンダードとなっています.
3.1.1 sendmail のインストール
演習用の PC には,sendmail が既にインストールされています.参考としてコマンドを記載します.
参考)以下のコマンドを実行するとインストールが開始されます.
$ sudo apt-get install sendmail
3.1.2 sendmail のバージョン確認
sendmail には,単純にバージョンのみを確認するコマンドはありません.そのため,以下のコマンドで sendmail の
基本設定を確認すると同時にバージョンを確認します.
$ sendmail -d0.1 -bv
Version 8.14.2
Compiled with: DNSMAP LDAPMAP LDAP_REFERRALS LOG MAP_REGEX MATCHGECOS
MILTER MIME7TO8 MIME8TO7 NAMED_BIND NETINET NETINET6 NETUNIX
NEWDB NIS NISPLUS PIPELINING SASLv2 SCANF SOCKETMAP STARTTLS
TCPWRAPPERS USERDB USE_LDAP_INIT XDEBUG
============ SYSTEM IDENTITY (after readcf) ============
(short domain name) $w = smtp.example.com
(canonical domain name) $j = smtp.example.com
(subdomain name) $m = <null>
(node name) $k = smtp.example.com
第 3 章 メールサーバの構築
104
========================================================
また,接続可能ならば telnet を利用した確認も可能です.SMTP のポート番号 25 番を指定して,接続後に HELP
コマンドでバージョンが確認できます.接続終了は QUIT コマンドで行います.以下にローカルホストでの例を示し
ます.
$ telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is ’^]’.
220 ubuntu-vm ESMTP Sendmail 8.xx.x/8.xx.x/Debian-2build1; Sun, 4 Oct 2009 12:25:15 +0900;
(No UCE/UBE) logging access from: localhost(OK)-localhost [127.0.0.1]
HELP
214-2.0.0 This is sendmail version 8.xx.x
214-2.0.0 Topics:
214-2.0.0
HELO EHLO MAIL RCPT DATA
214-2.0.0
RSET NOOP QUIT HELP VRFY
214-2.0.0
EXPN VERB ETRN DSN AUTH
214-2.0.0
STARTTLS
214-2.0.0 For more info use "HELP <topic>".
214-2.0.0 To report bugs in the implementation see
214-2.0.0
http://www.sendmail.org/email-addresses.html
214-2.0.0 For local information send email to Postmaster at your site.
214 2.0.0 End of HELP info
QUIT
221 2.0.0 ubuntu-vm closing connection
Connection closed by foreign host.
3.1.3 sendmail の起動・停止・再起動
sendmail の起動,停止,再起動には以下のコマンドを用います.
起動
$ sudo /etc/init.d/sendmail start
再起動
$ sudo /etc/init.d/sendmail restart
停止
$ sudo /etc/init.d/sendmail stop
3.1 sendmail
105
3.1.4 sendmail の設定
sendmail の設定ファイルは,/etc/mail/sendmail.cf です.しかし内容が複雑で,そのまま編集を行うのは困難で
す.そこで一般的には,CF や m4 という sendmail.cf を作成するツールを使用し編集を行います.ここでは m4 を用
いて,sendmail.cf の設定例を以下に示します.
$ cat /etc/mail/sendmail.mc
m4(または CF)とは,sendmail.mc(CF の場合 sendmail.def)という設定用のファイルを sendmail.cf に変換す
るツールです./etc/mail 内に,デフォルトの sendmail.mc も格納されています.cat コマンドを用いてその内容を確
認します.
divert(-1)dnl
divert(0)dnl
#----------------------------------------------------------------------------# $Sendmail: debproto.mc,v 8.14.2 2008-01-24 14:29:57 cowboy Exp $
# Copyright (c) 1998-2007 Richard Nelson.
All Rights Reserved.
・
・
include(‘/usr/share/sendmail/cf/m4/cf.m4’)dnl
VERSIONID(‘$Id: sendmail.mc, v 8.14.2-2build1 2008-01-24 14:29:57 cowboy Exp $’)
OSTYPE(‘debian’)dnl
DOMAIN(‘debian-mta’)dnl
・
・
dnl # Default Mailer setup
MAILER_DEFINITIONS
MAILER(‘local’)dnl
MAILER(‘smtp’)dnl
表記が少し特殊で,行の終わりには行末を宣言する dnl が書かれています.m4 は改行コードを認識しないため,dnl
が無い行は,変換時に空行として省かれてしまいます.dnl 以降にメッセージがあっても変換時に省くので,コメント
アウトとしても利用できます.また,引数の囲みはバッククォート (‘) で始まり,シングルクォート (’) で終わります.
さらに m4 は大文字小文字を区別します.微妙な違いですが,これらを間違えると変換時にエラーとなるので注意して
ください.
sendmail.mc に設定を追記,保存後,m4 コマンドを用いて sendmail.cf への変換を行います.また,cf に変換
する前に現在の sendmail.cf のバックアップを行うことを推奨します.mail ディレクトリに変更前の設定ファイル
sendmail.cf.old があるので上書きしておきます.
sendmail.cf 作成後,sendmail を再起動することで新しい設定が有効になります.
第 3 章 メールサーバの構築
106
$ cd /etc/mail
$ sudo rm sendmail.cf.old
$ sudo mv sendmail.cf sendmail.cf.old
$ sudo m4 sendmail.mc > sendmail.cf
3.1.5 sendmail のスタートアップ設定
sendmail は通常,OS 起動時に自動的に起動するよう設定されています.以下を用いて,スタートアップの有無の設
定及び設定確認を行います.
スタートアップ有りの設定
$ sudo sysv-rc-conf sendmail on
$ sudo sysv-rc-conf -list | grep sendmail
sendmail 0:off 1:off 2:on 3:on 4:on 5:on 6:off
スタートアップ無しの設定
$ sudo sysv-rc-conf sendmail off
$ sudo sysv-rc-conf -list | grep sendmail
sendmail 0:off 1:off 2:off 3:off 4:off 5:off 6:off
3.2 Postfix
107
3.2 Postfix
Postfix は sendmail をベースとした MTA です.1998 年に Wietse Venema 氏により開発され,オープンソースソ
フトウェアとして公開されました.
3.1 節で述べたように,現在最も広く利用されている SMTP サーバは sendmail です.その起源は古く,何度も改
修されたことによってセキュリティ面の管理や設定の難しさが指摘されています.Postfix はそれらの問題に対し,設
定ファイルの簡略化やセキュリティ問題の発生低下を可能にしました.また sendmail コマンドラインの継承など,
sendmail との互換性を保つべく設計されています.
3.2.1 Postfix のインストール
演習用の PC には,Postfix が既にインストールされています.参考として以下に,コマンド及びインストールの手
順を記載します.
参考)
Postfix は sendmail との互換性を維持するために,sendmail と同名のバイナリを使用します.sendmail がインス
トール済みの場合,sendmail の復旧用に Postfix のインストール時に上書きされてしまうバイナリを,以下のコマンド
であらかじめ移動します.
$ sudo mv /usr/lib/sendmail/usr/lib/sendmail.old
$ sudo mv /usr/bin/mailq/usr/bin/mailq.old
$ sudo mv /usr/bin/newaliases/usr/bin/newaliases.old
また,Postfix と sendmail が同時に起動する環境では競合を起こす可能性があります.本テキストでは,sendmail
及び依存パッケージを全て削除することで対応します.
以下のコマンドで,sendmail 及び依存パッケージを全て削除します.
$ sudo apt-get remove sendmail
$ sudo apt-get autoremove
バイナリのバックアップ及び sendmail の削除完了後,以下のコマンドで Postfix のインストールを行います.
$ sudo apt-get install postfix
インストール開始時に,図 3.1 のような選択画面が出ます.Postfix の初期設定なので,ここではインターネットサ
イトを選択します.ここで選択した内容に沿って,後述する main.cf の初期値が決まります.設定なしを選択すると
main.cf が作成されず,Postfix が起動しません.既存の設定を使用する場合は,任意の選択肢を選びます.
3.2.2 Postfix のバージョン確認
以下のコマンドで,Postfix のバージョンを確認できます.
$ postconf | grep mail version
mail_version = 2.5.1
第 3 章 メールサーバの構築
108
図 3.1 Postfix の初期設定画面
3.2.3 Postfix の起動・停止・再起動
Postfix の起動,停止,再起動には以下のコマンドを用います.
起動
$ sudo /etc/init.d/postfix start
再起動
$ sudo /etc/init.d/postfix restart
停止
$ sudo /etc/init.d/postfix stop
3.2.4 Postfix の設定
Postfix の設定は,主に/etc/postfix/main.cf で行います.sendmail に比べて格段に見やすくそのまま変更や追記が
できるため,ツールを使った変換なども必要ありません.cat コマンドを用いて,実際にその内容を確認します.
$ cat /etc/postfix/main.cf
# See /usr/share/postfix/main.cf.dist for a commented, more complete version
3.2 Postfix
109
・
・
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
myhostname = ubuntu-vm
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = example.com, ubuntu-vm, localhost.localdomain, localhost
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
途中を省略していますが,初期設定でインターネットサイトを選択した場合の main.cf の例です.Postfix インス
トール時の初期設定において,必要なパラメータだけがピックアップされて main.cf が作られているため設定項目が少
なくなっています.ひな形となる main.cf は /usr/share/postfix/main.cf.dist です.このファイルには,ほぼ全ての
パラメータとその説明が記載されています.
なお,行頭に # を記述することでコメントアウトすることができますが,文中に # を記述することによってコメ
ントアウトを行うことはできません.例えば,以下のようにすると,構文エラーとなりその行自体が無視されてしまい
ます.
myhostname = ubuntu-vm
# hostname
また,ダブルクォート (”) や行末のセミコロン (;) なども構文エラーの原因となるため注意が必要です.
3.2.5 Postfix のスタートアップ設定
Postfix は通常,OS 起動時に自動的に起動するよう設定されています.以下の操作で,スタートアップの有無の設定
及び設定確認を行います.
スタートアップ有りの設定
$ sudo sysv-rc-conf postfix on
$ sudo sysv-rc-conf -list | grep postfix
postfix 0:off 1:off 2:on 3:on 4:on 5:on 6:off
スタートアップ無しの設定
第 3 章 メールサーバの構築
110
$ sudo sysv-rc-conf postfix off
$ sudo sysv-rc-conf -list | grep postfix
postfix 0:off 1:off 2:off 3:off 4:off 5:off 6:off
3.3 Dovecot
111
3.3 Dovecot
Dovecot は,POP/IMAP に対応した MTA です.Timo Sirainen 氏により開発され,オープンソースソフトウェア
として公開されました.sendmail や Postfix と高い互換性を持ち,高速な動作を提供するため,sendmail や Postfix
と合わせ,広く利用されています.
3.3.1 Dovecot のインストール
演習用の PC には,Dovecot が既にインストールされています.参考としてインストールの手順を記載します.
参考)
以下のコマンドを実行するとインストールが開始されます.
$ sudo apt-get install dovecot-common
$ sudo apt-get install dovecot-pop3d
$ sudo apt-get install dovecot-imapd
3.3.2 Dovecot のバージョン確認
以下のコマンドで,Dovecot のバージョンを確認できます.
$ dovecot --version
1.0.10
3.3.3 Dovecot の起動・停止・再起動
Dovecot の起動,停止,再起動には以下のコマンドを用います.
起動
$ sudo /etc/init.d/dovecot start
再起動
$ sudo /etc/init.d/dovecot restart
停止
$ sudo /etc/init.d/dovecot stop
3.3.4 Dovecot の設定
Dovecot の設定は主に /etc/dovecot/dovecot.conf で行います.実際に内容の確認を行います.
$ cat /etc/dovecot/dovecot.conf
第 3 章 メールサーバの構築
112
## Dovecot configuration file
# If you’re in a hurry, see http://wiki.dovecot.org/QuickConfiguration
・
・
# Protocols we want to be serving: imap imaps pop3 pop3s
# If you only want to use dovecot-auth, you can set this to "none".
#protocols = imap imaps
protocols = pop3 imap
・
・
##
## Mailbox locations and namespaces
##
・
・
#
mail_location = maildir:~/Maildir
#
#mail_location =
・
・
##
## IMAP specific settings
##
protocol imap {
# Login executable location.
#login_executable = /usr/lib/dovecot/imap-login
##
## POP3 specific settings
##
protocol pop3 {
# Login executable location.
#login_executable = /usr/lib/dovecot/pop3-login
・
・
途中を省略していますが,使用するプロトコルやプロトコルの動作設定,及びメールボックスの設定などの必要な情
報は,全て dovecot.conf に記載されています.
3.3 Dovecot
113
3.3.5 Dovecot のスタートアップ設定
Dovecot は通常,OS 起動時に自動的に起動するよう設定されています.以下の操作でスタートアップ有無の設定変
更,及び設定確認を行います.
スタートアップ有りの設定
$ sudo sysv-rc-conf dovecot on
$ sudo sysv-rc-conf -list | grep dovecot
dovecot 0:off 1:off 2:on 3:on 4:on 5:on 6:off
スタートアップ無しの設定
$ sudo sysv-rc-conf dovecot off
$ sudo sysv-rc-conf -list | grep dovecot
dovecot 0:off 1:off 2:off 3:off 4:off 5:off 6:off
第 4 回 演習課題
目標
いくつかの方法を用い,メールを送信します.
mail コマンドを使用してメールを送信して下さい.次に,第 3 回で作成した Web サーバ上にアプリケーション
を設置し,ブラウザからメールを送信して下さい.また,課題で送信したメールのメールヘッダを確認して下
さい.
課題 1 mail コマンドでのメール送信
2.6 節を参考に,mail コマンドを使ってメールを送信し,送信されていることを確認して下さい.あて先は自身の学
内メールアカウントに設定し,件名は学籍番号 1,本文は This is testmail 学籍番号 として下さい.
課題 2 Web アプリケーションでのメール送信
授業用 Web サイトに,メール送信用の Web アプリケーション send\ mail.php のソースが保存されています.第
3 回で作成したサイト (/home/www/(学籍番号)/public html) に新しく send\ mail.php を作成して下さい.方法は
問いません,html からのコピーペーストでも構いません.
保存後,ブラウザより http://(IP アドレス)/send mail.php へアクセスすると,図 3.2 のような画面が表示され
ます.to にあて先,subject に件名,message に本文を入力し,実行を押すとメールが送信されます.あて先は自身の
学内メールアカウントとして下さい.また,メールが送信されていることを確認して下さい.
課題 3 メールヘッダの確認
課題 2 で送信したメールのメールヘッダを確認し,Received: に書かれているメールサーバの IP アドレスが,演習
で使用している端末のアドレスであることを確認して下さい.
本テキストでは触れませんでしたが,メールには必ずヘッダと呼ばれる情報が含まれており,これを確認する事で
メールの送信元,送信サーバの特定が可能となります.図 3.3 にメールヘッダの表示方法の例を示します.
以下にメールヘッダの例を示します.
Return-Path: <[email protected]>
Received: from sv2mail.example2.jp (kyuuri.example2.jp [***.***.***.***])
by sv1mail.example.jp (MOS 3.10.5-GA)
with ESMTP id AHZ06591;
Tue, 15 Dec 2009 18:02:37 +0900 (JST)
Received: ...
115
図 3.2
send mail.php
Received: ...
Received: from mailsv
by mailsv.example.jp id **********
for <[email protected]>; Tue, 01 Jun 2009 18:02:36 +0900 (JST)
From: [email protected]
To: [email protected]
Message-ID: <*******-*****************@mailsv.example2.jp>
Date: Tue, 01 Jun 2009 18:02:36 +0900
Mime-Version: 1.0
Content-Type: text/plain; charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit
.
.
.
メールヘッダには様々な情報が含まれますが,今回はこれらの情報のうち Received: の部分に注目します.ここに
は,送信元(または中継の)メールサーバ名と IP アドレスが記載されます.Received: は送信者から受信者までメー
ルが送られる際に,通過したメールサーバの情報が追記されていきます.情報は先頭から追記されるため,上に書かれ
ている Received: ほど受信側に近いサーバに,下に書かれている Received: ほど送信側に近いサーバとなります.
メールヘッダの表示方法はメーラによって異なりますが,Web メールの場合は図 3.3 の位置にある source アイコン
をクリックする事で表示できます.
第3章
116
図 3.3 メールヘッダ表示方法の例
第 4 回 演習課題
参考文献
[1] Paul G. Sery. Jay Beale. 有限会社ヴァインカーブ (監訳), Red Hat Linux Internet Server, ソフトバンクパブリッ
シング, 2003
[2] Costales Bryan. Allman Eric. 鈴木克彦 (訳), sendmail リファレンス, オーム社, 1998
[3] Kyle D. Dent 菅野良二 (訳), Postfix 実用ガイド, オーム社, 2004
[4] DOVECOT, http://www.dovecot.org/
第5回
サーバにおけるログ管理
ネットワークサーバの管理業務を構成する重要な作業であるログ管理について解説します.ま
た,Web サーバ構築に用いられる Apache のログについても解説します.syslog の導入と管理
の説明に加え,logwatch, logrotate, swatch といった様々なログ管理ツールの導入と設定方法
を説明します.演習では,logrotate を実際に導入・設定し,アクセスログのローテーションに
ついて学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
ログ管理の重要性について
1.1 ログとは
ログとは,コンピュータの利用状況やデータ通信の記録を取ること,またはその記録自体のことを指します.操作や
データの送受信が行われた日時,操作の内容,送受信されたデータの中身などが記録されます.
サーバで出力されるログには,サーバの異常を示すログやユーザのログイン履歴,プログラムの動作ログなど様々な
種類が存在します.
1.2 ログの運用管理
システムのトラブルやユーザの行動などの情報は,問題解決の重要な手がかりとなります.例えば,対象システムが
不正行為を受けた場合,システムや各サービスなどが出力するログに攻撃の痕跡が残る場合があります.そのログを分
析することで,いつ頃からどのサービスに対して,どのような攻撃手法で攻撃を受けたのかを判断することが可能にな
ります.セキュアなシステム運用を行うには,定期的にログの監査を実施し,現在のシステム状況を分析する作業が不
可欠です.
ログは不正行為等の発見以外にも利用されます.例えば,Web サーバのログを統計的に解析することによって,サ
イト管理の効率化を図ることも可能です.
しかし,ログはすべてのトラブル情報を記録することはできないため,ログに不正行為の痕跡がない場合でもシステ
ムが被害を受けている可能性があります.熟練した攻撃者は攻撃の痕跡をログファイルからきれいに抜き取り改ざんす
る技術を持っています.そのため,ログファイルに攻撃の痕跡が存在しないからといって侵入されていないとは限りま
せん.
また,ログは何も考えずに収集していると肥大化してしまうので,ローテーションさせる必要があります.ローテー
ションとは一定期間ごとにログを別ファイルにバックアップとして保存していき,バックアップされたログファイルを
一定期間ごとに破棄することで,ディスク容量の圧迫を防ぐ仕組みです.
1.3 ログの収集
主なログ収集対象として,アクセスサーバ,ファイアウォール,IDS(侵入検知システム)
,メールサーバ,Web サー
バなどが挙げられます.
その中でも代表的な,Web サーバ構築に用いられる Apache [1] のログについて解説します.
1.3 ログの収集
121
1.3.1 Apache のログ
Web サーバ構築に用いる Apache のログからは,サイトの不具合や不審なアクセスを発見できます.また,閲覧者の
移動経路などからサイトを使いやすくする手掛かりを得ることも可能です.Apache のアクセスログに関しては,3 章
でも取り上げています.
アクセスログ
通常,ログといえばアクセスログを指します.アクセスログは,Web ブラウザがサーバに何かをリクエストし,そ
れに Apache が応えるごとに記録されます.このログに「何を記録するのか」「どのファイルに記録するのか」といっ
たことは,管理者が自由に定義できます.Apache のアクセスログは,Ubuntu では/var/log/apache2/access.log とい
うファイルに出力されます.正常なアクセスログの例を以下に示します.
127.0.1.1 - [12/Jul/2009:22:03:53+0900] "GET/HTTP/1.1" 200 45 "-"
"Mozilla/5.0 (X11; U; Linux i686; ja; rv:1.9.0.11) Gecko/2009060309
Ubuntu/8.04 (hardy) Firefox/3.0.11"
Apache のアクセスログのフォーマットは/etc/apache2/apache2.conf で指定することができます.デフォルトでは
以下のようになっています.また,パラメータの詳細は表 1.1 に示したとおりです.
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b common
LogFormat "%{Referer}i -> \%U" referer
LogFormat "%{User-Agent}i" agent
表 1.1
項目
Apache のアクセスログのフォーマット
内容
%h
クライアント名(IP アドレス,ホスト名)
%l
個人情報(通常はハイフン)
%u
ユーザ ID
%r
リクエストの日付
%t
クライアントからのリクエスト内容
%>s
クライアントに返す 3 桁のリターンコード
%b
クライアントに転送したオブジェクトのバイト数
%Refereri
%User-Agenti
参照元
ユーザ・エージェント(Web ブラウザ名など)
また,アクセスログの設定で必要になるディレクティブには,
「CustomLog」や「LogFormat」などがあります.ディ
レクティブとは,Apache の動作をコントロールする命令のことです.CustomLog ディレクティブはアクセスログの
場所と内容を指定し,LogFormat ディレクティブはログファイルで使用する書式を設定するために用います.
第1章
122
ログ管理の重要性について
エラーログ
エラーログは,リクエストの結果がエラーになったものだけが記録されます.また,アクセスログと違い,設定でき
るのは記録するエラーのレベル程度しかありません.
基本的に,エラーログはサーバに問題が起きていないことを確認するために使用します.
エラーログの設定で必要になるディレクティブは,
「ErrorLog」と「LogLevel」の 2 つです.ErrorLog ディレクティ
ブはログファイルの位置と名称を指定し,LogLevel ディレクティブは記録するログのレベルを指定します.
LogLevel ディレクティブで指定できるログレベルを表 1.2 に示します.
表 1.2
エラーログのレベル
レベル
記載される内容
emerg
動作不能な状況(Emergency の意)
alert
修正しなければ(部分的に)動作できない問題
crit
上記に該当しない動作上の問題(Critical の意)
error
存在しないファイルへのアクセスなど各種エラー
warn
警告(Warning の意).設定のミスなどが考えられる場合
notice
起動停止や設定変更された場合など
info
あらゆる情報(プロセスの起動や停止など)
debug
Apache 関連のデバッグに必要な情報
例えば,以下のようにレベルの指定を行ったとします.
LogLevel notice
このように指定すると,notice 以上のもの (emerg∼notice) が記録されることになります.一般的に,運用状態にあ
るサーバでは「notice」か「warn」を指定し,テスト状態であれば「info」や「debug」を指定することが多いです.
ErrorLog ディレクティブには,ログを指定するディレクトリとファイルの名称を指定します.例えば,以下のよう
に記述します.
ErrorLog /usr/local/apache/logs/error.log
また,以下のようにファイル名の代わりに「syslog」を指定しても構いません.
ErrorLog syslog
この場合,Apache 専用のエラーログファイルを作らず,Linux が標準で持っている syslog にエラーを記録します.
ただし,syslog に記録するよりも管理の利便性から専用のファイルに記録することがほとんどです.
また,syslog に記録する場合は,次のようにすることで syslog のファシリティを指定することも可能です.ファシ
リティとはログの分類に当たるものです.ファシリティの指定がない場合は,local7 がデフォルトのファシリティとし
て採用されます.
1.3 ログの収集
123
ErrorLog syslog:facility
エラーログを設定したら,わざと間違ったアクセスを試み,どのようなログが記録されるのか確認しておくとよいで
しょう.例えば,以下のようなログが記録されたとします.
[crit] [client192.168.1.11] (13)Permission denied:
/usr/local/apache/html/root_own.html pcfg_openfile:
unable to check htaccess file, ensure it is readable
「Permissiondenied」の部分に注目してください.これは,ファイルは存在しているがパーミッション(権限)の問
題でファイルを読み込めなかったことを意味します.こうした問題は,単なるエラー (error) よりも高レベルのログと
して記録されることになります.このようなログを抽出することで,問題を早期に修正することが可能です.
[alert] [client192.168.1.11] /home/ichishi/public_html/.htaccess:
Multiple <Files> arg umentsnot (yet) supported.
[alert] [client192.168.1.11] /home/ichishi/public_html/.htaccess:
Invalid command ’hogehoge’, perhaps mis-spelled or defined by a module
not included in the server configuration
この場合も単なるエラーよりも高レベルのログ (alert) として記録されています.これは,.htaccess の内容に間違い
があることを警告しています.Apache 自身の動作に問題はありませんが,このユーザーのファイルに正常なアクセス
ができなくなるという問題が生じます.
以下に示すのは,比較的発生しやすいエラーです.
[error] [client192.168.1.11] File does not exist:
/usr/local/apache/html/index.html not_exist
これは,リクエストに対応するファイルがなかったという意味のエラーです.このようなエラーの大半はユーザー側
のミスですが,リンクのミスという可能性も考えられます.この記録が頻発するようであれば,リンクを間違えていな
いかなどを検査してみる必要があります.
[error] [client192.168.1.11] client denied by server configuration:
/home/ichishi/public_html/index.html
これは,「denied」となっていることから分かるように,アクセス制限によってアクセスが拒否されたことを意味し
ています.単にパスワードを打ち間違えても記録されますが,これがログに頻繁に現れるようなら不正アクセスという
ことも考えられます.
これらはほんの一例でしかありませんが,見慣れないエラーでも注意深く英語を解読すれば大体の意味は理解できる
はずです.もし error 以上のレベルが記録されたら,基本的に対処を要するものだと思った方がよいでしょう.
124
第1章
ログ管理の重要性について
CGI エラーログ
CGI エラーログには,CGI スクリプトが発行するエラーだけが記録されます.このログは Apache の設定ファイル
に対し,ScriptLog ディレクティブを用いて設定しなければ作成されません.通常の運用時にこのログを記録すること
は少なく,CGI スクリプトの開発環境においてのみ記録させることがほとんどです.
バグを含んだ CGI スクリプトを作成し,Web ブラウザでアクセスすればこのログを作成することができます.その
内容を見るとよく分かりますが,サーバ上の端末やエミュレータなどで実行したときに出力されるエラーメッセージと
まったく同一のものが記録されることになります.
Cookie ログ
Cookie ログは,ユーザの行動追跡に使用されます.このログは,「mod usertrack」というモジュールを必要とする
ため,あらかじめ Apache にモジュールを組み込んでおかなければ記録できません.
モジュールの機能が有効化されている場合,Apache はリクエストした Web ブラウザに対して自動的に Cookie を
発行します.ここで発行された Cookie を記録することで,利用者がどういった経路でサイト内を移動したかを分析で
きます.主に商業サイトなどでユーザーの行動を分析し,サイトの構造を評価する目的で利用されることがほとんど
です.
第2章
syslog の導入・管理
2.1 ログ制御システム (syslog) とは
syslog [2] は,ログメッセージを IP ネットワーク上で転送するための標準規格です.syslog という用語は,その通
信プロトコルを指すだけではなく,syslog メッセージを送信するアプリケーションやライブラリに対しても使用され
ます.
syslog プロトコルはクライアント/サーバ型のプロトコルです.syslog 送信側は 1024 バイト以下の短いテキスト
メッセージを syslog 受信側に送信します.受信側を一般に syslogd,syslog デーモンなどと呼びます.
ほとんどの場合,ログは syslog を介して出力されます.まず,syslog はカーネルや各種のデーモン,アプリケーショ
ンなどが出力したログを取得します.その後,あらかじめユーザの指定した方法でファイルに記録したり,特定のサー
バに送信したりします.このようにログを別の syslog サーバに転送するという機能があるため,その機能を用いてロ
グの一元管理を行うことができます.syslog は各種プラットフォーム上で広くサポートされているため,様々なシステ
ムのログデータを 1 つの集中リポジトリで管理することも可能です.
図 2.1
syslog のしくみ
126
第 2 章 syslog の導入・管理
2.2 syslog の歴史と今後の展望
2.2.1 syslog の歴史
syslog とは 1980 年代に EricAllman が sendmail プロジェクトの一部として開発したものです.当初は sendmail
だけで使われていましたが,その利便性から,他のアプリケーションでも使われるようになっていきました.そして
UNIX や Linux でのロギング方法の標準となりました.
最近まで syslog はデファクトスタンダードであり,何らかの規格があるわけではなく,個々の実装には非互換も存
在していました.セキュリティ強化のため IETF (Internet Engineering Task Force) はワーキンググループを結成し,
2001 年に RFC3164 (Request For Comment 3164) としてまとめられました.
現在利用されている syslog の実装例としては,標準のデーモンプログラムである syslogd のほかに,安全性がより考
慮され,機能が追加された syslog–ng や,TCP 転送やデータベースへのログ保存などの機能が実現された rsyslog な
どがあります.
2.2.2 今後の展望
現在も syslog の利用は拡大し続けています.様々なグループが syslog の拡張の標準化を行っており,医療関係での
応用などが提案されています.
アメリカでは,SOX 法 (Sarbanes–Oxley act) や HIPPA 法 (Health Insurance Portability and Accountability
Act: 医療保険の相互運用性と説明責任に関する法律) などの規制により,企業は包括的なセキュリティ強化を迫られ
ています.syslog は各種ソースからのログを収集,解析するのに最適なフォーマットであり,解析を行うためのツール
も数多く存在しています.最近では,企業全体の syslog 記録を集め,解析するサービス (Managed Security Service
Provider: MSSP) が登場しています.このサービスは,人工知能的アルゴリズムを適用してパターンを検出し,顧客
に対して問題を通報するというものです.
2.3 syslog の運用
syslog サービスは,まず標準のログ出力用デーモンである syslogd により提供されます.syslogd では syslog ファイ
ルのローテーションの実行や,syslog ログの自動的な監査をすることができません.そのため,解析を行う場合には同
時に logrotate や logwatch, swatch などのソフトを別途導入する必要があります.logrotate や logwatch, swatch に
ついては 3 章で紹介します.
2.4 syslogd の代替ツール
syslogd は多くの UNIX などで利用されていますが,大きな問題点がいくつかあります.例えば,ディスク I/O の
方式が非効率的で処理速度が遅い,UDP で送信を行うため信頼性が低いなどの問題点が挙げられます.しかし,歴史
が長いため広く普及しており,簡単に仕様を変えることができないというのが現状です.
そのため,さまざまな syslogd の代替ツールが開発されています.ここではそのうちの 1 つを紹介します.
2.4 syslogd の代替ツール
127
2.4.1 syslog–ng
代替ツールのひとつに,syslog–ng (syslog–next generation) があります.syslogd ではファシリティでのみ振り分
けが可能だったのに対し,syslog-ng はファシリティ,プライオリティ,IP,キーワードなどでのフィルタリングが可
能です.プライオリティとは,プログラムが出力するメッセージのうち,ログのレベルの重要度を設定するものです.
また,syslog–ng は出力先としてプログラムを指定することもできるため,swatch のようにログ監視をさせることも
可能です.swatch との違いは,サーバやネットワーク経由で吐き出される全てのログを対象に監査できることです.
そのため syslog–ng の方が使い勝手が良いと言われています.
第3章
ログ管理ツールの導入
3.1 logrotate
先述したように,ログファイルを放っておくとディスクを圧迫することになりかねません.ログファイルのサイズが
大きくなれば,ログの解析にも悪影響を及ぼすことになります.また,サイズが大きいとファイルを開くこと自体が困
難になり,問題の個所を発見しにくくなります.
そこで,最低でも週に一度くらいの割合でログファイルのローテーションを行う必要があります.ファイルをロー
テーションすることで,ファイル 1 つ当たりのサイズとそこに含まれる情報を必要最小限に抑えることが可能になりま
す.また,過去のログは何世代分か前のものまで保持し,必要に応じて過去にさかのぼれるようにします.
図 3.1 logrotate のしくみ
この方式は時間をきっかけにローテーションするため,1 つ 1 つのファイルのサイズは予測できません.その上,管
理対象世代を過ぎたログは自動的に削除されてしまうため,ログを残しておきたい場合は削除される前にテープ装置な
どでバックアップしなければなりません.それでもログのサイズが大きくなり過ぎる場合,ローテーションのタイミン
グや管理する世代数を見直さなくてはなりません.このように多少の工夫や配慮は必要になるものの,この方式は柔軟
性も高く運用も容易です.そのため,Linux や商用 UNIX ではログの管理にこの方式を用いることが多いです.
logrotate とは各種 log をローテーションさせるサービスです.log は放っておくと肥大化するため,それを定期的に
3.1 logrotate
129
分割,バックアップするために cron で logrotate を実行します.図 3.1 に logrotate のしくみを示します.
logrotate の導入方法について説明します.今回の作業環境では,logrotate は標準でインストールされています.ま
ず,以下のコマンドなどを使用して設定ファイルを探し,vi などのテキストエディタで設定ファイルを開きます.
$ ls -la
現在どのような設定がされているのかを確認します.書き込まれている設定の意味は以下のようになっています.
# see "man logrotate" for details
# rotate log files weekly
weekly # ローテートの間隔
# keep 4 weeks worth of backlogs
rotate 4 # 何世代まで保存するか
# create new (empty) log files after rotating old ones
create
# ローテート処理後すぐにログファイルを作成するか
# uncomment this if you want your log files compressed
# compress
# ログファイルを圧縮する場合はコメントを外す
# packages drop log rotation information into this directory
include /etc/logrotate.d
# logrotate の個別設定ファイルの保存場所
# no packages own wtmp, or btmp -- we’ll rotate them here
/var/log/wtmp {
missingok
monthly
create 0664 root utmp
rotate 1
}
/var/log/btmp {
missingok
monthly
create 0664 root utmp
rotate 1
}
第 3 章 ログ管理ツールの導入
130
# system-specific logs may be configured here
前回までに Apache が導入されているはずなので,Apache ログの設定ファイルも確認します.
$ vi /etc/logrotate.d/apache2
設定ファイルの内容は,以下のようになっています.
/var/log/apache2/*.log {
weekly
# daily, weekly, monthly から選択
missingok
rotate 52
# ログをローテートする回数 (52 週間)
compress
# ログを圧縮する.しない場合は,nocompress
delaycompress
# 次のローテーションタイミングで圧縮する
notifempty
# ファイルが空だとローテートしない
create 640 root adm
sharedscripts
postrotate
if [ -f "‘. /etc/apache2/envvars ; echo ${APACHE_PID_FILE:-/var/run/apache2.pid}‘" ]; then
/etc/init.d/apache2 reload > /dev/null
fi
endscript
}
postrotate は ロ ー テ ー ト 後 に コ マ ン ド を 行 う と い う こ と を 示 し て お り ,次 の 判 定 文 以 下 (こ の 場 合 だ
と/etc/init.d/apache2 reload) が 実 行 さ れ ま す .こ の よ う に ,ロ グ を ロ ー テ ー ト し た 後 に ロ グ フ ァ イ ル を 見
失ってログ取得に失敗しないよう再起動をかけます./var/run/apache2.pid は httpd の pid ファイル (デーモンプロ
グラムが起動しているときのプロセス ID を記録しておくファイル) の位置です.ログファイルの位置を指定するため,
上のファイルを以下のように変更して下さい.
/var/log/b1007000/*_log {
weekly
# daily, weekly, monthly から選択
missingok
rotate 52
# ログをローテートする回数 (52 週間)
compress
# ログを圧縮する.しない場合は,nocompress
delaycompress # 次のローテーションタイミングで圧縮する
notifempty
# ファイルが空だとローテートしない
create 640 root adm
sharedscripts
postrotate
if [ -f "‘. /etc/apache2/envvars ; echo ${APACHE_PID_FILE:-/var/run/apache2.pid}‘" ]; then
/etc/init.d/apache2 reload > /dev/null
3.2 swatch,logwatch
131
fi
endscript
}
次に,実際にローテーションをテストしてみます.
$ sudo /usr/sbin/logrotate -v /etc/logrotate.conf
ここで, -v とはどのファイルをローテートしているのかを確認するオプションです.logrotate の動作確認のために
は,過去に対象ファイルにローテートを実施した記録が必要です.そこで,この記録を編集します.
$ sudo vi /var/lib/logrotate/status
編集前は以下のような記録になっています.
"/var/log/b1007000/access_log" 2009-10-21
"/var/log/b1007000/error_log" 2009-10-21
確実に実施するため,記録を 2 年前の日付にしてください.つまり,上述のファイルを以下のように変更します.
"/var/log/b1007000/access_log" 2007-10-21
"/var/log/b1007000/error_log" 2007-10-21
その後,もう一度 logrotate を実行します.以下のような実行結果が出力されれば成功です.
considering log /var/log/b1007000/access_log log needs
次は crontab で 1 日 1 回動作するように設定します.
$ sudo vi /etc/crontab
crontab をテキストエディタで開き,以下の 1 文を追加します.
0 3 *** root /usr/sbin/logrotate /etc/logrotate.conf
これで毎日午前 3 時に一度,ファイルがローテートされます.logrotate を実行すると,/var/lib/logrotate/status
にローテーションするファイルの更新情報が蓄積されます.
3.2 swatch,logwatch
本来ログとは常に監視しておくものであって,異常時にのみ確認するものではありません.しかし,大量のログが出
力されるサーバではそれを監視することは不可能です.そのため,少しでも労力を減らした上で確実に必要な情報を拾
う方法を考えなければなりません.
swatch や,logwatch は出力されるログを監視するツールです.swatch はリアルタイムに重要なログをそのまま確
認することができます.また,logwatch は 1 日 1 回,ログのチェックを行い,比較的見やすい状態に加工して出力す
第 3 章 ログ管理ツールの導入
132
ることができます.サーバの利用目的に応じて,どちらかあるいは両方のツールを使用すると良いでしょう.
まず,swatch の導入方法について説明します.最初に,swatch をインストールします.
$ sudo apt-get install swatch
次に,自動起動スクリプトを作成します.
$ vi /etc/init.d/swatch
テキストエディタを開いた後,以下のようなスクリプトを記述します.
#!/bin/sh
PATH="/sbin:/bin:/usr/sbin:/usr/bin"
NAME="swatch"
DAEMON="/usr/bin/swatch"
DESC="simple watcher"
CONFFILE="/etc/swatch.conf"
#LOGFILE="/var/log/secure"
LOGFILE="/var/log/auth.log"
PIDFILE="/var/run/swatch.pid"
OPTS="--config-file $CONFFILE --tail-file $LOGFILE
--pid-file=$PIDFILE --awk-field-syntax --daemon"
test -x $DAEMON || exit 0
start() {
if [ ! -f "$CONFFILE" ]; then
echo "Error: $CONFFILE does not exist."
exit 1
fi
if [ ! -f "$LOGFILE" ]; then
echo "Error: $LOGFILE does not exist."
exit 1
fi
if [ -f "$PIDFILE" ]
then
echo "Error: $NAME is already running."
else
$DAEMON $OPTS >/dev/null 2>&1
fi
}
stop() {
if [ -f "$PIDFILE" ]
then
PID=‘cat $PIDFILE‘
if ps h $PID > /dev/null
3.2 swatch,logwatch
133
then
pkill -P $PID
else
echo "Error: $NAME is not running, but PID file exists. Deleting it."
fi
rm -f $PIDFILE
else
echo "Error: $NAME is not running."
fi
}
case "$1" in
start)
echo "Starting $DESC: $NAME"
start
;;
stop)
echo "Stopping $DESC: $NAME"
stop
;;
restart)
echo "Restarting $DESC: $NAME"
stop
sleep 1
start
;;
*)
echo "Usage: $0 start|stop|restart"
exit 1
;;
esac
exit 0
このままだとログローテート時に不具合が生じるため,以下のように/etc/cron.daily/sysklogd をテキストエディタ
で開き,最終行に次の 1 文を追加します.
$ vi /etc/cron.dialy/sysklogd
/etc/init.d/swatch restart > /dev/null
次に,作成したスクリプトに実行権限を付与し,起動テストを行います.
第 3 章 ログ管理ツールの導入
134
$ chmod a+x /etc/init.d/swatch
$ /etc/init.d/swatch start
ここまで終了したら,次は設定ファイルを作成します.
$ vi /etc/swatch.conf
例として,以下のような記述を行います.
watchfor /Did not receive identification string from/
exec "/sbin/iptables -A INPUT -s $12 -j DROP"
watchfor /Invalid user/
exec "/sbin/iptables -A INPUT -s $10 -j DROP"
exec "echo ’/sbin/iptables -D INPUT -s $10 -j DROP’ | at now+5min"
mail=root,subject=[Swatch] Invalid access
watchfor /Authentication failure for root/
exec "/sbin/iptables -A INPUT -s $13 -j DROP"
これにより,ssh でのログインに失敗した場合,5 分間アクセスを遮断してルートに通知のメールを送信することに
なります.
$ /etc/init.d/swatch start
上のようにして swatch を再起動し,自動起動の設定を行います.
$ sudo update-rc.d swatch defaults 50
これで/etc/rc*.d に自動起動のリンクが貼られます.
次に,logwatch の導入方法について説明します.まずは,logwatch をインストールします.
$ sudo apt-get install logwatch
/usr/share/logwatch/以下にデフォルトの設定ファイルが存在します.ただし,/etc/logwatch/にある設定ファイ
ルが優先され,/usr/share/logwatch/以下のデフォルトの設定ファイルに上書きされるため,/etc/logwatch/以下に
設定ファイル群をコピーして使う方がよいでしょう.次のようにして,メインの設定ファイルをコピーします.
$ cp /usr/share/logwatch/default.conf/logwatch.conf /etc/logwatch/conf/
次に,見たいログの設定ファイルをコピーします.すべてコピーしても構いませんが,量が多いので見たいものだけ
コピーする方が良いでしょう.今回の場合は,http.conf と sshd.conf をコピーします.
$ cp /usr/share/logwatch/default.conf/services/http,sshd.conf
/etc/logwatch/conf/services/
コピーが完了したら,次にこれらに関してのログのみを出力するように設定ファイルを書き換えます.
$ vi /etc/logwatch/conf/logwatch.conf
#Service = All #ここをコメントアウトする
3.2 swatch,logwatch
135
Service = http #ログを出力するものを追加
Service = sshd #ログを出力するものを追加
これだけではデフォルトの設定ファイルにすべてのログを出力する設定が残っているため,そちらの設定も変更し
ます.
$ vi /usr/share/logwatch/default.conf/logwatch.conf
#Service = All #ここをコメントアウトする
/var/cache/logwatch/をテンポラリファイルとして使用するので,ディレクトリを作成しておきます.テンポラリ
ファイルとは,ソフトウェアが作業中のデータの保存のために一時的に作るファイルのことです.メモリ上に格納しき
れない巨大なファイルの一部の一時待避や編集中のファイルのバックアップ,クリップボードの内容を保管しておくな
ど,様々な用途に利用されます.
$ mkdir /var/cache/logwatch
これで設定は完了です.あとは crontab で,1 日 1 回 logwatch が作動するように設定します.
$ sudo vi /etc/crontab
crontab をテキストエディタで開き,以下の 1 文を追加します.
0 3 *** root /usr/sbin/logwatch /etc/logwatch.conf
これで毎日午前 3 時に一度,logwatch が実行されます.
第 5 回 演習課題
目標
サーバに logrotate を導入します.
まず logrotate を導入し,ファイルの更新情報を確認して下さい.次に,ローテーションされたアクセスログを
確認して下さい.
課題 1 logrotate の導入
1–1
logrotate を実行し,/var/lib/logrotate/status にローテーションするファイルの更新情報が追加されたことを確認
して下さい.
1–2
ローテーションされたアクセスログを確認して下さい.ローテーション後のログファイルの名前は,access.log.1 と
なっています.
参考文献
[1] The Apache Software Foundation, http://httpd.apache.org/
[2] IETF syslog working group, http://www.ietf.org/dyn/wg/charter/syslog-charter.html
第6回
セキュリティ対策と運用方法
Linux サーバを運用する上で必須であるセキュリティ確保について説明します.そもそもセ
キュリティとは何か,セキュリティの定義について触れます.また,セキュリティ上の問題や
解決方法,サーバ運用においてサーバをセキュアに保つための設定方法や診断ツールなども紹
介します.演習では,iptables を用いて実際にファイアウォールを構築し,アクセスが制限され
ていることを確認することで,その動作を学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
セキュリティとは何か
1.1 セキュリティの概要
ネットワークサーバにおけるセキュリティとは機密性,完全性および可用性の維持です.提供するサービスや対象と
するユーザを明確にし,セキュリティを確保しなくてはなりません.
基本的に,インターネットの通信は暗号化されておらず,その中継点にいる人間なら誰でも盗聴できてしまうという
欠点を持ちます.また,それ以外にも,コンピュータが外部と接続されたことによって悪意のある人間が故意にコン
ピュータを破壊したり,データを改ざんしたりすることができるようになってしまいました.セキュリティとは,この
ような行為を防いで保守安全を維持することを言います.
一般に,セキュリティと利便性は相反する性質のものです.現在のコンピュータでは主にユーザ ID とパスワードに
よってユーザを認証していますが,セキュリティを確保するために利用者が頻繁にパスワードを入力するようではシス
テムが使いづらくなってしまいます.しかし,パスワードを要求しなければ情報が他人に悪用される可能性がありま
す.利便性を減らさずにセキュリティを高める方法を見付けるのがセキュリティの目標です.
1.2 セキュリティ上の問題
セキュリティ上の問題としてはコンピュータへの不正侵入や不正使用,情報の漏洩,コンピュータウィルスへの感染
などが挙げられます.
サーバを構築する際に重要となるセキュリティ上の主な問題を以下に示します.1.2.1 節から 1.2.6 節までがサーバ
を対象とした攻撃による問題で,1.2.7 節から 1.2.9 節がアプリケーションを対象とした攻撃による問題です.
1.2.1 ポートスキャン
ポートスキャンとは,セキュリティ上で問題のあるサービスや,既知のセキュリティホールをもつサービスを発見す
る際に使用する手法です.
ポートスキャンの主な種類としては,TCP コネクトスキャン,TCP ハーフスキャン(TCP SYN スキャン),UDP
スキャンなどが挙げられます.
TCP スキャンとは,3–way–handshake により TCP コネクションを確立することで,そのサービスが稼動している
かどうかを確認するものです.この場合は,サーバのログに残るため,確認が容易です.3–way–handshake について
は,図 1.1 を参照して下さい.
しかし,コネクションの確立まで行わない TCP ハーフスキャンは,ログに残らないため確認が困難です.そのため,
ステルススキャンとも呼ばれています.
もともとコネクションを確立しない UDP を用いた UDP スキャンでは,いきなりデータを送りつけ応答が返ってく
るかどうかでサービスが稼動しているかを判断しています.
1.2 セキュリティ上の問題
141
図 1.1 3–way–handshake の概要
1.2.2 パスワードクラック
パスワードクラックとは,他人のパスワードを探り当てることです.これはネットワーク上での攻撃の基本となりま
す.推測しやすいパスワードだとすぐに見破られてしまうため,管理の甘いユーザが増えた今では大きな問題となって
います.
攻撃方法としては,推測や辞書攻撃,総当たり攻撃(ブルートフォースアタック)などが挙げられます.姓名や生年
月日,辞書に載っているような単語をパスワードに使うのは避けるべきです.また,アルファベットだけではなく数字
や記号を混在させることも,被害を抑えるのに有効な手段となります.
1.2.3 セッションハイジャック
セッションハイジャックとは,セッションを管理する ID やクッキー情報を盗聴し,セッションを奪い取ることを指
します.セッション ID が推測可能な文字列であったり,暗号化されていない通信経路で盗聴されたりすると,被害に
遭う可能性が増します.セッションが盗まれると,そのセッションを利用していたユーザーになりすましたアクセスが
行えるため,個人情報が盗まれたり,コンピュータに侵入されたりする危険性があります.
セッションハイジャックにも種類があり,TCP におけるセッションハイジャックや UDP におけるセッションハイ
ジャック,Web サーバとクライアント間のセッションハイジャックなどがあります.また,セッションハイジャック
によく用いられる手法として,Man–in–the–Middle Attack(中間者攻撃)などがあります.
Man–in–the–Middle Attack とは,通信を行なう二者の間に第三者が割り込む攻撃のことです.両者が交換する公開
情報を自分のものとすりかえることで,通信者に気付かれることなく盗聴したり,通信内容に介入したりできます.
Man–in–the–Middle Attack を用いたセッションハイジャックの例を,図 1.2 を用いて解説します.図のように,通
信を行なう A と B の間の経路上で,攻撃者が中継を行なうとします.まず,A はコネクションを確立するために,B
142
第 1 章 セキュリティとは何か
に SYN を送ります.この際のセッション ID を 1000 とします.次に,B はコネクションの確立を許可するために,
SYN/ACK を返します.B から送られてきた SYN に対して A が ACK を返す前に,攻撃者が正しいセッション ID で
RST(リセット)を返すとそのコネクションは中断されてしまいます.この場合,A が ACK を返してもすでに接続は
切断されているため,そのパケットは破棄されてしまいます.その後,攻撃者が A のセッション管理情報を用いて B
に SYN を送った場合,B は A に SYN/ACK を送信します.A は SYN を送っていないため,そのパケットを破棄し
ますが,ここで攻撃者が B に対して ACK を送ると,攻撃者と B の間でコネクションが確立してしまいます.これで
セッションハイジャックが成功したことになります.
1.2 セキュリティ上の問題
143
図 1.2 Man–in–the–Middle Attack を利用したセッションハイジャックの例
1.2.4 DNS サーバに対する攻撃
DNS サーバに対する攻撃として,ゾーン転送要求による登録情報の収集や DNS キャッシュポイゾニング,不正な
リクエストによりサービス不能状態を引き起こす攻撃などがあります.
ゾーン転送要求による登録情報の収集とは,その名の通りネットワークやサーバの構成を収集する攻撃のことです.
ゾーン転送するデータ範囲を制限していない場合には,セカンダリ DNS サーバ以外にもゾーン転送の応答を返してし
まうため,そのような情報を収集されてしまいます.
DNS サーバはクライアントからの要求に効率的に応答するためにキャッシュという仕組みを備えています.DNS
キャッシュポイゾニングは,このキャッシュに偽の情報を教え込む攻撃のことです.DNS サーバだけではなく,DNS
機能を内蔵したルータなども攻撃対象になるため,被害が広範囲に及ぶ危険性があります.
手順として,まずターゲットとなる DNS サーバーに要求パケットを送ります.その直後に,偽の情報を記載した応
答パケット送り付けます.正規の応答パケットが届く前に,偽の情報を記載した応答パケットを送り込むことで,偽の
情報をキャッシュさせます.偽の情報をキャッシュさせられた DNS サーバーは,クライアントの DNS 要求に対して,
偽のアドレス情報を返答します.その結果,クライアントは偽のアドレスにアクセスすることになるので,攻撃者にパ
ケットの内容を盗聴されたり,フィッシング詐欺の標的にされる危険性が出てきます.
144
第 1 章 セキュリティとは何か
不正なリクエストによりサービス不能状態を引き起こす攻撃とは,仕様上,または実装上の脆弱性を突いて不正な要
求を与える攻撃のことです.例として,2002 年に hosts ファイルの書き換えにより,ルート DNS サーバ 13 台のうち
9 台が一時的にサービスを提供できなくなってしまったことが挙げられます.
1.2.5 DoS 攻撃
DoS (Denial of Service) 攻撃とはネットワークを通じた攻撃の 1 つで,サービス不能攻撃とも呼ばれます.システ
ムリソースを過負荷状態にしたり,ネットワーク帯域をあふれさせたりする攻撃です.また,セキュリティホールを突
いてアプリケーションを異常終了させることもあります.
DoS 攻撃の種類としては,SYN Flood 攻撃や DDoS(Destributed DoS : 分散型サービス不能)攻撃,DRDoS
(Distributed Reflection DoS : 分散反射型サービス不能)攻撃などが挙げられます.
SYN Flood 攻撃とは,発信元アドレスを偽装した SYN パケットを大量に送り,タイムアウトが起こる前にリソー
スを食い潰す攻撃です.発信元アドレスを偽装しているため,攻撃者の特定は困難です.
DDoS 攻撃とは,複数の攻撃元が一斉に特定のサーバへパケットを送出し,通信路を溢れさせてサービスを停止させ
てしまう攻撃のことです.外部の悪意ある第三者にコンピュータを操られ,一般の利用者や管理者が気付かないうちに
攻撃に参加させられてしまうといった特徴があります.
クラッカーは,多数のコンピュータにトロイの木馬と呼ばれる攻撃実行用のプログラムを仕掛けます.攻撃者はこの
トロイの木馬に対して一斉にパケットの送出命令を発行するだけで,攻撃を開始することが可能です.標的となった
サーバには,トロイの木馬が仕掛けられたコンピュータからパケットが送り込まれるため,真の攻撃元を割り出すこと
は困難です.
DDoS による妨害アクセスは通常のアクセスと見分けがつきにくく,選択的に排除するのが困難です.このため,標
的のサーバにセキュリティ上の弱点を放置するなどの管理のミスがなくても被害が発生してしまいます.
DRDoS 攻撃とは,送信元の IP アドレスを攻撃対象のサイトのものに偽装した大量の SYN パケットを多数のサー
バに送信する攻撃です.これにより,そのサーバからの応答パケットを大量に集中させることが可能です.攻撃パケッ
ト単体では特に不正なものではないため,防ぐのが困難です.
1.2.6 コンピュータウイルス,ワーム
コンピュータウイルスとは,他人のコンピュータに侵入し,異常な動作を行うプログラムの一種です.コンピュータ
ウイルスに感染すると,ディスクに保存されているデータが破壊されたり,画面上に無意味な文字やウィンドウが表示
されたりします.ウイルスはインターネットからダウンロードしたファイルや,他人から借りた記憶媒体などを通じて
感染します.最近では e–mail を介して感染するタイプのウイルス(ワーム)もあります.大抵は使用者の知らないう
ちに感染します.またウイルスに感染したことに気付かずにコンピュータを使用し続けると,他のコンピュータにウイ
ルスを移す危険性もあるため注意が必要です.
ワームとは,自己増殖を繰り返しながら破壊活動を行なうプログラムのことです.以前は CD–ROM やフロッピー
ディスクなどに潜伏して感染するものが主流でしたが,近年ではインターネットの普及により,電子メールなどを介し
て爆発的な速度で自己増殖するものが出現し問題となっています.作成が容易なため亜種の登場も早く,その種類は急
増しています.
1.2.7 バッファオーバーフロー攻撃
バッファオーバーフロー攻撃とは,バッファに対して許容量を超えるデータを送り付けてシステムを機能停止にした
り,意図的にバッファをオーバーフローさせ,溢れ出たデータを実行させてしまう攻撃のことです.バッファオーバー
1.2 セキュリティ上の問題
145
フロー攻撃は最も代表的なセキュリティホールであり,昔からさまざまな OS やアプリケーションに多く存在している
問題です.現在 OS で見つかっているセキュリティホールの半数以上はバッファオーバーフロー攻撃によるものといわ
れています.
また,バッファオーバーフロー攻撃は,主にサーバの管理者権限を奪取するために用いられます.その手法として
setuid や setgid を利用するものがあります.setuid, setgid とは,実行されたプログラム(プロセス)のユーザ権限
にそのプログラムの所有者の実行権限を一時的に設定するコマンドです.例えば,一般ユーザでパスワードファイ
ル (/etc/passwd) を開くことは不可能ですが,パスワードコマンド (/bin/passwd) を実行することは可能です.この
パスワードコマンドの所有者は root なので,setuid を使用するとその一般ユーザに root の実行権限が付与されてしま
います.
1.2.8 クロスサイトスクリプティング
クロスサイトスクリプティング (XSS) とは,ソフトウェアのセキュリティホールの 1 つです.Web アプリケーショ
ンが動的に HTML を生成する仕組みになっている掲示板などのページが,訪問者のブラウザに悪意のあるコードを送
るというものです.
フォームから JavaScript などのスクリプトコードを入力した際にプログラム側で適切な処理を行わないと,そのス
クリプト内容がそのまま HTML に埋め込まれてしまいます.そのため,ページを閲覧したコンピュータでスクリプト
がそのまま実行されてしまうことがあります.Web ブラウザは,このような形でページに埋め込まれてしまったスク
リプトでも正規のスクリプトであると認識してしまいます.そのため,ブラウザ側でこの問題を防止するには,スクリ
プトを使用しない設定にするしかありません.
悪意のあるコードを直接埋め込んで実行させるほかに,ユーザに認識のないまま他所のスクリプトを呼び出して実行
するよう仕向けることが可能です.そのため「クロスサイト」の名がついています.
スクリプトの内容によっては Cookie データの盗聴や改ざんなどが可能です.そのため,商取引に使った Cookie を
横取りして,本人になりすまして物品の購入を行なったり,Cookie を認証やセッション管理に使っているサイトに侵
入したりする可能性があります.
1.2.9 SQL インジェクション
SQL インジェクションとは,データベースと連動した Web サイトを対象とした攻撃手法です.データベースへの問
い合わせや操作を行うプログラムにパラメータとして SQL 文の断片を与えることで,データベースの改ざんや不正な
情報の入手が可能です.
多くの Web アプリケーションではデータベースの操作に SQL という言語を利用しています.ユーザがフォームか
ら送信した検索語などのパラメータを受け取り,これを SQL 文に埋め込んでデータベースへの問い合わせや操作を行
います.このとき,SQL 文の断片として解釈できる文字列をパラメータに含めることで,プログラムが想定していな
い SQL 文を合成します.これにより不正にデータベースの内容を削除したり,本来アクセスできない情報を表示させ
たりすることができてしまう場合があります.
SQL インジェクションは,クロスサイトスクリプティングと同様にプログラム側での入力データのチェック不足で
起こることが多いです.そのため,データベースのアクセス権や Web サーバのエラーメッセージ処理を正しく設定し
なければなりません.
第2章
セキュリティポリシー
セキュリティの確保のためには,ネットワークサーバで提供するサービスの種類や提供するユーザ,運用方法などを
系統立てて策定したセキュリティポリシーを作成することが重要です.実際のサーバ設計,構築および運用はセキュリ
ティポリシーに沿って作業を実施する必要があります.
2.1 セキュリティポリシーとは
セキュリティポリシーとは,企業全体の情報セキュリティに関する基本方針のことです.広義には,セキュリティ対
策基準や個別具体的な実施手順などを含みます.誰がその情報を読み取れるようにするのか,誰に対してどの操作を許
可するのか,どのデータを暗号化するのかなど,情報の目的外利用や外部からの侵入,機密漏洩などを防止するための
方針を定めたものです.コンピュータウイルス感染によるデータやシステムの破壊や,トラブルによる情報システムの
停止,データの喪失などに対してどう対処していくか,といった項目まで含める場合もあります.
セキュリティポリシーを策定し公開することにより責任の所在が明らかになり,判断基準や実施すべき対策が明確に
なります.社員のセキュリティに対する意識や対外的なイメージ,信頼性が向上するといったメリットもあります.
2.2 法律との違い
一般的に,企業や個人を守る方法として法律などの制定が考えられますが,セキュリティの分野においてほとんどの
場合,守るべき情報資産や脅威・脆弱性の種類などが企業や組織ごとに異なります.そのため,一元的な法律などで保
護できる範囲に限界があります.そこで,各企業や組織が自分たちで判断して情報セキュリティポリシーを策定するこ
ととなります.
2.3 セキュリティポリシーの作成
情報セキュリティポリシーを策定する場合,一般的には 3 段階に分類されます.
2.3.1 情報セキュリティ基本方針
会社としてのセキュリティへの取り組み指針や基本理念などを示す文書のことです.対外的なアピールもこの文書に
よって行われるため,必要最低限のことだけが書かれています.経営層レベルが策定し,社長などの名前で公表され
ます.
2.3 セキュリティポリシーの作成
147
2.3.2 情報セキュリティ対策基準
基本方針に基づいて,情報セキュリティ対策を具体的に行う際の基準をまとめたものです.そのため,基本方針より
も具体的な記述が多くなります.基本方針は会社の文書として提出されますが,対策基準は各部署ごとに異なるものが
作成されます.
基本方針と対策基準の 2 つを合わせて情報セキュリティポリシーとよびます.しかし,企業によっては対策実施手順
を含めた 3 段階の全体を情報セキュリティポリシーとする場合もあります.
2.3.3 情報セキュリティ対策実施手順
実際にどのような手順を踏めば,セキュリティを維持できるのかを示した文書のことです.スキルのない社員でも対
処できるように,詳細な業務手順を文書化しています.手順を示しているため,セキュリティプロシジャとも呼ばれ
ます.
第3章
セキュリティ上の問題への対策方法
既知の問題に対しては,その問題に対応した対策が可能です.しかし,新しい攻撃は日々生まれるため,そういった
問題に対処する一般的な方法も知らなければなりません.
一般的なセキュリティ対策として,各種診断ユーティリティの使用,サービスの実行状況の確認と設定,システムロ
グのチェック,ネットワークの監視,システムのアップデート,通信の暗号化,システムパスワードのチェック,シス
テムパスワードの保護などの実施が挙げられます.
3.1 サービス実行状況の確認
サービスの実行状況は,chkconfig コマンドによるサービスの自動起動の確認や,service コマンドによるサービスの
稼動状態の確認により行うことができます.
3.2 システムログのチェック
ログの内容を見ることで,ユーザーの利用状況や不正利用の痕跡を把握できます.そのため,定常状態を把握し異常
を検知することが可能です.記録されるメッセージの内容は多岐にわたり,その量も多いためログのチェックは簡単で
はありません.不正利用の痕跡を見つけるためには,正常運用時からログファイルをチェックして,システムやアプリ
ケーションがどのようなログを記録するのかを覚えておくことが大切です.
3.3 ネットワークの監視
ネットワークやサーバ全体の稼動状況は,SNMP(IP ネットワーク上のネットワーク機器を監視・制御する)や
MRTG(ネットワークの負荷を監視する)により監視することができます.
3.4 システムのアップデート
システムのアップデートを怠ると,そのシステムがセキュリティホールになる可能性が生じます.そのため,Linux
カーネルやサービスプログラムなどにセキュリティ上の問題が発見された場合,できるだけ早く対策を行う必要があり
ます.
3.5 通信の暗号化
ネットワーク上の通信を安全に行うために,暗号鍵を用いて暗号化するという方法が用いられます.暗号鍵とは,
データの暗号化を行なう際に,暗号方式の定めた計算手順に与えるパラメータのことです.暗号化では平文に一定の計
3.6 システムパスワードのチェック・保護
149
算・処理を行なって暗号文を生成しますが,このとき平文とともに暗号鍵を用いて計算を行ないます.同じ平文を同じ
方式で暗号化しても,異なる暗号鍵を用いれば異なる暗号文が得られます.解読の際には秘密鍵暗号の場合には暗号鍵
が,公開鍵暗号の場合には暗号鍵と対になるもう 1 つの鍵が,それぞれ必要となります.
3.6 システムパスワードのチェック・保護
パスワードは設定するだけではなく,ある程度の強度を持たせる必要があります.また,パスワードの解析を防ぐた
めにはパスワードに有効期限を設定し,定期的にパスワードを変更する必要があります.パスワードの文字数や有効期
限は/etc/login.defs で設定することができます.
3.7 ファイアウォールの設定
ファイアウォールとは,不正アクセスを防止するためのセキュリティ機器です.IP アドレスによるパケットフィル
タリングが基本ですが,最近では,ポート番号やアプリケーションデータ内部の情報をもとに通信の可否を決定する高
機能な製品が多いです.
現在のセキュリティモデルは,ネットワークをローカル(内)とリモート(外)に分け,ローカルネットワークのセ
キュリティを維持する設計思想となっています.この思想をぺリメータセキュリティモデルといいます.このモデルに
おいて内と外の境界に設置するものがファイアウォールです.ファイアウォールは,専用のハードウェア,もしくは一
般的な OS にインストールするソフトウェアとして実装されています.
ファイアウォールという用語は,広義にはセキュリティ境界に置かれるゲートウェイのことを指しますが,パケット
フィルタリング型やトランスポートゲートウェイ型などの細かい機能的な区別があり,運用を行う場合はそうした差異
を理解する必要があります.
第4章
セキュリティ上の問題への対処方法
対策を施していても,セキュリティホールを突かれて安全が脅かされることは多々ありえます.その場合は,適切に
対処しなければ被害の拡大にも繋がってしまうため注意が必要です.
4.1 コンピュータウイルスに感染後の対処
ウィルス感染後の対応手順として,初動対応,復旧,事後処理があります.
ウィルスに感染した場合,二次感染を防ぐため速やかに感染ノードをネットワークから切断して使用を中止します.
原因の特定などは後回しにし,後の解析で必要なスナップショットなどを記録するに留めておきます.その後,ウィル
スの感染があったことをユーザに通知して注意を呼びかけるとともに他の感染例がないかチェックします.
これらの初動対応の措置が済んだ後,ウィルスの特定と復旧作業に着手します.復旧作業中に二次感染を引き起こさ
ないよう,完全に遮断された環境で作業を行い,十分なチェックを行ってからネットワークへ接続します.ウィルスが
特定できない場合や,除去が不可能な場合は OS の再インストールを行う必要があります.これらの復旧作業手順は必
ず記録に残し,後日監査できるようにします.
復旧が完全に完了した後,再発防止策の策定と実施,関係機関への通知を行います.
第5章
セキュリティ対策ツールの導入
5.1 chkrootkit
chkrootkit とは,システムへ rootkit が設置されているのかを簡単にチェックできるプログラムです.一般的に
rootkit だけではなく,カーネル基盤の rootkit,ワームまでも探知可能です.
rootkit とは,攻撃者がハッキングに成功した後,次に侵入しやすくするためにバックドアやトロイの木馬プログラ
ムを設置するようなプログラムのことです.
rootkit に含まれるプログラムとしては ps,ls,netstat,login 等のシステムプログラムがあります.このような
rootkit は,システムに元々あった正常なプログラムと入れ替えて使用されます.たとえば,ps や ls といったプログラ
ムと入れ替えて,管理者がシステムを点検しても,攻撃者が実行したプロセスや設置したファイルを確認できないよう
にすることが可能です.
最近はこのように一般的な rootkit が管理者によって簡単に探知できるため,自分の痕跡をより完璧に隠すためカー
ネル基盤の rootkit を設置する場合があります.カーネル基盤の rootkit は,現在実行されているカーネルに攻撃者が
作ったカーネルモジュールを積載して,システム関数の正常的な実行を変える方法です.
本ツールはワームなどの攻撃に有効な対策となります.
chkrootkit の導入方法を紹介します.まずは,chkrootkit をインストールします.
$ sudo apt-get install chkrootkit
インストールが完了したら,chkrootkit を実行してみます.
$ chkrootkit|grep INFECTED
実行結果として”INFECTED” という行が表示されなければ問題ありません.
確認が終了したら,chkrootkit を定期的に自動実行するようにします.
$ sudo vi /etc/crontab
crontab をテキストエディタで開き,以下の 1 文を追加します.
0 3 * * * root /usr/sbin/chkrootkit
これで毎日午前 3 時に一度,chkrootkit が実行されます.
5.2 iptables
iptables とは,パケットフィルタを行うソフトウェアで,Linux カーネル 2.4 以降に組み込まれています.主に PC
をルータとして使うとき,通過するパケットを検査して必要ないパケットを破棄します.この機能を使うことで,ファ
第 5 章 セキュリティ対策ツールの導入
152
イアウォールとして活用することができます.
iptables では,コンピュータがやり取りするパケットをあらかじめ定義しておいたチェイン単位に分類し,チェイン
ごとにどのような処理を行うかをルールとして設定します.チェインとはどのタイミングで処理を行うのかを示すもの
です.
主な Linux ディストリビューションでは,INPUT(サーバーへ到達するパケット),FORWARD(サーバーを通過
するパケット),OUTPUT(サーバーから送出するパケット)の 3 種類のチェインが標準で用意されています.また,
ユーザーが新しいチェインを追加することもできます.
ルールでは,パケットの送出元やパケットのあて先,該当するパケットに対してどのような処理を行うのかを指定し
ます.処理には,DROP(パケットを破棄する),REJECT(拒否パケットを送出する)
,ACCEPT(許可をする)な
どを指定します.
本ツールはポートスキャンやバッファオーバーフロー,DoS 攻撃などに有効な対策となります.
iptables を利用した,ファイアウォールの設定方法を紹介します.まず,/usr/local/sbin 以下に set iptables という
スクリプトを作成し,権限を付与します.
$ sudo vi /usr/local/sbin/set iptables
$ sudo chmod u+x /usr/local/sbin/set iptables
スクリプトの中身を書き,コマンドを実行すると iptables に記録されます.
#!/bin/sh
# 初期化
iptables -F
# デフォルトルール
iptables -P INPUT DROP
# 内部への通信を拒否
iptables -P OUTPUT ACCEPT
# 外部への通信を許可
iptables -P FORWARD DROP
# 通過を拒否
# 自分からのアクセスを許可
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# 内部から始まった外部からの応答を許可
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$ sudo /usr/local/sbin/set iptables
trusthost にはサービスを開放するマシンの範囲を記述します.開放するマシンが 1 台の場合は IP を直接指定し,サ
ブネット内にオープンするならサブネットを指定します.全てに開放する場合は,0.0.0.0/0 とします.今回は自分の
マシンの IP アドレスを指定します.
その他,サービスごとの設定を追加していきます.例えば,$trusthost からの ssh 接続を受け付ける場合は,以下の
ような記述を追加します.
iptables -A INPUT -p tcp –dport 22 -j ACCEPT
22 とは,ssh で使用される標準のポート番号です.表 5.1 に,よく使用されるアプリケーションとポート番号の一覧
5.3 Tripwire
153
を示します.
表 5.1
ポート番号
アプリケーションとポート番号の例
アプリケーション
21
File Transfer (Control)
22
SSH Remote Login Protocol
25
Simple Mail Transfer Protocol
80
World Wide Web HTTP
443
http protocol over TLS/SSL
iptables が自動起動されるように設定したい場合,sysv-rc-conf というコマンドを利用します.コマンドの使い方を
知りたい場合は以下のようにします.
$ sudo sysv-rc-conf -h
iptables を自動起動したい場合は以下のようにします.
$ sudo sysv-rc-conf --level 2345 iptables on
5.3 Tripwire
Tripwire [1] とは,ファイルの改ざん防止を目的とするツールです.ファイルの書き換えを監視することにより,
身に覚えのない変更がファイルに加えられた場合にそれを検出し,またある時点での設定状態に書き戻すことが可能
です.
Tripwire は,SIV (System Integrity Verifier),またはインテグリティチェッカ (Integrity Checker),整合性チェッ
クツールと呼ばれるソフトウェアの 1 つです.ホスト型 IDS(侵入検知システム)に分類される場合もあります.ホス
トの重要なファイル群の完全性をチェックし,ファイルの改ざんの有無を検出します.
Tripwire は米パーデュ大学において Gene Kim 氏が学生時代に Eugene Spafford 教授とともに開発しました.正常
時点で,MD5 (Message Digest 5) や SHA1 (Secure Hash Algorithm 1) などのハッシュ関数を利用しファイルのダ
イジェスト値をデータベースに保存します.その後,任意のタイミングでファイルのダイジェスト値を計算し,異なっ
ていれば異常とします.オープン・ソース版と米 Tripwire 社による商用製品版があります.
Tripwire の導入方法を紹介します.まずは,Tipwire をインストールします.
$ apt-get install tripwire
インストールが完了したら,Tripwire を初期化します.
$ cd /etc/tripwire/
$ ./twinstall.sh
スクリプトを実行すると,site keyfile passphrase と local keyfile passphrase を尋ねられるので入力し,メモを取っ
ておきます.その後,再度 site keyfile passphrase の入力を 2 回求められるので,先に入力したパスフレーズを入力し
ます./etc/tripwire ディレクトリに,表 5.2 のようないくつかのファイルが生成されたのを確認します.
暗号化されていない*.txt ファイルは改ざんされる恐れがあるため,一通り設定が終わり運用を開始したら削除した
ほうがよいでしょう.
ファイルが生成されたのを確認したら,次はポリシーファイルを作成します.
第 5 章 セキュリティ対策ツールの導入
154
表 5.2 初期化により生成されるファイル一覧
ファイル名
説明
***-local.key
ローカルキーの格納されたファイル.ローカルキーで保護されたファイルに書き込むには
ローカルパスフレーズが必要.*** の部分はローカルホスト名.
site.key
サイトキーの格納されたファイル.Tripwire の設定ファイル・ポリシーファイルの書き
込みにはサイトパスフレーズが必要.
tw.cfg
Tripwire の設定ファイル.twcfg.txt をサイトキーで暗号化したもの.
tw.pol
Tripwire のポリシーファイル.twpol.txt をサイトキーで暗号化したもの.
twcfg.txt
暗号化されていない Tripwire の設定ファイル.サンプルとして付属している.
twpol.txt
暗号化されていない Tripwire のポリシーファイル.ファイルやディレクトリのチェッ
クを行なうためのポリシーが記述されている.サンプルとして付属している.
$ twadmin -m F -c /etc/tripwire/tw.cfg -S /etc/tripwire/site.key
/etc/tripwire/twcfg.txt
上のようなコマンドを入力すると,先程設定したサイトパスフレーズを聞かれるので,それを入力します.その後,
以下のような 1 文が出れば成功です.
Wrote configuration file: /etc/tripwire/tw.cfg
ポリシーファイルを作成したら,テキスト版の Tripwire 設定ファイルは削除します.
$ rm -f /etc/tripwire/twcfg.txt
テキスト版の設定ファイルを復元したい場合は,以下のようなコマンドを入力します.
$ twadmin -m f -c /etc/tripwire/tw.cfg > /etc/tripwire/twcfg.txt
次に,ポリシーファイルを元に現時点でのディレクトリやファイルの情報を収集して,ベースラインデータベースを
作成します.
$ tripwire -m i
これを実行すると,ローカルパスフレーズの入力を求められます.デフォルトのサンプルファイルをそのまま使用し
た場合,インストールされているパッケージの組み合わせによってはエラーがいくつも出ることがあります.これはポ
リシーファイルに記述されたチェック対象のファイルやディレクトリが存在しないためです.エラーが出た部分につい
ては,ポリシーファイルでコメント化してから,ベースラインデータベースの作成をやり直す必要があります.
データベースファイルは/var/lib/tripwire/に(ローカルホスト名).twd というファイル名で作成されます.この
ファイルの内容を確認するには,twprint コマンドを使います.
$ twprint -m d -c tw.cfg -d /var/lib/tripwire/(ローカルホスト名).twd | more
これを実行すると,データベースの内容が大量に表示されます.ここには/bin 以下のファイルの所有者,サイズ,権
限などの情報が格納されています.
ベースラインデータベースを作成したら,手動でチェックします.
$ tripwire -m c
5.3 Tripwire
155
ファイル数が多いため,チェックには時間がかかります.しばらくすると結果が表示されるので,Section: Unix
File System の項を確認します.まだ何もファイルが変更されていないため,No violations. と表示されます.
次にファイルを変更して再検査してみます.対象となっているファイルであればどのファイルでも構わないので,
touch コマンドでタイムスタンプを変更して,tripwire でのチェックをしてみます.
$ touch /etc/apache2/apache2.conf
$ tripwire -m c
これによって,以下のような文を含む結果が出力されます.
Modified:
"/etc/apache2"
"/etc/apache2/apache2.conf"
ファイルの変更を検知できることは分かりましたが,設定ファイルの正当な変更も検知されてしまっては困ります.
そのため,ベースラインデータベースを更新する必要があります.この作業を自動化するために,以下のようなスクリ
プトを作成します.
$ vi tripwire.sh
#!/bin/bash
PATH=/usr/sbin:/usr/bin:/bin:/usr/local/tripwire/sbin
# パスフレーズ設定
LOCALPASS=xxxxxxxx # ローカルパスフレーズ
SITEPASS=xxxxxxxx
# サイトパスフレーズ
cd /etc/tripwire
# Tripwire チェック実行
tripwire -m c -s -c tw.cfg|mail -s "Tripwire(R) Integrity Check Report in ‘hostname‘" root
# ポリシーファイル最新化
twadmin -m p -c tw.cfg -p tw.pol -S site.key > twpol.txt
rm -f twpol.txt* *.bak
# データベース最新化
rm -f /usr/local/tripwire/lib/tripwire/*.twd*
tripwire -m i -s -c tw.cfg -P $LOCALPASS
スクリプトを作成したら,以下のように実行権限を付与し,定期的に自動実行するようにします.
$ chmod 700 tripwire.sh
$ echo "0 3 * * * root /root/tripwire.sh" > /etc/cron.d/tripwire
これで,毎日 3 時にスクリプトが実行されるようになりました.
第 6 回 演習課題
目標
iptables を用いてファイアウォールを構築します.
スクリプトを記述・実行し,ssh による接続の遮断の有無を確認して下さい.また,Web サーバのポートの開放
を行って下さい.
課題 1 iptables を用いたファイアウォールの構築
1–1
iptables のスクリプトを書いて実行した際に,ssh での接続が遮断されることを確認して下さい.
1–2
ssh に関する記述をスクリプトに追加して実行した際に,ssh による接続が可能になったことを確認して下さい.
1–3
以上の実行によって,Web サーバにもアクセスできなくなっています.そこで,Web サーバのポート番号を調べ,
iptables でポートの開放を行って下さい.
注意:info.php か test.cgi で動作確認を行って下さい.
参考文献
[1] Tripwire, Inc., http://www.tripwire.org/
第7回
オープンソースの開発ツール
ソフトウェア開発において利用可能なオープンソースの開発ツールを紹介します.OSS として
利用できる分析・設計ツール,プログラミング支援ツール,ビルドツール,テストツールといっ
た各種ツールの概念と使い方について解説します.演習では,実際に Eclipse 上で JUnit によ
るテストケースを作成・実行することにより,テスティングフレームワークの利用方法を学び
ます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
OSS とは
OSS(Open Source Software)とは,プログラムソースが公開されており,誰もが複製や修正が可能なソフトウェ
アのことです.ソフトウェアのソースが公開されているかどうかが焦点であり,ソフトウェア自体が無償であるかは関
係ありません.この OSS に対して,ソフトウェアのソースを公開しないソフトウェアをプロプライエタリと呼びます.
また,OSG-JP(Open Source Group Japan)はオープンソースソフトウェアを推進する機関であり,オープンソー
スライセンスの日本語参考訳を多く公開しています.OSG-JP は,オープンソースを次のように定義しています [1].
1. 自由に再頒布ができること
2. 自由にソースコードを入手できること
3. 自由に派生物を作ることができ,同じライセンスを適用できること
4. パッチなどの配布には,同一性の保持を要求してもよい
5. 個人やグループに対する差別の禁止
6. 利用する分野に対する差別の禁止
7. 再頒布の際の追加ライセンスを禁止
8. 特定製品でのみ有効なライセンスの禁止
9. 他のソフトウェアを制限するライセンスの禁止
10. ライセンスは技術中立的でなければならない
1.1 ライセンス
オープンソースソフトウェアはソースコードが公開されているため,容易に利用することが可能です.しかしながら
複製や改変したソフトウェアの再頒布については,ライセンス毎に条件が違うため注意が必要です.
表 1.1 は,複製・改変・再頒布する場合の条件です.継承はライセンスの継承が義務付けられていることを示します.
著作権は著作権の明示が義務付けられていることを示します.無保証はソフトウェアを利用したことによる不利益につ
いて,著作者はその責任を負わないことをであり,これを明示することが義務付けられています.公開はソースコード
の公開が義務付けられていることを示します.
再頒布の条件以外にも,各ライセンスには様々な特徴があります.また,全ての著作権を放棄する考え方にパブリッ
クドメイン(Public Domain)がありますが,日本での著作権法では著作権の放棄は認められていません.
修正 BSD ライセンス [2]
修正 BSD ライセンスは派生物への制限が緩いライセンスとして有名なため,広く使用されています.修正 BSD ラ
イセンスが適用されているソフトウェアには,FreeBSD や PostgreSQL などがあります.
1.1 ライセンス
161
表 1.1 ライセンスの特徴
ライセンス名
継承
New BSD License
著作権
無保証
◦
◦
公開
GPL2
◦
◦
◦
◦
GPL3
◦
◦
◦
◦
Apache License 2.0
◦
◦
MIT License
◦
◦
GNU General Public License version2 [3]
フリーソフトウェア財団(FSF: Free Software Foundation)によって 1991 年 6 月に公開されました.GPL の改訂
で既に第 3 版が公開されていますが,一般に GPL といった場合には GPL 第 2 版を指します.規約の第 7 節に書かれ
た,ソフトウェアは全ての人に自由に使われるべきであるとの思想を端的に表した言葉「自由,でなければ死」はとて
も有名です.
GNU General Public License version3 [4]
FSF によって 2007 年 6 月 29 日に公開されました.GPL2 との大きな違いは,Tivozation(TiVo 化とも)を阻止
する制限が加えられたことです.Tivozation とは,オープンなソースコードを利用するが,そのアップデート版の上
書きができないようにする措置がハードウェアに組み込まれていることを指します.つまり,Tivozation の阻止とは
GPL3 を適用したソースコードを利用する場合に,その修正を必ず受け入れなければならないことを義務化することで
あり,商用には利用が難しいとされる要因となりました.
Apache License, Version 2.0 [5]
Apache ソフトウェア財団(ASF: Apache Software Foundation)によって 2004 年 1 月に公開されました.Apache
ライセンスは非常に緩いライセンスであり,頒布される派生物が同じライセンス(Apache ライセンス)で頒布される
ことを要求しません.つまり,コピーレフトなライセンス以外で頒布することも可能です.ただし,頒布する派生物に
は Apache ライセンスのコードが使用されていることを明記する必要があります.
ASF と FSF は,Apache License 2.0 と GPL3 が互換であるとしているため,2 つのライセンスを適用した(デュア
ルライセンス)ソフトウェアを配布することも可能となっています.
MIT License [6]
マサチューセッツ工科大学(MIT: Massachusetts Institute of Technology)が公開するライセンスの 1 つです.
MIT はこれ以外にもライセンスを公開していますが,一般に MIT License というと X11 の頒布に使用されたライセ
ンスを指します.そのため,厳密に使い分ける場合には X11 License 又は X License と表記される場合もあります.
Apache ライセンスと似ており,非常に緩いライセンスとして有名で,著作権表示と無保証の明示の他は頒布の条件は
ありません.
修正 BSD ライセンスと MIT ライセンスは,ほとんど同じ内容となっています.
第2章
開発ツール
開発ツールとはソフトウェアの開発において,プログラムの作成やデバッグをサポートするためのソフトウェアの集
合体です.そのため,開発ツールには開発を容易にするための様々な機能が要求されます.開発の言語やそのツールに
よっても求められる機能は異なりますが,一般的に便利な機能の一部を紹介します.
統合開発環境(IDE: Integrated Development Environment)とは,統合という言葉の通り複数のツールが組み合わ
されています.その中には,ソースコードを作成するためのエディタやビルドツールなどが含まれます.IDE は GUI
であることが多く操作が容易なことと,インストール直後から機能が豊富に用意されているために,初心者から上級者
まで幅広く利用されています.現在,OSS の IDE として最も有名なものに Eclipse があります.
また,高機能なエディタを開発ツールとして使用する場合も考えられます.代表的なものは Vim や Emacs です.こ
れらは,エディタの機能に,様々な機能を付与することで成長してきました.そのため,インストール直後は使用でき
る機能が限られており,その設定方法も IDE などの GUI と比較して少し難しくなっています.
実装の工程では,コンパイルのように何度も同一の手順を行う場合があります.この一連の手順を登録して呼び出す
ことで,自動的に手順を再生することができる開発ツールをビルドツールと呼びます.このビルドツールを利用するこ
とで,手順の漏れをなくし開発の効率を上げることができます.
2.1 コーディングサポート
ソフトウェア開発を行うためのツールには,ソースコードを作るサポートを行う機能が含まれていることが望ましい
と言えます.例えば,関数名や変数名の補完機能や予約語の強調表示機能は,タイプミスなどのヒューマンエラーの削
減に貢献します.これらの機能については開発言語の特徴に合ったツールを利用することが一般的ですが,本テキスト
では,それらに依存しない一般的な機能についてのみ紹介します.
2.2 テストツール
ソフトウェア開発には設計・開発と同じくらい重要な工程に「テスト」があります.特に,利用者が想定する動作以
外をバグと呼び,それを発見することが本工程の目的となります.また,テストのみを目的とする開発ツールは,特に
テストツールと呼ばれています.このテストツールは,開発言語や環境に依存することが多いため,開発に応じて選択
する必要があります.
第3章
開発ツールの紹介
本テキストでは,開発ツールの中でも重要なエディタとビルドツールを中心に紹介します.
3.1 エディタ
エディタは,プログラムを作成する上で必要不可欠なツールです.そのため,開発者が効率的に開発を行うことがで
きるように,様々な機能が追加できるようになっています.これらの機能は,プラグイン形式で配布されており,必要
な機能だけを追加できるように工夫されています.
ここでは,開発環境に依らない必要不可欠な機能と,エディタ毎の使用方法について紹介します.
1. オートコンプリート
この機能は,ライブラリに用意された関数やメソッドの名称を簡単に補完できる機能です.特に,長い関数名も
しくはメソッド名のときにタイプ数を減らすことができ,同時にタイプミスも減らすことができるため,開発の
効率を上げることができます.
2. カラーコーディング
この機能は,開発に使用している言語に合わせて色をつけます.色は使用する機能に依存しますが,ほとんどの
場合は好みの色に調整することができます.ソースコードに色がつくことで,予約語や変数などを直感的に判断
することができるため,コードリーディングの時間が大幅に短縮され,開発の効率を上げることができます.
3. オートインデント
この機能は,ソースコードのインデントを整形します.インデント幅は開発者によって嗜好が異なるため,ほと
んどの場合は好みの幅(Tab や空白 2 つ分など)に調整することができます.整形されたソースコードはコード
リーディングを容易にし,開発の効率を上げることができます.
3.1.1 Eclipse
Eclipse には導入時点からオートコンプリート,カラーコーディング,オートインデントの各機能は備わっています.
よって,設定の必要はありません.
第3章
164
開発ツールの紹介
オートコンプリート
オートコンプリート機能は,図 3.1 のようにドット「.」が入力されるか,コントロールキーとスペースキーを同時に
押下することで利用できます.場合によっては複数の候補が表示されるため,適切なメソッドを選択します.候補が多
い場合,続けてメソッド名を入力することで,補完するメソッドを絞り込むことができます.
図 3.1
Eclipse のオートコンプリート機能
カラーコーディング
カラーコーディングも Eclipse では標準の機能です.図 3.2 のように,予約語などの色が初期設定のルールに従って
表示されているため,非常に読みやすくなっています.
図 3.2
カラーコーディング
3.1 エディタ
165
オートインデント
オートインデントも標準で設定されています.開発中は波括弧「{}」をトリガとして,行頭のインデントを追加,消
去します.しかし,他の開発者が作成したファイルを読み込んだ場合,なんらかの原因でインデントが崩れている場合
があります.このような場合にも 1 行毎に直す必要はありません.
図 3.3 Eclipse のオートインデント機能(1/4)
まずはインデントを修正したい箇所を選択します.オートインデント機能が優れているのは,行頭にタブを追加する
といった単純なものではなく,不必要なインデントを行わないところにあります.すなわち,全てを選択してインデン
トを実行した場合には,そのファイル全体で最適なインデントにしてくれます.図 3.4 は Ctrl-a で,全てを選択した
例を示しています.
図 3.4 Eclipse のオートインデント機能(2/4)
第3章
166
開発ツールの紹介
選択した箇所のインデントを行うには,図 3.5 のようにメニューバーから [ソース]-[インデントの訂正] を選択しま
す.また,Ctrl-i でも同様の結果を得ることができます.
図 3.5 Eclipse のオートインデント機能(3/4)
インデントに成功した場合は,図 3.6 のようにコードリーディングが容易になります.
図 3.6 Eclipse のオートインデント機能(4/4)
3.1.2 Vim
Vim はそれ単体でテキストエディタとして動作するため,IDE ではありません.そのため,強いコーディングサポー
トを望む場合には設定ファイルの変更が必要です.今回はデフォルトで使用できる機能を紹介します.
3.1 エディタ
167
オートコンプリート
Vim は初期の導入状態で C 言語のオートコンプリート機能を使用することができます.Eclipes とは異なり,図 3.7
では C 言語で開発する例を示しています.
オートコンプリート機能は,編集モードで Ctrl-n を押下することで利用できます.
図 3.7 Vim のオートコンプリート
カラーコーディング
Vim のカラーコーディング機能では,図 3.8 のように標準で非常に多くの色が使われています.色が多過ぎて読み
にくい場合は,必要に応じてカスタマイズして使用するとよいでしょう.
オートインデント
Vim のオートインデントは空白 8 文字分を行頭に追加するため,長い行を書くのに適していません.狭い幅のイン
デントを行頭に挿入したい場合には,設定ファイルで変更を行う必要があります.
また,再度インデントを設定したい場合には,コマンドモードで==を入力することでカレント行がインデントされ
ます.ファイルの最初から最後までを再インデントするには gg=G を用います.gg は,ファイルの先頭に移動するコ
マンド,G は逆にファイルの最後を示します.オートインデント後は,図 3.9 のようになります.
3.1.3 Emacs
Emacs は,導入時点ではオートコンプリート機能を使うことはできません.利用する場合は,Emacs Lisp などに
よって機能を追加する必要があります.
第3章
168
図 3.8 Vim のカラーコーディング
図 3.9 Vim のオートインデント
開発ツールの紹介
3.1 エディタ
169
カラーコーディング
カラーコーディングは,Emacs 導入時から入っている機能で,C mode によって実現されています.色遣いは Vim
よりは穏やかになっていますが,Vim と同様に設定ファイルによって変更が可能です.Emacs でのカラーコーディン
グは図 3.10 のようになります.
図 3.10 Emacs のカラーコーディング機能
オートインデント
Emacs においてもオートインデント機能は標準で用意されています.しかしながら,インデントされていないファ
イルを開いたときや,インデントが崩れたときなどの場合には再インデントが可能です.Vim と同様に,ファイルの
最初に移動するには Ctrl-x h を用います.その後,M Ctrl-\ (M は Meta の略,Esc キーを割り当てていることが
多い)とすることで,インデントが行われます.オートインデント後は図 3.11 のようになります.
第3章
170
図 3.11 Emacs のオートインデント機能
開発ツールの紹介
3.2 ビルドツール
171
3.2 ビルドツール
3.2.1 Ant
Apache Ant(通称 Ant)は,Apache ソフトウェア財団によって開発およびメンテナンスが行われているビルドツー
ルです.C 言語や C++ のビルドでよく利用される GNU make の Java 版ともいうことができます.また,特徴とし
ては Java のためのビルドツールであるがゆえ,クロスプラットフォームでの動作が可能です.XML でルールを記述
することになっているため,環境を移行してもルールの変更は行わなくてもよい点も利点として挙げられます.また,
Eclipse には Ant プラグインが標準で導入されていますので,簡単に使用することができます.
Ant を利用する場合,事前にコンパイルの中間生成物をどのように処理するのか,具体的なコンパイルオプションを
どのようにするのかなどを詳細に定め,build.xml に記述することが求められます.また,Ant でサポートするタス
クは非常に多いため,必要に応じて取捨選択する必要があります.表 3.1 に Ant のタスクの一部を列挙します.
表 3.1 Ant のタスクの一部
javac
javadoc
java
junit
copy
delete
mkdir
ftp
zip
echo
buildnumber
ant
使用例
『Hello, World!を表示するプログラム (Java)』を例に,Apache Ant と設定ファイルの例を示します.
Ant によってビルドが自動化できるようになると,複雑なファイル構成やコンパイルオプションも指定できるように
なり,開発効率は大幅に向上します.今回は以下の手順で,プログラムの作成とビルドを自動化することで,JAR ファ
イルの生成を行います.
1. Eclipse で Java プロジェクトを作成する
2. プログラムを作成する
3. Ant の設定ファイルを作成する
4. Ant によるビルドを行う
5. オートビルドによって得られた JAR ファイルを実行する
まずは,Eclipse に Java プロジェクトを作成します.左側のパッケージ・エクスプローラーがあることを確認して
下さい.選択されていない場合,タブが隠れているか,表示されていない場合もあります.表示されていない場合は,
図 3.12 のように [ウィンドウ]-[ビューの表示] -[パッケージ・エクスプローラ] と選択し,表示させて下さい.
Java プロジェクトは,図 3.13 のようにパッケージ・エクスプローラのビュー(白い部分)の上を右クリックし,[新
規]-[プロジェクト] を選択してダイアログを立ち上げます.
フィルタでは,図 3.14 のように,Java プロジェクトを選択して下さい.
今回のプロジェクト名は AntTest とします.ここで,プロジェクト名を AntTest 以外にした場合は,以後のテキ
ストも適宜読み替えて下さい.
以上で Java プロジェクトが作成されました.次に,ソースファイルを格納するディレクトリを作成します.図 3.16
のように,先ほど作成した Java プロジェクトの上で右クリックし,[新規]-[ソース・フォルダー] を選択します.
ダイアログが出ますので,フォルダー名を src として作成を終了してください.
第3章
172
図 3.12
パッケージ・エクスプローラビューの表示
図 3.13 プロジェクト作成画面 (1/3)
開発ツールの紹介
3.2 ビルドツール
173
図 3.14 プロジェクト作成画面 (2/3)
ディレクトリの作成に成功していると,図 3.18 のように AntTest プロジェクト直下に src ディレクトリが作成され
ます.
この src ディレクトリにプログラムを作成します.まず,src ディレクトリ上で右クリックし,図 3.19 のように [新
規]-[クラス] を選択します.
図 3.20 のように,ファイル名は Hello,パッケージはデフォルト(空欄)で構いません.また,ファイル名を Hello
以外にすることも可能ですが,以後のテキストは適宜読み替えて下さい.
以下にサンプルプログラムとして,「Hello, World!」を表示するプログラムを用意しました.これをプログラムとし
て作成し,保存して下さい.
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
図 3.21 のようにパッケージ・エクスプローラーに先ほど作成したファイルがありますので,その上で右クリックし,
[実行]-[Java アプリケーション] と選択して下さい.ソースコードの下部にコンソールビューが現れ,予測通りの結果
となることを確認して下さい.
Java で開発を行った場合,プログラムのリリースは,JAR 形式で行います.つまり,コンパイルエラーなどがなく
実行できることが確認できた後は,JAR 形式のファイルを作成することになります.JAR 形式のファイルを作成する
第3章
174
開発ツールの紹介
図 3.15 プロジェクト作成画面 (3/3)
ためには,Eclipse の機能を用いてインタラクティブに出力することができます.しかしながら,環境が変化した場合
や,複数人で作業していた場合には,まったく同じ環境を設定することは難しくなります.そこで,Ant を利用します.
Ant は XML で設定を書く必要があるため,図 3.22 のように AntTest プロジェクト上を右クリックし,[新規]-[ファ
イル] からファイルを追加します.ファイル名は build.xml にして下さい.
Ant の設定ファイルには以下のように記述します.
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="jars" name="AntTest">
<property name="src.dir" value="src" />
<property name="build.dir" value="classes" />
<property name="jar.dir" value="binary" />
<property name="jar.name" value="AntTest" />
<target name="build">
<mkdir dri="${build.dir}" />
<javac srcdir="${src.ir}" destdir="$build.dir}" />
</target>
3.2 ビルドツール
175
図 3.16 ソース・フォルダー作成画面 (1/2)
図 3.17 ソース・フォルダー作成画面 (2/2)
第3章
176
図 3.18
ソース・フォルダー作成後
図 3.19 クラスファイル追加(1/2)
開発ツールの紹介
3.2 ビルドツール
177
図 3.20 クラスファイル追加(2/2)
図 3.21 プログラム実行
第3章
178
開発ツールの紹介
図 3.22 プログラム実行
<target name="jars" depends="build">
<mkdir dir=${jar.dir} />
<jar jarfile="${jar.dir}/${jar.name}" basedir="${build.dir}" />
</target>
</project>
Windows 環境の Eclipse を使用している場合,encoding=Shift JIS でなければ正常に動作しない可能性があり
ます.環境に合わせて,適宜変更を行って下さい.この設定ファイルでは,2 行目にプロジェクト名(name)とプロ
ジェクトの場所(basedir)を記述しています.property では変数として,ソースディレクトリの場所(src.dir)
,中間
生成ファイルの場所(build.dir),JAR ファイルの場所(jar.dir),JAR ファイル名(jar.name)を定義しています.
target では 2 つのビルドを定義しています.ターゲット名 build では,Java コンパイラによるコンパイルを実施して
います.このときに生成されるファイル群の生成場所は,property で定義した build.dir になります.また,ターゲッ
ト名 jars で JAR ファイルの生成を行っていますが,build に依存(depends)しているため,先に build ターゲットが
実行されることになります.その後,jar.dir で定義したディレクトリに jar.name で定義した JAR ファイルが生成さ
れます.
ファイルを作成した後は,設定ファイルを使用して自動でビルドを行います.先ほど作成した build.xml の上で右ク
リックし,図 3.23 のように [実行]-[Ant ビルド] を選択します.
図 3.24 のようなダイアログがでますが,そのまま実行して下さい.
3.2 ビルドツール
179
図 3.23 Ant の実行(1/3)
図 3.24 Ant の実行(2/3)
第3章
180
開発ツールの紹介
Ant 実行後,コンソールビューに結果が表示されます.図 3.25 のように BUILD SUCCESSFUL と出た場合は
成功です.成功しなかった場合は,設定を適宜見直して下さい.
図 3.25 Ant の実行(3/3)
3.2 ビルドツール
181
3.2.2 make
C 言語や C++ などの言語でのビルドツール make はプログラムのビルドツールという点では Ant と変わりません.
しかし,その記述方法は,Ant が XML で行われるのに対して,make は独自のルールに従って行います.make は
Linux のシェルを介して行われることが前提となっているため,開発環境(開発言語がコンパイルできる環境)さえあ
れば導入が可能です.また,make の歴史は古く,多くの機能が含まれ,十分にテストされたツールであることも利点
として挙げられます.
使用例
『10 個のフィボナッチ数列を表示するプログラム(C 言語)』を例に,GNU make と Makefile の例を示します.
複数人で開発するにはいくつかのソースコードが作成されるのが一般的です.そこで今回は,フィボナッチ数列を計
算するための関数とそれを表示するための関数を別々のソースファイルとして作成します.表示するためのソースファ
イル(print.c)には C 言語で最初に実行される関数である main 関数を含み,フィボナッチ数列を計算するソースファ
イル(fibonacci.c)には関数を 1 つだけ含むものとしました.また,それらのソースファイルに共通するヘッダファイ
ルをカスタムヘッダ(myheader.h)としてまとめることにします.
まず,myheader.h を作成します.ソースコードの詳しい説明は省略しますが,このようにヘッダファイルを統一す
ることで,ヘッダファイルの多重読み込みや宣言の不足などを防ぐことができます.
/*
* myheader.h
*/
#include <stdio.h>
#include <stdlib.h>
// myheader.h の多重読み込みを防止
#ifndef _MYHEADER_
#define _MYHEADER_
extern int fibonacci(int);
#endif
フィボナッチ数列を計算する関数(fibonacci.c)を作成します.先ほど作成したヘッダファイル(myheader.h)に
は,関数内で必要とされるヘッダファイルが全て含まれています.そのため,myheader.h を読み込むだけで良いよう
になっています.必要なヘッダファイルが生じたときは,myheader.h に追加するだけでこのソースファイルにも適用
されるため,非常に便利です.
/*
* fibonacci.c
*/
#include "myheader.h"
int fibonacci(int n) {
第3章
182
開発ツールの紹介
if (n == 1)
return 1;
else {
if (n == 2)
return 2;
else
return fibonacci (n-1) + fibonacci (n-2);
}//end-of-fibonacci(n!=1)
}//end-of-function
最後に表示のための関数(print.c)を作成します.ここには main 関数も含まれています.このように,必要最小限
の機能毎に分割して関数を作成することで,メンテナンス性も向上します.ここでも,myheader.h を読み込むだけで,
すべてのライブラリ関数および fibonacci 関数が読み込まれます.
/*
* print.c
*/
#include "myheader.h"
void print(int n) {
int i;
for (i=1; i<=n; i++)
fprintf (stdout, "%d ", fibonacci(i));
fprintf(stdout, "\n");
}
int main (void) {
print(10); //10 個のフィボナッチ数列を表示
return 0;
}
以上のファイルを同一のディレクトリに配置して下さい.これらをコンパイルして実際の動作を確認してみます.
$ gcc fibonacci.c print.c -o fibonacci -Wall
$ ./fibonacci
1 1 2 3 5 8 13 21 34 55 89
gcc の o オプションはコンパイル後のファイル名を指定します.Wall オプションは致命的なエラーだけでなく警告
文も表示します.環境によってはエラーや警告が表示されることもありますので,適宜修正してください.
フィボナッチ数列を出力するために 2 つのソースコードを使用しましたが,大規模な開発ではさらに多数のソース
コードを使用します.豊富に用意されている gcc のオプションを利用する場合などは,毎回手作業でコンパイルしてい
ては開発の効率は上がりません.これを解決するのが Makefile です.以下のリストを見て下さい.
3.2 ビルドツール
183
# Makefile
# 最初はここが実行される
all: print.o fibonacci.o
gcc -o fibonacci -Wall fibonacci.o print.o
fibonacci.o: fibonacci.c
gcc -c fibonacci.c -Wall
print.o: print.c
gcc -c print.c -Wall
# ヘッダファイルを編集したときにもコンパイルを
# 実行させるため,依存ファイルとしている
fibonacci.o: myheader.h
print.o: myheader.h
ファイル名を Makefile としなければ動作しません.注意して下さい.
コメントアウトには番号記号「#」を使用します.Makefile はまず最初に all 句を解釈します.コロン「:」の右式は
依存ファイルを記述します.リストでは,all を実行するために print.o と fibonacci.o を必要としています.そして,
この依存ファイルが存在する場合に実行されるコマンドを次の行から記述します.このとき,実行するためのコマンド
は空白行を入れず,行頭はタブ (Tab) が入っていなければなりません.また,依存ファイルが存在しない場合にはエ
ラーとなりますが,Makefile 内に依存ファイルの生成ルールが存在した場合には,先に依存ファイルの生成を実行し
ます.今回の Makefile では,fibonacci.c と print.c から fibonacci.o と print.o がそれぞれ生成されています.この生
成ルールでは,ソースファイルとオブジェクトファイルとタイムスタンプを比較し,新しく編集されたソースファイル
についてのみオブジェクトファイルの生成を行います.最後の 2 行では,オリジナルのヘッダファイルをオブジェクト
ファイル生成の依存ファイルとしています.本来はコンパイルの段階で呼び出されるため,書かなくても正常に動作し
ます.しかしながら,依存ファイルとして Makefile 内に記述することで,ヘッダファイルの変更もキャッチしてコン
パイルしてくれるようになります.
この Makefile を使用するには,Makefile が含まれたカレントディレクトリで以下のコマンドを入力するだけです.
$ make
または,以下のようにコマンドを入力することでも同じ結果が得られます.
$ make all
このように,Makfile を駆使することで,IDE を利用しない場合にも効率的に開発を行うことが可能になります.今
回は Makefile の使い方を簡単に触れましたが,本来 Makefile には膨大な書式とオプションが用意されているため,
様々な環境にも柔軟に適応することが可能です.
第4章
ソフトウェア品質
ソフトウェア品質は利用者が最も使いやすいと感じた場合を最良の品質としている場合が多いため,主観的なものと
考えられがちです.今回は,ソフトウェアの開発目的に左右される利用者側からのソフトウェア品質の測定ではなく,
客観的な評価が可能な開発者側からの測定によるソフトウェア品質の測定について紹介します.
4.1 バグ収束曲線
開発者側から測定できる評価指標として,バグの件数が挙げられます.当然,バグの件数が少ないほど,品質の良い
ソフトウェアということになります.バグを少なくするためには,バグの内容と件数を正確に見積もるためのソフト
ウェアテストが必要不可欠となります.
品質の高いソフトウェア開発のために,発生したバグの件数と改修済みバグの件数を把握するために用いられるグラ
フとして「バグ収束曲線」がよく知られています.図 4.1 に示したバグ収束曲線の例にある通り,x 軸にソフトウェア
テストを行った(もしくはバグの発生した)日付を,y 軸に発生したバグの累計(破線)と改修したバグの累計(実線)
を同時に表すのが一般的です.
図 4.1 バグ収束曲線の例
4.2 ソフトウェアテスト
185
よく知られたバグ収束曲線ですが,『バグはテスト開始時にこそ指数的な増加があるものの,テストが進むに従って
収束する』との経験則に基づいています.ただし,このグラフを用いても,バグの発生件数の収束がテストケースの減
少(終了)によるものなのか,バグの発生自体の減少なのかの判別がつかないという欠点があります.そのため,バグ
を判定する複数の指標の 1 つとして用いられることが一般的です.また,バグ収束曲線は信頼度成長曲線とも呼ばれ,
ソフトウェア開発終了後のドキュメンテーションの 1 つとして納品物に含める場合もあります.
4.2 ソフトウェアテスト
バグを修正するためにはバグを検出する必要があります.この作業をソフトウェアテストといいます.ソフトウェ
アテストでは,網羅性と正確さが要求されます.そのため,専用のツールを使用することが一般的です.その中でも,
xUnit はソフトウェアツールとして非常によく知られています.
4.2.1 xUnit
xUnit は様々な環境や言語のためのテスティングフレームワークです.xUnit 単体では使用できず,テストツールの
集合体となっています.
よく知られている xUnit の一部を表 4.1 に示します..
表 4.1
よく知られた xUnit の一部
ツール名
言語名
CUnit
C
CppUnit
C++
HUnit
Haskell
JsUnit
JavaScript
JUnit
Java
OUnit
Objective Caml
PerlUnit
Perl
PHPUnit
PHP
PyUnit
Python
RubyUnit
Ruby
SUnit
Smalltalk
tclUnit
Tcl/Tk
また,開発言語ではなく,表 4.2 に示すような,プロトコルなどを介したテストを提供するツールもあります.
表 4.2
開発言語に依らないテストツール
ツール名
備考
HttpUnit
擬似的に HTTP を用いた通信を行うテストに利用される
HtmlUnit
ウェブブラウザをエミュレートして行うテストに利用される
表 4.1, 4.2 の通り,xUnit には非常に多くのツールが存在します.そのため,ツール毎に提供する機能も少しずつ変
わってきますが,xUnit では概ね Test Fixtures, Test Suites, Test Execution, Assertions の機能を提供しています.
第4章
186
ソフトウェア品質
Test Fixtures
Test Fixtures は,テストを成功させるための状態や条件のことです.テストの際は,テストに適した状態を設定し,
テスト終了後には,元の状態に復元します.ここで,テストに適した状態とはプログラムが既存のデータを前提として
いる場合,ダミーデータを作成するなどして,実環境と近い環境を定義することです.
Test Suites
同じ条件(Test Fixtures)で行うテストの集合です.
Test Execution
テストにはテスト用の環境を用意します(setup).テスト後はリリースに不適切なダミーデータを削除するなど,元
の状態に戻す(teardown)ことで完了します.
Assertions
テスト対象の動作を確認するための関数のことです.Assertions が失敗した場合は,例外(Exception)となりテス
トを中断します.
4.2.2 JUnit を用いたソフトウェアテストの方法
図 3.13∼ 図 3.20 を参考にし,新しくプロジェクト,ソースディレクトリ,クラスを作成してください.新しく作成
するプロジェクト名,ソースディレクトリ名,クラス名は以下を用いて下さい.
プロジェクト名
JUnitTest
ソースディレクトリ
src
クラス名 Leap
Leap クラスには以下のリストのコードを記述してください.これは『閏年を判定する』メソッドと動作確認用のメ
インメソッドです.
public class Leap {
public boolean isLeap(int year) {
return year%4==0 && year%100!=0 || year%400!=0;
}
public static void main(String[] args) {
int year = 1000;
Leap leap = new Leap();
System.out.print(year + "年は閏年");
if( leap.isLeap(year) ) System.out.println("です");
else System.out.println("ではありません");
}
4.2 ソフトウェアテスト
187
}
プロジェクト,ソースディレクトリ,クラスを作成し終えると,図 4.2 のようになります.
図 4.2
閏年判定メソッド作成後の画面イメージ
次に,テストの実行環境を用意します.図 4.3 のように Java プロジェクトの上で右クリックし,[新規]-[JUnit テス
ト・ケース] を選択して下さい.
図 4.4 のように,クラス名を LeapTest にして作成を終了して下さい.
しかし,このままでは JUnit のライブラリにリンクされていないため,図 4.5 のようなエラーが表示されます.
これを解決するには,図 4.6 のように import 文の左にあるエラーマークをクリックし,JUnit 3.8.1 をビルド・パ
スに追加を選択してください.ただし,環境によっては JUnit のバージョンが異なっている場合がありますので,適宜
読み替えるようにしてください.
Leap.isLeap メソッドテスト用に,TestLeap.testisLeap メソッドを追加してください.
import junit.framework.TestCase;
public class TestLeap extends TestCase {
public void testisLeap() {
Leap leap = new Leap();
assertEquals(true , leap.isLeap(1996));
assertEquals(false, leap.isLeap(1997));
assertEquals(false, leap.isLeap(1998));
assertEquals(false, leap.isLeap(1999));
assertEquals(true, leap.isLeap(2000));
第4章
188
ソフトウェア品質
図 4.3 テストケース作成(1/4)
}
}
TestLeap.testisLeap メソッド追加後は図 4.7 のようになります.
図 4.8 のように JUnit テスト・ケースを実行して下さい.
実行した結果,図 4.9 のような結果となりました.これは,残念ながらテストで異常が発生したことを示す結果で
す.発生した異常をダブルクリックすることで,発生条件の式に移動できます.
ソースコードにバグがあった場合は修正を行います.今回は,Leap.isLeap メソッドにバグがありますので,該当箇
所を以下のように修正して下さい.
return year%==0 && year%100!=0 || year%400==0;
修正前は以下のようになっていました.3 つめの条件式の部分が異なっていることに注意して下さい.
return year%==0 && year%100!=0 || year%400!=0;
再度,テスト・ケースを実行してみます.図 4.10 のように,バーが青くなった場合は成功です.
今回はテスト・ケースで assertEquals メソッドしか使用していませんが,他にも表 4.3 のように評価用メソッドが
用意されていますので,状況に応じて使用して下さい.また,JUnit によるテスト・ケースの作成方法にも様々な方法
4.2 ソフトウェアテスト
189
図 4.4 テストケース作成(2/4)
図 4.5 テストケース作成(3/4)
がありますので,単一の方法だけではなく状況に応じて使用して下さい.
表 4.3 テスト・ケースで利用できるメソッド
junit.framework.Assert.assertFalse
junit.framework.Assert.assertTrue
junit.framework.Assert.assertSame
junit.framework.Assert.assertNotSame
junit.framework.Assert.assertNull
junit.framework.Assert.assertNotNull
junit.framework.Assert.fail
以上が,JUnit を用いたテストの例です.テスティングの注意としてテストが失敗した場合に,それがバグによるも
のなのかテストの条件や仕様などの不備によるものなのか,慎重に判断する必要があります.そのため,テストは網羅
的かつ正確に行うとともに,テスト・ケース自体のチェックも忘れないようにします.
第4章
190
図 4.6 テストケース作成(4/4)
図 4.7 TestLeap.testisLeap 追加
ソフトウェア品質
4.2 ソフトウェアテスト
191
図 4.8 JUnit テスト・ケースの実行
図 4.9 JUnit テスト・ケース実行結果(失敗)
第4章
192
図 4.10 JUnit テスト・ケース実行結果(成功)
ソフトウェア品質
第 7 回 演習課題
目標
JUnit によるテストケースを作成します.
まず,プログラムを作成し,それらのプログラムに対するテストケースを作成・実行して下さい.
課題 1 JUnit によるテストケースの実行
1–1
プログラムを作成します.次のプロジェクト,ソースディレクトリ,クラスを作成して下さい.作成方法は,4.2.2 節
を参照して下さい.
プロジェクト名
JUnitTest
ソースディレクトリ
src
クラス名 QuadricFormula
クラスは『2 次方程式の解を求める』プログラムを作成して下さい.但し,虚数解はこれを除外して構いません.ま
た,次のプログラムを利用しても構いません.
public class QuadricFormula {
private double answer1;
private double answer2;
public QuadricFormula(int a, int b, int c) {
this.Calc(a,b,c);
}
private void Calc(int a, int b, int c) {
answer1 = ((-1) * b + Math.sqrt(b*b - 4*a*c)) / 2*a;
answer2 = ((-1) * b - Math.sqrt(b*b + 4*a*c)) / 2*a;
}
public void reCalc(int a, int b, int c) {
this.Calc(a,b,c);
}
public double getAnswer1() {
return this.answer1;
}
第4章
194
第 7 回 演習課題
public double getAnswer2() {
return this.answer2;
}
}
1–2
前述のプログラムに対してテストケースを作成し,テストを実施して下さい.もしもテストで異常が発見された場合
は,テストをパスするまでプログラムの修正を行って下さい.
テスト・ケースのプログラム例を次に示しますので,これを参考に様々なテストを追加して下さい.
import junit.framework.TestCase;
public class testQuadricFormula extends TestCase {
public void testAnswer() {
QuadricFormula qf = new QuadricFormula(1, 0, -4);
assertEquals((double)2, qf.getAnswer1());
}
}
虚数解は存在しないため,以下のように 2 次方程式を考え期待値として下さい.
(x − 1)(x − 2) = 0
x2 − 3x + 2 = 0
x = 1, 2
また,この期待値を利用して以下のようにコードを追加します.これ以外にもテストコードを最低 5 つは追加してテ
ストして下さい.
qf.reCalc(1, -3, 2);
assertEquals((double)2, qf.getAnswer1());
assertEquals((double)1, qf.getAnswer2());
参考文献
[1] Open Source Group Japan, http://www.opensource.jp/osd/osd-japanese.html
[2] New BSD License, NetBSD, http://www.netbsd.org/about/redistribution.html
[3] General Public License 2.0, GNU, http://www.gnu.org/licenses/gpl-2.0.html
[4] General Public License 3.0, GNU, http://www.gnu.org/licenses/gpl-3.0.html
[5] Apache License 2.0, Apache Software Foundation, http://www.apache.org/licenses/
[6] MIT License, XFree86, http://www.xfree86.org/current/LICENSE4.html
第8回
ドキュメント作成支援
開発フェーズごとのソフトウェアドキュメンテーションの実際について解説します.また,
オープンソースのドキュメント作成支援ツール,オンラインマニュアルの位置付けと,その実
装例である Doxygen,Javadoc,nroff などについても解説します.演習では,実際に Javadoc
により API ドキュメントを作成し,Web 上に公開することにより,その利用方法について学び
ます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
ドキュメンテーションとは
ソフトウェア開発は,その規模や目的に応じて,ウォーターフォール型,スパイラル型,アジャイル型などのプロセ
スにより行われます.そして,そのいずれのプロセスの場合でも,1 つ 1 つの過程を経るごとに何らかのドキュメント
が作成されます.
ドキュメントを作成する目的のひとつは,顧客である利用者側と開発者側で開発するソフトウェアのイメージを共有
し,開発における手戻りを少なくすることです.また,手戻りが発生してしまった場合には,利用者側か開発者側のど
ちらかがコストを負担する必要があるため,その責任範囲を明確にするためにドキュメントが用いられる場合もあり
ます.
1.1 ドキュメントの種類
ソフトウェア開発では,その過程において様々な種類のドキュメントが作成されます.以下にその例を示します.
顧客が業務効率の向上などの目的に応じて,システムに求める機能や性能などの要件を定義するドキュメントが要件
定義書です.この要件定義書から,動作の遷移やウィンドウの表示内容など,具体的なシステムの動作について提案す
るために作成されるのがシステム提案書です.このシステム提案書に基づいて開発を行いますが,その進め方について
は開発計画書にまとめます.
開発計画書に基づいて開発を行う過程で,外部設計書と内部設計書という 2 種類のドキュメントを作成します.外部
設計書で,システムのフロントエンドの部分,すなわちソフトウェアとユーザが直接関わる部分や他システムとのイン
ターフェース部分について詳細にまとめます.また,ユーザからは見えない内部処理をまとめたものが内部設計書で
す.ここにはユーザから入力されたデータをデータベースに格納したり抽出したりといった,性能に関わる部分が記述
されます.これらの設計書に基づいてコーディングを行っていくことになります.
プロジェクトの終了時には,プロジェクト完了報告書を作成します.ここにはプロジェクトの完了報告のほか,プロ
ジェクトを遂行する上で発生した問題や得られた知見など,今後のプロジェクトに役立つ情報を記載します.
1.2 ソフトウェアドキュメンテーション
ソフトウェアは目に見えるものではありませんので,顧客と開発者がそのイメージを共有することが非常に重要です
が,ソフトウェアドキュメントの目的はそれだけではありません.開発成果物のイメージや設計仕様や実装方法など,
実装を進めるために必要な情報を開発者間で共有することも非常に重要です.
そのようなドキュメントの一部においては,ソフトウェアを実装する前までに作成される設計書などとは異なり,ソ
フトウェア開発中もしくは開発後にソフトウェアのソースコードについて,その挙動や利用方法などを記述します.そ
のため,ソースコードには,その挙動や利用方法などの説明を埋め込んでおき,全体としてのソフトウェアドキュメ
ントの生成は自動で行うことが一般的です.このようにドキュメントとソースコードを同一の場所に書いた場合には,
ソースコードとドキュメントが 2 つにわかれていた場合と比較して,一方を修正した後のもう一方の修正が非常に容易
1.3 ソフトウェアドキュメンテーションの重要性
199
になり,ソースコードとドキュメントがかい離しにくくなるというメリットがあります.
1.3 ソフトウェアドキュメンテーションの重要性
ここまでは,ソフトウェア開発の過程で作成させるドキュメントの役割として,顧客と開発者がイメージを共有する
という目的と開発者間での情報共有という目的があることを示しました.ここでは,特に後者のドキュメンテーション
の重要性について見ていきます.
大規模な開発プロジェクトでは,例えば,図 1.1 のように,提案・設計と実装がそれぞれ別の組織に属するチームに
よって行われるような場合が少なくありません.このような場合は,チーム間でイメージを明確に共有するために,ド
キュメントを詳細に示す必要があります.
図 1.1
企業間で役割分担が行われている例
同様に,1 人の開発者が実装できる量は限られているので,機能ごとに開発者が違うことも珍しくありません.図 1.2
のように,開発フェーズごとに開発人数が異なる場合もあります.このように,ソフトウェアの実装段階においては開
発の人数が常に流動的であることがよくあります.これでは,開発者が追加・変更されるたびに仕様書を見ながらソー
スコードを追うことになり,引継ぎの作業が大変です.
そこで,実装中にその内容についてドキュメントを残していくことで,引き継ぎの作業やバグの改修時に他の開発者
が書いたソースコードの修正が容易になります.
このように,実装された内容とその挙動についてのドキュメントを残すことは,規模の大きいソフトウェア開発にな
るほど重要になります.そこで,次からは実際に利用されているソフトウェアドキュメントツールとその利用方法につ
いて紹介します.なお,ソフトウェアドキュメントツールはその目的や開発言語などにより,様々なのもがあります.
使用しているツールの機能等が不十分な場合には,必要に応じて探して下さい.
第1章
200
図 1.2
開発フェーズで開発者が追加・変更になる例
ドキュメンテーションとは
第2章
ソフトウェアドキュメンテーション
前節でその重要性について説明したように,ソフトウェアドキュメントは様々な開発者が参加するプロジェクトなど
のように人材が流動的な場合にも,既に終了している実装をすぐに確認することができるため,ソフトウェア開発の効
率を大幅に向上させます.
このようなソフトウェアドキュメントを作成する手段および方法をソフトウェアドキュメンテーションと呼びます.
ソフトウェアドキュメンテーションは,ソースコードから自動的にその関係性をグラフ化するだけでなく,ソフトウェ
アドキュメンテーションの自動生成ツールが提供するタグを記述することで,スタイルが統一された独自の内容を出力
することができます.ここでは,ソースコードから自動生成する Doxygen と Javadoc,そしてユーザマニュアルの作
成ツールとして昔から使われていた nroff について紹介します.
2.1 Doxygen
Doxygen は既に完成されたソースコードを継承関係や依存関係を考慮した上で解析し,わかり易く表示するソフ
トウェアです.Doxygen は C/C++ 言語や Java だけでなく,幅広い言語の解析が可能であり,出力形式も HTML,
リッチテキスト,TEX などがサポートされています.特に,ソースコードに専用のタグを埋め込むことなく解析を行
うため,手軽に導入できるという特徴があります.
また,後述する Javadoc と同様に,専用のタグをコメントとして記述することで Javadoc のようなソフトウェアド
キュメントの自動生成が可能になります.
2.1.1 インストール
Doxygen は Debian コミュニティでパッケージングされているため,インストールは容易です.
$ sudo apt-get install doxygen
TEX 形式で出力する場合は,実際にタイプセット*1 するには他の環境が必要となります.HTML 形式で出力する場
合は,Apache などの Web サーバソフトウェアを使用して公開するとよいでしょう.
2.1.2 Doxyfile(Doxygen の設定ファイル)
Doxygen を利用するには,その設定を Doxyfile に記述しなければなりません.膨大な設定項目が存在しますので,
必要に応じて設定項目を追加して下さい.Doxyfile は全て自分で記述することもできますが,解析を行いたいディレク
トリ内で以下のコマンドを発行することで自動生成することもできます.
*1
プログラミング言語をオブジェクトコードに変換することをコンパイルと呼びますが,TEX に限ってはコンパイルではなくタイプセットと
呼ばれます.これは TEX がプラグラムを書くことを目的としたものではなく(実行時間を無視するのであればプログラム可能であることが
証明されています),文書作成のためのソフトウェアであることに由来します.
第2章
202
ソフトウェアドキュメンテーション
$ ./doxygen -g
自動生成された Doxyfile には,PROJECT NAME, PROJECT NUMBER と OUTPUT DIRECTORY などが何
も記述されていませんので,ここだけは記述しておきます.その他は,変更しなくても構いませんが,出力形式などを
変更したい場合には変更する必要があります.
PROJECT_NAME = TestProject
PROJECT_NUMBER = v1.0
OUTPUT_DIRECTORY = ./doc
その他,便利な設定項目を表 2.1 に紹介します.
表 2.1 Doxyfile 設定項目
設定項目
説明
CREATE SUBDIRS
YES で,ソースコードのディレクトリと同じ階層構造を維持する
OUTPUT LANGUAGE
出力の言語を設定する
BUILTIN STL SUPORT
YES で,STL クラスを入力してインクルードしない
FILE PATTERNS
解析するファイルの種類(拡張子)を指定する
RECURSIVE
対象とするディレクトリを再帰的に解析したい場合は YES を指定
する
ALPHABETICAL INDEX
YES で,アルファベット順のインデックスを生成
HAVE DOT
YES で,Graphviz を用いたグラフを生成
CALL GRAPH
HAVE DOT と CALL GRAPH が YES で,呼び出し依存関係図
を生成
SOURCE BROWSER
YES で,ソースファイルのリストを生成
OPTIMIZE OUTPUT FOR C
C(他に JAVA, FORTRAN など)に,より適合した出力を生成
(すべてのソースが同一言語で作成されているときのみ)
2.1.3 Doxygen によるドキュメント生成例
Doxygen を用いてドキュメントを生成します.ドキュメントの生成対象としたのは,Linux ではおなじみの ls コマ
ンドです.ただし,Linux に同梱されている ls コマンドは GNU の拡張が多分に入っているため,あまり拡張が行わ
れていない FreeBSD 版を用います.
まずはソースコードをダウンロードします.ここでは CVS(第 9 回参照)を利用します.
$ sudo apt-get install cvs
$ CVSROOT=:pserver:[email protected]:/home/ncvs
$ export CVSROOT
$ cvs login
cvs login 後にはパスワードが求められますが,匿名ユーザで接続しているため適当な文字列を入力して下さい.
その後,ダウンロードが可能になります.早速,CVS を利用して ls コマンドのソースコードをダウンロードします.
2.1 Doxygen
203
$ cvs co ls
U ls/Makefile
U ls/cmp.c
U ls/extern.h
U ls/ls.1
U ls/ls.c
U ls/ls.h
U ls/print.c
U ls/util.c
FreeBSD 版の ls コマンドには Makefile なども含めて 8 つのソースコードが含まれています.このソースコード
を解析するために Doxyfile を設定します.設定項目は設定ファイルを自動生成した後,最小限の項目のみ設定を行い
ます.
PROJECT_NAME= ‘ls‘ command on FreeBSD
PROJECT_NUMBER = v7.2
OUTPUT_DIRECTORY = ./doc
クラスの継承関係などをグラフ化するのであれば,Doxyfile 設定項目の HAVE DOT を YES にし,Graphviz パッ
ケージが導入されていなければなりません.もしインストールされていない場合には,以下のコマンドでインストール
してください.
$ sudo apt-get install graphviz
図 2.1 は,実際に生成されたドキュメントの一部です.予約語には色がつくなど,コードリーディングを容易にする
機能が多く含まれています.
図 2.1
Doxygen で生成されるソースコードビュー
図 2.2 は,Graphviz を用いて継承関係を視覚化した例です.このように継承関係が矢印で表されるため,継承のト
レースなどは非常に容易となっています.
このように,ソースコードの自動解釈によるドキュメンテーションは,コードリーディングに有用です.既に完成さ
れたソースコードに適用できるということは,ドキュメントの少ないプロジェクトへの途中参画や,過去のソースコー
ドのメンテナンスなどにも役立ちます.
204
第2章
図 2.2 Doxygen で生成される継承グラフ
ソフトウェアドキュメンテーション
2.2 Javadoc
205
2.2 Javadoc
Javadoc は,Java で作成したソースコードの解説をソースコード内に記し,後にドキュメントを自動生成します.
そのため,ソースコードとその説明はセットで記述することが可能であり,説明のためのドキュメントを別に用意する
必要がないため,プログラムと説明の変更を容易に行うことができます.
2.2.1 Javadoc の書式
Javadoc は,ソースコード内ではコメントとして扱われます.Java では 2 種類のコメントアウトの方法が許容され
ています.行頭に「 // 」を置くことにより,1 行だけをコメントとして扱うことができます.それに対して,
「 /* 」で
始める方法は,「 */ 」で終了しなければならないため,複数行にわたるコメントを記述する場合に用いられます.
Javadoc は後者のコメントの方法を用いますが,開始タグは「 /** 」となっているため,注意が必要です.終了タグ
の「 */ 」は変わりません.これをメソッドの直前に置くことでメソッドの説明として認識するため,メソッド名など
をコメント内に直接記述する必要はありません.
メソッドの説明
メソッドの直前においた Javadoc 用のコメント内には専用のタグによる引数や返り値の他にメソッドの説明を入れ
ることもできます.この説明は Javadoc にも反映されるため,記述することが望ましいでしょう.
class Test {
/**
* メソッドの説明
* @param a 引数の説明
* @return 返り値の説明
*/
public Test(int a) {
return a*2;
}
}
@author , @version
@author と @version タグはプログラムの基本情報の記述に使用されます. @author タグにはプログラムの作成者
など,そのプログラムの担当を記述します.また, @version タグの更新は,ソフトウェア全体で管理する方法のほか,
ソースファイル単体で管理する場合にはバージョン管理システム(第 9 回参照)を利用して管理することもできます.
/**
* @author Mirai Taro
* @version 3.1.4
*/
class Test {
第2章
206
ソフトウェアドキュメンテーション
public Test() {
}
}
@param
@param タグはメソッドの引数の説明に使用されます.タグの後ろはスペースまたはタブ(TAB)を挿入し,引数
名,引数の説明を記述します.通例,引数が複数ある場合には,第 1 引数から記述します.
class Test {
/**
*
* @param str 挨拶する先
* @param obj 挨拶した人
*/
public void printHello(String str, String obj) {
System.out.println("Hello, "+str+"! -from"+obj);
}
}
@return
@return タグはメソッドの戻り値の説明に使用されます.1 つのメソッドにつき戻り値は必ず 1 つに決まっており,
タグの直後に説明を記述します.
class Test {
/**
*
* @param num 偶数か奇数かの判断を行う対象の数値
* @return 奇数の場合は true,偶数の場合は false を返す
*/
private static boolean isOdd(int num) {
return (a%2==0) ? false:true;
}
}
@throws , @exception
@throws タグはメソッドの例外の説明に使用されます.場合によっては複数の例外を記述する必要があります.な
お, @throws タグと @exception タグは,タグ名こそ異なるもののまったく同一の機能をもちます.
import java.io.*;
2.2 Javadoc
207
class Test {
/**
*
* @throws FileNotFoundException ファイルが存在しない場合にスローされる
*/
public void fileReader() throw FileNotFoundException {
FileInputStream fs = new FileInputStream("test.csv");
}
}
2.2.2 コンソールからの Javadoc 生成
Java Developer Kit(JDK) をインストールしている場合,同時に Javadoc ドキュメンテーション生成のプログラ
ムも同梱されています.対象のファイルを指定することにより生成されます.
$ javadoc Test.java
また,複数のファイルを指定することもできます.以下の場合,Test で始まる .java ソースファイルと,Hoge.java
が javadoc ドキュメントとして生成されます.
$ javadoc Test*.java Hoge.java
2.2.3 Eclipse からの Javadoc 生成
Javadoc によるドキュメントは Eclipse を用いて出力することもできます.まずは,Javadoc 用のタグを埋め込んだ
ソースコードを用意します.今回は閏年判定用のクラスを作成し,利用することにします.
また,Javadoc ドキュメントは HTML で出力されるため,コメント内に HTML のタグを埋め込むことで文字の装
飾などを行うことができます.
/**
*
* @author Mirai Taro
* @version 1.0
*/
public class JavadocTest {
/**
*
* @param year 閏年かどうかを判定する対象年
* @return <b>true</b> 閏年である<br />
*
<b>false</b> 閏年ではない
*/
public boolean isLeap(int year) {
第2章
208
ソフトウェアドキュメンテーション
return year%4==0 && year%100!=0 || year%400==0;
}
}
その後,図 2.3 のように [プロジェクト]-[Javadoc の生成] を選択します.
図 2.3 Javadoc ドキュメントの生成(1/6)
先ほど作成したソースコードを選択します.ソースコードごとや,パッケージごとなどを選択することができます.
図 2.4 のように次へ進んで下さい.
ここでは特に設定の必要はありません.状況に応じて文書タイトルを変更することもできます.図 2.5 のように次へ
進んで下さい.
今回,標準でインストールされる Eclipse では,「JRE ソース互換性」が 1.5 では動作しませんので,図 2.6 のよう
に,「JRE ソース互換性」を 1.4 に変更して下さい.その後,ダイアログを終了すると,図 2.7 のように Javadoc ド
キュメントが生成されます.
設定を変更していない場合には,図 2.8 のように, JavadocTest/doc に Javadoc ドキュメントが生成されます.
Eclipse の初期起動時に Workspace の場所を変更していない場合,Workspace は /home/(user)/Workspace に作
成されています.更に,Workspace 直下にプロジェクト名でディレクトリが作成されており,今回の Javadoc はその
下の doc ディレクトリに格納されています.
早速,ブラウザで確認して下さい.図 2.9 のように表示されたら成功です.
このように,Eclipse ではソースコードとコメントを同時にメンテナンスすることが容易です.Java の開発元である
Sun Microsystems が公開する API 情報もこれによって作成されています.
2.2 Javadoc
209
図 2.4 Javadoc ドキュメントの生成(2/6)
図 2.5 Javadoc ドキュメントの生成(3/6)
210
第2章
図 2.6 Javadoc ドキュメントの生成(4/6)
図 2.7 Javadoc ドキュメントの生成(5/6)
ソフトウェアドキュメンテーション
2.2 Javadoc
211
図 2.8 Javadoc ドキュメントの生成(6/6)
図 2.9 Javadoc ドキュメントの表示
第2章
212
ソフトウェアドキュメンテーション
2.3 nroff
nroff,または new roff(以下 nroff)は,Joseph Ossanna によって開発された,roff で作られた文書を表示する書式
です.nroff は昔から UNIX の man コマンドで使用されており,非常に浸透したマニュアルドキュメント作成(表示)
プログラムであるといえます.また,man コマンドは roff によって整形した文書を more, less などに代表されるペー
ジャプログラムによって画面に出力します.
roff で使用される書式を表 2.2 に示します.
表 2.2 roff の書式
コマンド
説明
.B
太字 (Bold)
.br
改行
.I
斜体 (Italic)
.PP
段落
.SH
段落名
.TH
コマンド名などの説明,man ページの先頭に記述
.TP
字下げを行う段落
\-
ハイフンの表示
.\”
コメント
この書式を用いて架空の fun コマンドマニュアルを作成してみます.以下のリストの内容は,表 2.2 を参考にして
ください.
.\" This is a test page of custom command
.TH FUN "1" "July 1985"
.SH NAME
fun \- make you happy
.SH SYNOPSIS
.LP
\fBfun\fP \fB[\fP-ap\fP\fB]
.SH DESCRIPTION
.PP
remove ALL files, so make you happy at least temporarily
.TP
\fB\-a\fR, \fB\-\-all\fR
remove all files, wrap you up in greater happiness
.TP
\fB\-p\fR, \fB\-\-part\fR
remove a part of files, make you happy a little
.SH AUTHOR
2.3 nroff
213
Written by GOD
.SH COPYRIGHT
License GPLv3+: GNU GPL version 3 or later
このマニュアルは,作成したディレクトリで以下のコマンドによって参照できます.
$ man -M . fun
図 2.10 は作成したマニュアルを実行した結果です.このようにコマンドを作成,もしくは改変した場合には,必要
に応じてマニュアルを作成,または修正することも可能です.
図 2.10 roff 書式によって作成したマニュアル
第 8 回 演習課題
目標
Javadoc によるドキュメントの作成・公開を行います.
プログラムにコメントを挿入し,ドキュメントを自動生成して下さい.また,生成されたドキュメントを外部か
ら閲覧できるようにして下さい.
課題 1 Javadoc によるドキュメントの生成と公開
1–1
次のプロジェクト,ソースディレクトリ,クラスを作成して下さい.
プロジェクト名
JUnitTest
ソースディレクトリ
src
クラス名 QuadricFormula
『2 次方程式の解を求める』プログラムを利用して下さい.
public class QuadricFormula {
private double answer1;
private double answer2;
public QuadricFormula(int a, int b, int c) {
this.Calc(a,b,c);
}
private void Calc(int a, int b, int c) {
answer1 = ((-1) * b + Math.sqrt(b*b - 4*a*c)) / 2*a;
answer2 = ((-1) * b - Math.sqrt(b*b - 4*a*c)) / 2*a;
}
public void reCalc(int a, int b, int c) {
this.Calc(a,b,c);
}
public double getAnswer1() {
return this.answer1;
}
public double getAnswer2() {
215
return this.answer2;
}
}
1–2
コメントを作成します.
• Javadoc で使用される専用のタグを調べ,先のプログラムの全てのメソッドにコメントを作成して下さい.
• @author タグには自分の名前を入れて下さい.
• @param タグなどの前には,必ずメソッドの説明をいれて下さい.
/**
* メソッドのコメントの例です
* @param str 挨拶の対象者の名前
*/
public void hello(String str) {
System.out.println("Hello, "+str+"!");
}
1–3
Javadoc プログラムでドキュメントの出力を行って下さい.
1–4
Javadoc ドキュメントを公開領域に移動させ,外部から閲覧できるようにして下さい.
参考文献
[1] 宇治則孝 ほか,ずっと受けたかったソフトウェアエンジニアリングの新人研修, 翔泳社, 2009
第9回
バージョン管理システムの特徴,主なツールと
利用方法
バージョン管理ツールの機能と特徴,バージョン管理ツールの利用方法を説明し,現在広く利
用されている OSS のバージョン管理ツール(CSV,Subversion)を紹介し,Subversion につい
て詳しく扱う.また,分散リポジトリの考え方と,分散バージョン管理ツール(Git)を紹介
する.演習では,実際に Subversion を用いて,コミット,差分情報の確認を行うことにより,
バージョン管理ツールについて学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
バージョン管理システムとは
バージョン管理システムとは,主にソースコードなどのデータを管理することを目的とします.バージョン管理シス
テムでは,機能の追加後に不具合が発見された場合には差分情報を利用して不具合を取り除く作業のサポートや,リ
リース版と開発版を分けて管理するといった機能を提供します.
バージョン管理システムを利用するには中央集約しているサーバのリポジトリ*1 のクローンを作成し,ファイルを
編集します.ファイルの編集後は,その変更した情報をリポジトリにコミット*2 します.これによって変更前と変更
後にそれぞれ差分情報が保存されることになり,変更前のファイルを取り出すことを可能にしています.
バージョン管理システムは中央集約型の CVS や,CVS の問題点を解決しようとした Subversion などがあります.
最近では,リポジトリを中央集約にするのではなく,ローカルに保持する分散型のツールも開発されています.分散型
のツールの中には Linux カーネル開発に用いられている Git や Google code で採用された Mercurial などが有名です.
*1
*2
バージョン管理システムにおけるリポジトリは,バージョン管理を行うファイル・ディレクトリを保存する場所のことを指します
バージョン管理を行っているファイル・ディレクトリの変更前と変更後の差分情報をサーバに保存します
第2章
バージョン管理の方法
2.1 集中型のバージョン管理
集中型の管理方法はデータの一貫性を確保するため,すべてのデータをリポジトリに集中管理します.もちろん,
サーバに一元管理しているため,ネットワークでのアクセスが保証されている限りすべてのデータが取得可能です.し
かし,定期メンテナンスや停電などの障害によってサーバが停止した場合には,管理している全てのファイルのバー
ジョン管理は停止します.そのため,データの取得やコミットを行うことができなくなり,作業を継続させることは非
常に難しくなります.最近では中央集約に必要なサーバだけではなく,ローカルリポジトリを提供するツールも登場す
るようになりました.
2.2 分散型のバージョン管理
集中型の管理方法の欠点は,サーバにすべてのデータを集約するためにサーバに接続できない状況が発生すると,作
業の一切が滞ることでした.そこで,作業を行うローカル環境にリポジトリを配置し,相互にコミットやプッシュ*1 を
行うのが分散型の管理方法です.これにより,作業は常に継続することができ,他のメンバが自身のデータを欲してい
るとき,または他のメンバのデータを必要とするときに接続できれば良いことになります.しかしながら,他のメンバ
のデータは接続しない限りは最新のものではないことになります.そのため,必要とするデータをもっているメンバが
ネットワークにアクセスできない環境にいるときにはデータを更新することができません.最近では中央集約のサーバ
を配置することによってこの問題を解決することができるようになりました.
2.3 リポジトリの管理
バージョン管理システムにおいて,リポジトリの管理は非常に重要です.リリースまでにいくつかのステップがある
場合は,それに合わせた計画とリリース番号の規則を決める必要があります.また,リリースしたバージョンは仕様の
変更や追加に備えて,スナップショット*2 として残しておく必要もあります.すべてのプロジェクト管理をバージョ
ン管理システムで賄うことはできないため,プロジェクトごとに複数のルールが必要となる場合もあります.ここで
は,一般的なリポジトリ管理方法について紹介します.
*1
サーバへの差分情報の保存をコミット,他のメンバのリポジトリへの差分情報の保存をプッシュと区別します.バージョン管理システムに
よっては区別しない場合があり,どちらか一方に統一されている場合もあるので注意が必要です.
*2 バージョン管理システムにおいて,ある瞬間を保存すること.広義にはバックアップなどでも用いられる.
第 2 章 バージョン管理の方法
220
2.3.1 ディレクトリツリー
一般的なリポジトリはルートディレクトリ以下に, trunk ディレクトリ, branches ディレクトリ,そして tags
ディレクトリを配置しています.それぞれ次のような役割をもちます.
trunk 開発中のソフトウェアの最新版を追うことができます.当然,このディレクトリで管理しているものは正しく
ビルドすることができなければなりません.また,正常に動作することを確認した上で配置します.
branches trunk は常にビルドが可能な最新版の公開に使われます.そのため,試験的に新しい機能を追加する場合や
既存システムと整合がとれていないソースなどはコミットできません.そこで,trunk に配置できる安定的な
バージョンが完成後は,先進的な機能やバグへのパッチなどを開発するために,trunk からの branch を作成し,
そこで管理を行います.このような開発方法を行うことで,安定版には影響を与えることなく開発を続けること
ができます.
tags
branches で開発しているシステムを最新版として公開したい場合は,ビルドやテストなどの検証を得て,スナッ
プショットを tags に保存します.スナップショットをベータ版として公開し,安定して動作することが確認で
きたら,trunk への移動を行います.マイナーバージョンアップの場合は,既存のリリースである trunk と,ス
ナップショットである tags のマージにより対応することもあります.また,スナップショットを細かく保存す
ることで,変更の取り消しなどにも柔軟に対応することができます.
2.3.2 リリース番号
リリース番号はソフトウェアを公開する際に,過去にリリースしたバージョンと区別するために用いられます.ま
た,公開はしないものの,仕様の追加などによって現在のバージョンにマージする場合,バージョン管理システムでは
branch,つまり枝分かれさせるためのスナップショット名にも利用することができます.このリリース番号には規格
などは存在しませんが,一般的には Major.Minor.Patch の順に振ることになっています.
Patch Patch レベルでは大幅な機能変更はなく,むしろバグフィックスや UI などの細かな変更が中心となります.
そのため,セキュリティパッチ以外は適用しなくても問題がないことが多いといえます.セキュリティパッチの
場合は,その問題が公開されている時点で重大なセキュリティホールとなっている可能性が高いため,可能な限
り早く適用することが求められます.番号はインクリメントのみが行われます.
Minor Minor レベルは API や機能などが追加される場合にインクリメントされ,それまでの Patch を取り込むこと
が多いため,Patch 番号はリセットされます.機能追加などが行われますが,既存の機能が失われることは少な
いため,アプリケーションで用いているデータベースやデータなどについては下位互換性が保たれる(保証され
る)ことが多いです.下位互換性とは,ソフトウェアのバージョンが上がったとしても,それまでのバージョン
で利用していたデータを利用できることを保証することです.開発者は,アプリケーションに機能を追加すると
同時にそのバージョンアップを浸透させるため状況に応じて下位互換性を保つことも必要です.
Major Major レベルは API の削除などの仕様変更といった,大規模な変更に対して適用されます.番号がインクリ
メントされる場合には,Minor, Patch レベルの番号はリセットされます.データベースやデータなどの下位互
換性は保たれないこともあり,移行のためのツールが用意されることもありますが,そうでない場合はバージョ
ンアップを諦めるかデータの移行に大幅なコストを要求することになります.
但し,このようなルールによってバージョン番号がつけられたソフトウェアばかりではありません.例えば,TEX は
Donald Knuth によって開発された組版処理ソフトウェアですが,バージョン番号は 3 で始まり,現在まで 3.1415926
2.4 ワークフロー
221
まで公開されています [1].このバージョン番号は円周率を辿っており,ドナルド・クヌースの死をもってバージョン
は π となり,これ以後のバージョンは追加されないことになっています.また,同じくドナルド・クヌースによって
開発されたフォント作成システム METAFONT は, 2.718281 まで公開されており,こちらはネイピア数となってい
ます.
2.4 ワークフロー
ここではバージョン管理システムで,ソースコードなどのファイルを管理する場合のワークフロー(手順)について
説明します.通常,バージョン管理は複数人で行うことが多いため,リポジトリの作成と同時にバージョン管理する
ファイルの種別などを決定し,設定することが一般的です.また,複数人で開発する場合には,同時にファイルが編集
された場合の解決方法や,リリース毎にバックアップを取ることなどが求められます.これらは,その方法こそ異なる
ものの,ほぼ全てのバージョン管理システムに共通する機能となっています.
2.4.1 リポジトリの作成と設定
リポジトリの作成は,前述の集中型管理法か分散型管理法かによって異なります.集中型管理法の場合,Apache な
どのサービスと連携して動作することがあるため,それらの設定と併せて行う必要があります.Subversion の場合は,
Apache に連携するためのモジュールが公開されており,これを利用することで,簡単に導入することができるように
なっています.分散型管理法の場合には,サーバ・クライアント型ではないため,サーバのリポジトリ作成の場合にも
クライアントと同じ方法で作成することができます.但し,現在は集中型管理法と同じようにサーバでリポジトリを管
理し,クライアント同士のみでのバージョン管理はほとんど行われていません.そのため,この章では集中型管理と分
散型管理におけるサーバのリポジトリに差異はないものとして扱います.
リポジトリの設定の多くはバージョン管理システムに依存します.その中でも,多くのバージョン管理システムに含
まれている,重要な設定を紹介します.
ユーザの制限
ベーシック認証やダイジェスト認証などの技術を用い,閲覧や変更などの権限を設定します.プロプラ
イエタリ*3 な開発を行う場合,閲覧及び変更の権限は,管理者によって許可された開発者のみとし,オープン
ソースの開発を行う場合には閲覧及び変更の権限を全てのユーザに与えるなどの設定が可能です.また,ソース
の閲覧は許可するものの,開発者を制限したい場合には,変更の権限を開発者のみに与えるといったことも可能
です.このように権限の設定を適切に行うことで,安易な変更などから開発プロジェクト自体を守ることもでき
ます.
除外ファイルの設定
バージョン管理の対象とするファイル以外に,同一ディレクトリに他のファイルやディレクトリ
が存在した場合には,バージョン管理システムは未知のファイルとして認識します.バージョン管理システムに
よっては,自動的に管理の対象する場合も考えられます.このように,管理したくないファイルがバージョン管
理の対象とするディレクトリに存在する,もしくは存在する可能性がある場合には,除外ファイルの設定を行い
ます.また,除外ファイルの設定は多くの場合,サーバに設定する方法とローカルに設定する方法があります.
サーバに設定した場合には,チェックアウトやアップデートを通して,コミットするメンバの全員に反映されま
す.そのため,設定した後は,必ずコミットの処理を行い,設定を反映させる必要があります.当然,リビジョ
ン番号*4 も加算されてしまうので,安易な変更は行わず,リポジトリの作成時や,リポジトリのメンテナンス
時などに行うようにします.また,ローカルに設定した場合には,設定した本人しか反映されません.これによ
*3
*4
特定の企業のみによって開発・販売が行われるソフトウェアのこと.広義には,ハードウェアも含めたプロダクト全般を指すこともある.
バージョン管理システムで管理しているファイル群のバージョンのこと.ファイル 1 つ 1 つはバージョン番号として管理されていますが,複
数のバージョン番号は一括してリビジョン番号として管理されています.
第 2 章 バージョン管理の方法
222
り,LATEX やコンパイルを必要とする開発で生成される中間ファイル(オブジェクトファイル)やバイナリファ
イルを除外することができるため,本当にバージョン管理を必要とするファイルのみを適切に管理することが可
能になります.
ログコメントの変更
どのバージョン管理システムもコミット時にログコメントを残すことができます.ログコメン
トとは変更の反映時にどのような変更を行ったかについての情報を残すことです.コミットが行われた場合に
は,必ずリビジョン番号が加算されます.しかしながら,ログコメントが残っていない場合には,他のメンバ
は,バージョン管理されているファイル群から変更されたファイルを探し,前に保存されたバージョンとの差分
を見ることで変更情報を得なければなりません.これは複数人で開発を行っている場合には,非常に大きなコス
トになり,開発の効率が著しく低下します.ログコメントを正しく残すことにより,変更の情報を得る際にソー
スコードを確認する必要がなくなるため,開発効率が上がります.このように,ログコメントは非常に重要なた
め,間違った情報や,勘違いといった情報が残ると,開発に支障がでる可能性もあります.そこで,コミット時
に設定したログコメントを,後から修正する機能が,ほとんどのバージョン管理システムで提供されています.
これにより,不適切なログコメントを修正するなど,ログコメントを管理し,開発効率の向上に役立てるように
することが望ましいといえます.
以上がサーバでのリポジトリの作成と設定になります.他にも開発時に特殊な機能を必要とする場合には,バージョ
ン管理システムのヘルプやコミュニティで解決することができます.
2.4.2 チェックアウト, コミット, アップデート, ステータス確認
ローカルに設定を行う場合を除いて,クライアントにはリポジトリの作成や設定は必要ありません.リポジトリは,
サーバのコピーをローカルに保存し,ローカルで行った変更内容をサーバに反映します.より厳密には,集中型管理を
行っている場合には,バージョン管理はサーバのリポジトリでのみ行われており,ローカルのファイルは一時的なもの
に過ぎません.そのため,ローカルのリポジトリはコピーと呼ばれています.分散型管理の場合には,バージョン管理
はクライアントのリポジトリ間で行っており,サーバのリポジトリとはいいつつも,あるクライアントのリポジトリに
過ぎません.これにより,ローカルのリポジトリに保存されている内容は,サーバのリポジトリと全く同じになります
が,集中管理法とは異なり,バージョン管理自体はローカルで行っています.そのため,リポジトリの内容だけは同じ
という意味で,ローカルのリポジトリはクローンと呼ばれます.この章では,集中型管理でのコピーも分散型管理での
クローンもコピーとして扱います.
図 2.1 は,バージョン管理システムを利用するユーザのワークフローを示しています.ユーザはサーバで管理されて
いるファイル群をローカルにコピーし,変更を加えた後,その情報をサーバに反映させることを繰り返すことにより,
バージョン管理システムを利用します.
ローカルにファイルをコピーすることはチェックアウトと呼ばれています.チェックアウトはクライアントが最初に
サーバのリポジトリをローカルに保存するために用いられるため,通常は初回のみ行います.また,ローカルで加えた
変更をサーバに反映せず,サーバに保存されているファイル,もしくは特定のリビジョンで上書きしたい場合にも用い
られます.
既にチェックアウトが終わり,サーバのリポジトリがローカルにコピーされている場合,サーバの変更を確認する方
法を集中型管理ではアップデート,分散型管理においてはチェックアウト*5 で行います.用語こそ異なるものの,変更
情報を取得し,変更が加えられたファイルのみをサーバから取得します.リポジトリのコピーでは全てのファイルを転
送するためファイルサイズやファイル数によっては非常に時間がかかりますが,変更部分だけの転送であれば,短い時
間で処理を完了させることができます.
*5
分散型管理法によるバージョン管理システムによっては fetch(フェッチ) などと呼ぶ場合もあります
2.4 ワークフロー
223
図 2.1
チェックアウト, コミット, アップデート, ステータス確認
そして,ソースコードなどに変更を加えたファイルの情報をサーバに反映させます.既に管理対象となっているファ
イルであれば,変更の情報をそのままサーバに反映させるだけで完了します.しかしながら,新しく作成したファイル
やサブディレクトリ,バージョン管理システムに通知せずにリネームや削除したファイルが存在した場合には,バー
ジョン管理システムにバージョン管理の指示を行うまで明示的にバージョン管理は行われません.バージョン管理シス
テムが管理していない,つまり未知のファイルを見つけた場合,ユーザに通知する機能が提供されています.これによ
り,ユーザは追加・変更・削除の処理をバージョン管理システムに通知して管理の対象にするほか,除外ファイルとし
て設定することで,このステータス確認からも除外することができるようになります.
サーバに変更情報を反映させる処理をコミットと呼びます*6 .コミットはローカルで変更した内容の全てをサーバの
リポジトリに反映させます.但し,ローカルのバージョン管理システムが認識していないファイルはコミットの対象と
はならないため,前述のステータスの確認によって適切にバージョン管理の対象となっていることを確認する必要があ
ります.また,コミット時はチェックアウトもしくはアップデートし,コピーしたリポジトリとの変更点をログコメン
トとして残します.このログコメントは正確に適切な量を記述することで,開発の効率を上げることができます.
バージョン管理の対象となっているファイルは,ちょっとした変更も全てコミットされ,サーバに反映されるため,
コミットのポリシーを決めておくことも重要です.例えば,他のメンバが管理するソースファイルを閲覧した際に,タ
グを空白に自動変換してしまっていたり,波括弧「{ }」などの位置を好みの位置に移動したりといった本来の目的と
は関係ないコミットを禁止しておくことで,不必要なコミットを少なくする努力も必要です.
*6
分散型管理法によるバージョン管理システムによっては push(プッシュ) などと呼ぶ場合もあります
第 2 章 バージョン管理の方法
224
2.4.3 コンフリクト
コンフリクトは,直訳では衝突と訳されますが,バージョン管理システムにおいては競合という言葉の方がよく使わ
れています.バージョン管理システムで扱うコンフリクトは,ファイル変更に伴うもの,ファイル名の変更や移動,削
除に伴うものが挙げられます.ファイル名の変更などによるコンフリクトはポリシーなどによってある程度は抑制が可
能であり,発生頻度はそれほど高くありません.しかしながら,ファイルの変更によるコンフリクトは,複数人で開発
している限り,非常に高い確率で発生します.そこで,この節ではファイルの変更によるコンフリクトのみを対象とし
て扱います.
ファイルの変更によるコンフリクトは,ファイルコンフリクトとして,バージョン管理システムが生まれた当初より
問題となっていました.コンフリクトは複数の開発者が,異なるローカルリポジトリで,同一ファイルを編集した場合
に発生します.より厳密には,次のような例があります. Foo.c を開発者 A と開発者 B が同時に編集し,開発者 A が
先にコミットします.この時は, Foo.c が開発者 A によって変更されただけであり,バージョン管理システムはこの
変更を受け入れます.次に開発者 B が Foo.c に変更を加え,コミットした場合に初めてコンフリクトが発生します.
バージョン管理システムは,編集された複数のファイルの中で,最も優れた編集を採用するといった処理を行うことが
できません.そのため,このコンフリクトの解消には開発者同士の協議によって,開発者自身が解決する必要がありま
す.特に,同一ファイルの同一箇所が変更された場合,開発者が取り得る解決手段は以下のいずれかです.
1. 先にコミットされた変更を破棄する
2. コンフリクトを発生させた開発者のコミットを破棄する
「先にコミットされた変更を破棄」する場合,ローカルにリポジトリをコピーしたときと同一のリビジョンまで戻す
ことによって問題を解消します.また,「コンフリクトを発生させた開発者のコミットを破棄」する場合には,コミッ
ト自体を元に戻す,つまりコミットをなかったことにします.これにより,コンフリクトを解消し,正常なバージョン
管理が継続できるようになります.また,エディタ(特にコンフリクトエディタと呼ばれることもある)を起動し,コ
ンフリクトしたファイルから適切な変更を行うこともできます.これは,コンフリクトしたそれぞれのファイルの内容
が同種の問題を解決しようとしている場合や,大きなファイルでコンフリクトが生じた場合に,必要とされる変更点を
全て抽出し,反映させる目的で利用します.全ての変更点を 1 つのファイルとしてまとめることはマージとも呼ばれ
ます.
2.4.4 ブランチ, タグ, スイッチ, マージ
図 2.2 は,ブランチ,マージの概要を表しています.規模が大きいソフトウェア開発においては,しばしばソフト
ウェア全体の品質に関わるような新機能の追加が行われます.しかし,既存のリポジトリに変更を加えてしまっては,
コンパイルすら通らないことが起こり得ます.このような場合には枝分かれ,つまりブランチと呼ばれるサブプロジェ
クトを作成し,そこで開発を継続します.サブプロジェクトとしてリポジトリを管理することで,新機能の開発を滞る
ことなく継続することができるようになります.また,既存のリポジトリは変更されないため,既に完成されたソフト
ウェアとの互換性を逐一確認しながら開発を行う必要がなく,開発の効率を上げることもできます*7 .但し,セキュリ
ティパッチなどはパッチテスト用のブランチで問題ないと判断された場合は即座にメインプロジェクトに反映させるな
ど,闇雲にブランチを作るのではなく,一般のユーザに不便をかけないように配慮することが望ましいといえます.
マージは,ソフトウェアのパッチや新機能などの開発を行っていたサブプロジェクトからメインプロジェクトに吸収
*7
テストを行う必要がないのではなく,通常のテストと同様に全ての機能追加後にテストを行うことで,効率的にテストを行うことを示してい
ます.
2.4 ワークフロー
225
࣓࢖ࣥࣉࣟࢪ࢙ࢡࢺ
図 2.2 ブランチ,マージ
する場合などに用いられます.また,軽微な変更をブランチを通さずにメインプロジェクトで行った場合に,ブランチ
にも変更を反映させるためにも用いられます.つまり,マージとはリポジトリ内の 2 つのリビジョンを統合する処理
を示します.このマージは,バージョン管理システムごとに多少の差異はあるものの,ほとんどの場合は,2 つのリビ
ジョンの差分情報を指定したメインプロジェクトに反映させる処理を行うことで実現します.また,サポート用のブラ
ンチの場合,パッチの完成のたびにマージが必要となります.その場合には,前回マージした直後のリビジョンとパッ
チを完成させたリビジョンの差分情報をメインプロジェクトに反映させます.ブランチ直後のリビジョンと既にパッチ
が複数回適用されたメインプロジェクトの差分情報を指定した場合は,既に適用されたパッチ情報を重複して適用しよ
うとしてしまい,意図したマージを行うことができません.また,差分情報を取得する 2 つのブランチ(メインプロ
ジェクト)と,リビジョンがあればマージが可能なため,目的を終えたブランチや意図せず増加してしまったサブプロ
ジェクトを 1 つまたは複数のアクティブなサブプロジェクトに統合することもできます.
図 2.3
タグ
図 2.3 はタグの概要を表しています.ソフトウェアをメジャーバージョンアップ,場合によってはマイナーバージョ
ンアップなどの大幅な変更を加える場合には,既存のソフトウェアを利用するユーザを考慮し,セキュリティパッチな
第 2 章 バージョン管理の方法
226
どを当てることができるように,既存のソースコードを保存しておくことが望ましいといえます.また,既存のソース
コードを保存する際には,タグと呼ばれる名前をつけて管理することができます.一般的にはバージョン番号で管理し
ますが,メジャーバージョン番号レベルで 1 つだけ保存する場合などは,開発コードネームをタグにする場合もありま
す.特に規則などがあるわけではないので,タグを保存する場合には,開発プロジェクトでポリシーを定め,ユーザに
も開発者にもわかりやすい,一貫した命名規則を決めておくことで,混乱を避けることができます.
図 2.4
スイッチ
図 2.4 は,スイッチの概要を表しています.パッチの作成や新機能追加などの目的でブランチを作成した場合には,
以後の開発はそのブランチで行います.そこで現在,開発しているメインプロジェクト,もしくはブランチから新しく
作成したブランチに移動することをスイッチと呼びます.もちろん,ブランチだけではなく,既に作成したタグにス
イッチすることもできます.また,サーバの都合によりリポジトリ自体が移動した場合には,クライアント側もリポジ
トリの場所を変更しなくてはなりません.この場合には,リポジトリコピーの全てを削除して,新たにチェックアウト
することでも実現は可能です.しかし,非常に大きなサイズのファイルを扱っている場合や,大人数で運用している場
合には,移動直後にチェックアウトの処理が多く要求されることになり,負荷が大きくなります.そこで,このような
場合にもスイッチを利用することによって簡単に新しいリポジトリを追跡できるようになります.また,バージョン管
理システムによっては,ドメインまたはサブドメインの変更によるリポジトリの移動はスイッチと呼び,同一ドメイン
またはサブドメイン内でのリポジトリの移動はリロケート(relocate) と呼ぶことで区別している場合があります.
第3章
バージョン管理システムの種類
バージョン管理システムは様々なツールが知られていますが,その中でも特に有名な CVS , Git , Subversion を紹
介します.
3.1 CVS
CVS(Concurrent Versions System)は,The CVS Team によって開発・維持されています.CVS はネットワー
クを利用した集中型管理方法によるバージョン管理システムとして,最初に開発されました.特に,ソースコードなど
のテキストデータを管理するのに優れていますが,バイナリデータの扱いについてはあまり考慮されていないため,扱
いには注意が必要となります.また,SJIS や EUC によるサポートがないため,EUC を中心とした日本語環境では利
用が難しいことも挙げられます.但し,長く利用されているため非常に安定して動作することや,統合開発環境などの
プラグインが多数公開されているのもあり,現在でも多くのオープン系プロジェクトで利用されています.
3.1.1 CVS の導入
CVS は本テキストが前提とするシステムでパッケージが提供されているため,導入は非常に容易になっています.
$ sudo apt-get install cvs
$ sudo apt-get install xinetd
ただし,スーパサーバ経由でなければ正常に動作しないため,スーパサーバの設定を行います.設定ファイルは
/etc/xinet.d/ に cvspserver ファイルを作成して行います.設定の内容は以下の通りです.
cvspserver
service cvspserver
{
disable
= no
port
= 2401
socket_type = stream
protocol
= tcp
wait
= no
user
= root
passenv
=
server
= /usr/bin/cvs
server_args = -f --allow-root=/var/cvs pserver
}
第 3 章 バージョン管理システムの種類
228
スーパサーバのデーモンである xinet を再起動して反映させます.
$ sudo /etc/init.d/xinetd restart
今回は,CVS を /var/cvs に作成します. CVSROOT ディレクトリは,直前の CVS による初期化が正常に完了して
いれば,作成されます.また,パスワードファイル名は変更しないでください.
$ sudo mkdir -p /var/cvs
$ sudo cvs -d /var/cvs init
$ sudo htpasswd -c /var/cvs/CVSROOT/passwd anonymous
次に,CVS のリポジトリを作成します.まず,リポジトリに追加するファイルを作成し,リポジトリの初期化と同
時に追加を行います.
$ cd
$ mkdir tmp
$ cd tmp
$ echo "test" > README
$ CVSROOT=/var/cvs
$ export CVSROOT
$ cvs import cvstest user init
最後に,外部から利用できるようにディレクトリの権限を変更します.また, whoami で表示されるユーザを先ほど
設定した cvs ログイン用ユーザの末尾に追記します.パスワードを空白で設定した場合は以下のようになりますが,そ
れ以外の場合にも変更する必要はありません.
$ whoami
test
$ sudo chgrp -R test /var/cvs
$ sudo vi /var/cvs/CVSROOT/passwd
anonymous:hoKSrv9ahUyFY:test
以上で,外部から接続する設定が完了します.
3.1.2 CVS の利用
CVS はポート番号 2401 を利用します.ファイアウォール(iptables)が設定されている場合には通過を許可してく
ださい.
CVS のサーバに外部から接続するには,ログインを行い,初回のみチェックアウトを行う必要があります.
$ CVSROOT=:pserver:[email protected]:/var/cvs
$ export CVSROOT
$ cvs login
Logging in to :pserver:[email protected]:2401/var/cvs
CVS password:
$ cvs co hello
パスワードは前節の anonymous ユーザで設定したものを利用して下さい.ログインが正常に行われた場合にはメッ
3.2 Git
229
セージは何も表示されませんが,もしもエラーになった場合には以下の項目を確認して下さい.いずれも CVS の導入
を参考にして行って下さい.
1. iptables でポート番号 2401 を解除している
2. htpasswd コマンドで passwd ファイルを作成する
3. 所有グループの変更と passwd ファイルへの追記を行っている
初回以降は update によってファイルの更新をチェックできます.CVS のリポジトリを利用するために有用なコマ
ンドを表 3.1 に示します.
表 3.1 CVS のコマンド一覧
コマンド
説明
cvs checkout
初回のみリポジトリのコピーを作成する
cvs update
ファイルの更新チェックを行う
cvs commit
ローカルで変更した内容をリポジトリに反映する
cvs add
ローカルに追加したファイルをリポジトリにも追加する
cvs remove
リポジトリで管理しているファイルを削除する
cvs release
commit されていないファイルがないかをチェックして,ローカルのコピーを削除する
3.2 Git
Git は分散型バージョン管理システムです.そのため,基本的には中央管理サーバはありません.しかしながら,全
員が常にオンラインとは限りませんので,仮想的に一元集約を担うサーバとして設定を行います.
3.2.1 Git の導入
導入は git パッケージが用意されていますので,容易に行うことができます.
$ sudo apt-get install git
サーバ側として用意するリポジトリには bare オプションをつけて作成します. bare オプションは”裸の”を意味
し,管理するファイルが存在しない状態でのリポジトリ作成を行います.そのため,サーバ側だけでなく,空のリポジ
トリを作成する場合には常に bare オプションを使用してください.
$ sudo mkdir -p /var/git/testgit
$ whoami
test
$ sudo chown -R test:test /var/git
$ git --git-dir /var/git/testgit --bare init
以上で,リポジトリの作成は完了です.
3.2.2 Git の利用
まず,リモートリポジトリのコピーを作成します.リモートリポジトリのコピーを作成するには,作成したいディレ
クトリに移動し,以下のコマンドを実行します.なお, example.com は適宜,変更して下さい.
第 3 章 バージョン管理システムの種類
230
$ git clone ssh://[email protected]/var/git/testgit
次に,管理を行いたいファイルを編集し,それをコミットします. origin はリモートリポジトリを表し, master
はローカルリポジトリを表します.
$ git remote add origin ssh://[email protected]/var/git/testgit
$ git push origin master
3.3 Subversion
Subversion は CVS を改良する目的で開発されました.そのため,異種の文字コードを扱うことが可能であり,バイ
ナリにも非常に柔軟に対応できます.詳しくは,次章で説明します.
第4章
Subversion
4.1 Subversion の導入
Subversion は本テキストが前提とするシステムでパッケージが提供されているため,導入は容易になっています.
ここでは,Apache2 による Web ブラウザからの閲覧もサポートするため, libapache2-svn モジュールも導入して
います.
$ sudo apt-get install subversion{,-tools} libapache2-svn
次に Apache の設定を行います. /etc/apache2/mods-available/dav svn.conf の最後に Location ディレク
ティブを追加してください.
<Location /svn>
DAV
svn
SVNParentPath /var/svn
</Location>
また,この設定を有効にするために以下のコマンドを実行して下さい.これは Apache のモジュールを有効にするコ
マンドでもあります.無効にするには a2dismod が利用できます.
$ suod a2dismod dav svn
これで以下の起動から svn が利用できますので, Apache を再起動します.
$ sudo /etc/init.d/apache2 restart
次にリポジトリを作成します.今回は /var に svn ディレクトリを作成し,ここでバージョン管理を行うこととしま
した. svnadmin コマンドによってリポジトリを作成します. TestSVN ディレクトリは自動的に作成されます.
$ sudo mkdir -p /var/svn
$ sudo svnadmin create /var/svn/TestSVN
$ sudo chown -R www-data:www-data /var/svn/TestSVN
以上により,Subversion のリポジトリが完成しました.CVS では設定が煩雑でしたが,より容易に導入するとの思
想をもって開発されているため,CVS と比べると簡単に設定することができます.
4.1.1 Subversion の設定方法
Subversion を利用するユーザの制限方法と,バージョン管理しないファイル(除外ファイル)の明示的な指定方法
について説明します.
第 4 章 Subversion
232
ユーザ制限
まず, /etc/subversion/config ファイルの enable-auto-props を「yes」(有効)にしてください.標準ではコメ
ントアウトになっていることが多いので,その場合には,「#」を外すことで有効にできます.
/etc/subversion/config
#100 行目付近の以下の行のコメントアウト(#)を外す
enable-auto-props = yes
ユーザの制限を行うには,前述の svn 用 Location ディレクティブを以下のように変更します.但し,ユーザの制限
を行わない場合は,変更する必要はありません.
/etc/apache2/mods-available/dav svn.conf
<Location /svn>
DAV svn
SVNParentPath /var/svn
# add following lines
AuthType Basic
AuthName "svn repository authentication"
AuthUserFile /var/svn.passwd
AuthzSVNAccessFile /var/svn.authz
Require valid-user
</Location>
ここで,AuthUserFile はユーザ認証のためのパスワードファイルの場所を絶対パスで記述し,AuthzSVNAccessFile
はアクセス権限の設定を行うファイルの場所を絶対パスで記述します.svn の場所を変更している場合,もしくはパス
ワードファイルなどを適切な場所に配置したい場合には,変更することも可能です.
パスワードファイルを作成します.ここでは,パスワードファイルの生成と同時に hogeuser を追加しています.
$ sudo htpasswd -c /var/svn.passwd hogeuser
次に作成したユーザのアクセス権限を設定します.この設定では,全てのユーザに全ての svn リポジトリを閲覧する
権限があります.それに対して,TestSVN リポジトリでは,先ほど作成した hogeuser のみに更新権限が与えられてい
ます.
/var/svn.authz
[/]
* = r
[TestSVN:/]
hogeuser = rw
また,ここまでの設定を Web サーバに反映させるために Apache を再起動します.
4.2 Subversion の利用方法
233
$ sudo /etc/init.d/apache2 restart
以上で,ユーザの制限がついたリポジトリを作成することができます.更新権限をもつユーザを追加した場合は,
htpasswd コマンドで認証用のユーザを追加し, authz ファイルに追加してください.
除外ファイルの設定
例えば,LATEX では,中間生成されるファイルとして aux ファイルや log ファイルなどがあります.しかし,これ
はタイプセットするときには必要ですが,開発者が編集するものではないため,バージョン管理の必要性がありませ
ん.そこで,この 2 つのファイルを前述の通り作成したリポジトリに設定します.
$ cd /var/svn/TestSVN
$ svn propset -R svn:ignore "*.aux *log" "."
$ svn commit -m "configure svn:ignore list that ignore *.aux *.log"
この設定はサーバに設定され,コミットを行う全てのユーザが影響を受けます.そのため,この設定をサーバで有効
にするにはコミットが必要となります.また,前述のユーザ制限を行った場合には,ユーザ名とパスワードが尋ねられ
ますので,設定した値を入力して下さい.
その他の設定
Subversion では,バージョン管理するファイルは MIME タイプ を保持しています.この MIME タイプの設定が適
切でない場合,テキストファイルであったとしても,バイナリファイルとして扱われてしまいます.MIME の情報を
表示するには,以下のコマンドを利用します.
$ cd /var/svn/TestSVN
$ svn proplist --verbose test.txt
もしも適切な MIME タイプが設定されていない場合には,標準化されたリストが公開されている [2] ので,参考に
して,適切に設定して下さい.テキストファイルの MIME タイプとして最も有名な text/plain を設定するには以下の
コマンドを利用します.
$ cd /var/svn/TestSVN
$ svn propset svn:mime-type text/plain test.txt
$ svn commit -m "reconfigure mime-type of test.txt"
最後に,これまで設定したプロパティ値を取得する方法を紹介します.例えば,特定のリビジョンのログコメントを
参照したい場合には,以下のコマンドを利用します.
$ svn propget svn:log --revprop -r 69
4.2 Subversion の利用方法
Subversion をコマンドで利用します.
チェックアウト
リポジトリのクローンを作成します. example.com は自サーバの IP アドレスに置き換えて下さい.
$ svn checkout http://example.com/svn/TestSVN
第 4 章 Subversion
234
コミット
ここでは空のファイルを作成し,Subversion で管理することを明示してコミットしています.コミットの際は必ず
コメントが求められ, SVN EDITOR で設定したエディタが使用されます.また, m オプションを用いることで省略する
こともできます.
$ cd TestSVN
$ touch test
$ svn add test
$ svn commit -m "commit comment"
タグ
タグを作成します.以下のコマンドでは tags ディレクトリ以下に, dev とつけられたタグが作成されます.
$ svn copy trunk tags/dev -m "branch from trunk"
$ svn commit -m "tag test"
ブランチ
次の開発を行うためにブランチを作成します.これにより,最新の情報は branches で更新するようにします.
$ svn copy trunk branches -m "branch from trunk"
$ svn commit -m "branch test"
マージ
開発中のバージョンとメインラインもしくは他で開発しているソースをマージします.以下のコマンドはリビジョン
268 と最新のバージョン(HEAD は最新のリビジョン番号を表す)をマージします.リビジョン 268 と beta スナッ
プショットが存在しない場合には実行できないので注意して下さい.
$ svn merge -r 268:HEAD http://example.com/svn/TestSVN/branches/beta
4.3 キーワードアンカーテキスト
バージョン管理システムによって管理されているファイルは,しばしば Web ブラウザなどから確認できるよう
になっています.しかしながら,閲覧しているファイルはいつ変更されたのか,誰が変更したのかといった情報は
すぐには確認できません.これを解決するのがキーワードアンカーテキストです.キーワードアンカーテキストは
Subversion 独自のタグを埋め込むことにより,バージョン管理システムへファイルの変更を追加する際に,指定され
た情報に置換する役割を担います.これにより,修正を行った担当者や日付といった情報をファイルの変更のたびに修
正するといった煩わしさから解放されることになります.また,バージョン管理システム上から閲覧するときは置換さ
れた情報が表示されていますが,タグが埋め込まれたファイルにはタグの情報しか記述されていません.
4.3.1 キーワードアンカーテキストの種類
Subversion で利用できるキーワードアンカーテキストは 5 種類あります.
Date ファイルの最終更新日時を表します. $Date: $ または $LastChangedDate: $ を利用します.置換後は,
$LastChangedDate:
2009-07-22 22:00:00 +0900 (水, 22 7 月 2009)$ のようになります.このとき,
4.3 キーワードアンカーテキスト
235
Id とは異なり,時間は JST(UTC +0900)で表されていることに注意して下さい.
Revision ファイルの最終更新リビジョンを表します. $LastChangedRevision: $ または $Rev:
置換後は $Revision:
$ を利用します.
17$ のようになります.
Author ファイルの最終更新者を表します. $Author:
$ または $LastChangedBy:
$ を利用します.置換後は,
$LastChangedBY: admin$ のようになります.
HeadURL ファイルの存在場所を表します.置換後は $HeadURL: http://example.com/svn/hello.c$ のように
なります.
他のキーワードを圧縮して表示します.表示形式は「ファイル名 Revision Date Author」の順序となります.
Id
置換後は, $Id:
hello.c 17 2009-07-22 13:00:00Z admin$ のように表示されます.このときの時間は
UTC を用いて表されていることに注意して下さい.
このキーワードには他のキーワードが圧縮されているため,他のキーワードと比較して単独して利用される頻度
が最も高くなっています.
4.3.2 キーワードアンカーテキストの有効化
キーワードアンカーテキストをバージョン管理対象ファイル内に書いたとしても,標準では有効になっていないため
置換されません.この置換を自動で行うためには Subversion に対して明示的に置換を要求する必要があります.
$ svn propset svn:keywords "Id" hello.c
ダブルクオート内に有効にするキーワード群をスペースをデリミタ*1 として入れます.ファイル内のキーワードと
一致したものだけが置換されるため,ここで指定しないと置換されないので,注意が必要です.
*1
区切り記号のこと.CSV ファイルなどでは,カンマやスペース(タブ)などがよくデリミタとして使用されます.
第 9 回 演習課題
目標
バージョン管理ツールの設定・運用をします.
まず Subversion の設定を行います.次にプログラムの作成・追記を行い,差分情報を取得して下さい.
課題 1 Subversion を用いたコミット
1–1
4 章を参照し,Subversion を利用できるように設定を行って下さい.
1–2
先の『入力値が偶数であるかを判定するプログラム(even.c)』を作成し,Subversion にコミットして下さい.
#include <stdio.h>
#include <stdbool.h>
bool isEven(int num) {
return (num%2) ? false:true;
}
int main(void) {
int num;
scanf("%d", &num);
fprintf(stdout, "%d は偶数", num);
if( isEven(num) ) fprintf(stdout, "です\n");
else fprintf(stdout, "ではありません\n");
}
1–3
先の『入力値が偶数であるかを判定するプログラム』に,『入力値が奇数であるかを判定する関数と出力するコード』
を追加し,コミットして下さい.与えられたコード部分への変更(削除・修正)は行わないで下さい.
課題 2 差分情報の取得
237
2–1
演習で変更した even.c の差分情報を取得して下さい.差分情報は以下のコマンドを用いて出力します.最初にコ
ミットした(サンプルコードのみの)ファイルのリビジョンを X に代入します.
$ svn diff -rX even.c|tee (id).log
コミットした情報は以下のコマンドで閲覧できます.最も古いリビジョン番号(若い番号)を探して下さい.
$ svn log even.c
参考文献
[1] Knuth: Computers and Typesetting, http://www-cs-facu:tabpy.stanford.edu/∼knuth/abcde.html
[2] Internet Assigned Numbers Authority, http://www.iana.org/assignments/media-types/index.html
第 10 回
バグ追跡システムの目的・機能と利用方法・
Trac の利用
バグ追跡システムの目的・機能・役割と位置付けを解説する.継続的なデバッグの実現やバグ
対応の生産性向上に寄与することを示し,品質向上に不可欠なツールであることを説明します.
オープンソースのバグ追跡システムの代表的なシステムである Trac の導入方法と基本的な使
い方について説明します.演習では,Trac を用いて実際にチケットを登録し,確認や状態の変
更を行うことで,バグ追跡システムの運用について学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
バグ追跡システムとは
バグ追跡システム(BTS: Bug Tracking System)とは,ソフトウェア開発において発生したバグの情報を共有し,
修正が完了するまでを追跡するシステムのことです.バグ管理システムの多くは Web ブラウザからのアクセスを可能
としており,情報は集約され一元管理されているのが一般的です.バグを包括的に管理するという観点から,バグ管理
システムとも呼ばれます.
ソフトウェア開発において,バグの発生は回避できないため,その発見と修正はとても重要な課題です.近年はハー
ドウェアの制約はほとんどなくなり,ソフトウェアがカバーできる分野が増えたため,その規模は大きくなる傾向にあ
ります.また,ソフトウェアの規模が大きくなるにつれて,バグの発生数も多くなります.このように,非常に多くの
バグが発生したり,少なくとも相互に依存するバグが発生した場合には,プロジェクト内,バグの修正をするメンバ間
で緊密に連携して問題を対処しなければなりません.このような場合に,メーリングリストや会議だけでは,正しい情
報が伝達するとは限らず,情報の共有が不十分となる可能性があります.バグ追跡システムは,発生したバグごとに,
バグの内容,修正の担当者,そしてバグに関する議論が行える機能を提供します.これにより,プロジェクト内でバグ
の情報を正しく共有することが可能となり,効率的に開発を進めることができるようになります.
1.1 バグ追跡システムの特徴
バグ追跡システムは,開発の規模,開発環境,そしてツールの種類によらず概ね以下のような特徴があります.
バグ報告の集約
複数のテスト担当者によって発見されたバグリストを個々のファイルで管理していた場合,全てのバ
グを集約するにはマージする作業が必要です.また,この情報を共有するには HTML 化して公開したり,ファ
イル自体の配布を受ける必要があるため,集約,作成,配布に時間がかかり,その間にもバグが見つかるなど情
報が最新ではない可能性がありました.バグ追跡システムを利用することで,最初からバグの情報を集約するこ
とができるようになります.プロジェクトリーダがバグの管理を行いやすいだけではなく,バグの修正担当者
などのメンバはリアルタイムに更新されるバグの情報を閲覧することができるため,素早い対応が可能となり
ます.
バグ解決プロセスの明確化
複数の担当者が関係する箇所でバグが発生した場合には,修正の担当者を決定する必要が
あります.また,修正の担当者自身がその旨を宣言しファイルなどに書き込んで配布する場合には,修正担当者
になってからバグを修正するまでにタイムラグが発生してしまうため,効率がよいとは言えません.バグ追跡シ
ステムを利用することで,プロジェクトリーダなどの責任者が直接指名することが可能となり,担当者が明確に
なるため,他のメンバが修正する可能性は排除されます.また,担当者の割当にタイムラグが発生しないため,
効率的にバグの修正を行うことができます.
バグのレポート出力
報告されたバグを全て追跡するため,バグが報告されてから修正の確認が行われるまでの全ての
過程が明瞭になります.そのため,個々のバグの追跡結果,現在修正中などのステータス別のバグ件数,信頼度
成長曲線やバグの傾向などの各種データを集計することができるため,納品物としてのドキュメント生成にも利
1.2 バグ追跡システムのワークフロー
241
用することが可能となります.
1.2 バグ追跡システムのワークフロー
バグ追跡システムを用いたバグの管理は,概ね以下のような手順で行われます.
1. バグの報告
テスト担当者はテスト仕様書に従ってテストを行い,発見されたバグをバグ追跡システムで報告を行います.報
告したバグのステータスは Open となり,全てのメンバはバグを認識できるようになります.
2. 担当者の割当
プロジェクトリーダなどの責任者は,バグの情報を認知し,バグの修正担当者を割り当てます.修正の担当者を
割当後,バグのステータスを担当者割当済みを示す Assigned に変更します.
3. バグの修正
バグの修正担当者は,バグの修正後,修正内容や解決方法などの報告を行い,バグのステータスを解決状態を示
す Resolved に変更します.
4. 担当者以外によるダブルチェック
バグの修正担当者によって修正されたバグは,テスト担当者もしくはプロジェクトリーダなどがその確認を行い
ます.確認後,正しく修正されていた場合はバグのステータスを Verified に変更します.もしも再度修正が必
要だと判断された場合,バグのステータスを Reopen にし,以後,同様のステップにて解決を行います.
5. 修正の終了
テスト担当者やプロジェクトリーダによるチェックに問題がなかった場合,バグのステータスを Closed に変更
し,バグの修正を完了します.
第2章
バグ追跡システムの種類
多くのバグ追跡システムがオープンソースで公開されていますが,ここでは Bugzilla と Trac という代表的な 2 つの
バグ追跡システムを紹介します.Bugzilla はバグ追跡システムの草分けとして長く利用されてきました.それに対して
Trac はバグ追跡システムの機能に加え,様々な外部ツールと親和性が高く,近年注目されるツールの 1 つです.
2.1 Bugzilla
Bugzilla は Mozilla Foundation [1] が開発・維持を行う Web ブラウザベースのバグ追跡システムです.もともとは
Netscape 社内で利用されていたバグ追跡システムを同社の Web ブラウザであった Netscape Communicator 5.0 の
ソースコード公開と併せて公開しました.初期は Tcl で記述されていましたが,現在はそのほとんどが Perl によって
書き直されています.
Bugzilla は Netscape 社が開発したことからもわかる通り,商用ソフトウェアの開発に用いられてきました.そのた
め,大規模な開発にも耐えることができるような仕組みが多く用意されています.例えば,発見されたバグについて関
係者が議論する場所がバグごとに提供されていたり,相互に依存するバグを登録できる機能などは,後のバグ追跡シス
テムに大きな影響を与えています.
2.1.1 Bugzilla の必要要件
Bugzilla を導入するためには,以下のシステムが必要です [2].
• Perl (5.8.1 かそれ以上)
• Database Engine (MySQL, PostgreSQL, Oracle)
• Webserver (Apache 1.3.x か 2.x を推奨)
また,Bugzilla 導入後には以下の Perl モジュールの導入が必要です.
• CGI 3.21
• Date::Format (2.21)
• DBD::mysql (4.00) if using MySQL
• DBD::Pg (1.45) if using PostgreSQL
• DBD::Oracle (1.19) if using Oracle
• Template (2.22)
• Email::Send (2.00)
• Email::MIME::Modifier (1.442)
2.2 Trac
243
その他,バグ追跡システムからメールを送信するため,Sendmail または Sendmail に準拠した MTA(Mail Transfer
Agent)が必要です.
2.1.2 Bugzilla のインストール
本テキストで扱うシステムで Bugzilla のインストールを行うには,bugzilla3 パッケージをインストールだけで行え
ます.
$ sudo apt-get install bugzilla3{,-doc}
依存関係などを自動解決し,インストールを行います.
2.2 Trac
Trac は Edgewall Software によって開発・維持されるバグ追跡システムです.Python によって記述され,修正
BSD ライセンスによって配布されています.様々なバージョン管理システムと非常に相性がよく,Subversion, Git,
Mercurial で管理されているソースコードを閲覧するインタフェースも提供されています.また,コアパッケージは非
常に軽量で,機能も限定されていますが,プラグインを追加することで,プロジェクトの規模や開発ツールに応じたバ
グ開発システムの構築を可能とします.例えば,テスト管理システムとして有名な TestLink と連携することや,プロ
ジェクトの進捗状況を可視化するガントチャートを導入することも容易です.
2.3 その他のツール
Bugzilla や Trac の他にも,表 2.1 に示すような,日本語環境で動作するオープンソースのバグ追跡システムが存在
します.プロジェクトの状況や必要な機能に応じて,利用するツールを選択することが望ましいといえます.
表 2.1
バグ追跡システム
様々なバグ追跡システム
説明
Redmine
Ruby on Rails で記述されている
Scarab
バグではなく更に包括的な問題追跡システムとして有名
影舞
日本で開発されており文字コードなどの不安がない
第3章
Trac の導入と利用方法
Trac はまだ開発途上のため,導入には少しコツが必要です.また,Trac の利用方法についても直感的ではないため,
利用についても慣れが必要になります.ここでは,Trac の導入からプロジェクトでの Trac の利用の流れについて紹介
します.
3.1 Trac の導入
Trac を導入するためには,システムが以下のような要件を満たしている必要があります.
• python
• python-support(0.7.1 かそれ以上)
本テキストで前提とするシステムでインストールを行うには以下のようにコマンドを実行します.
$ sudo apt-get install trac-ja-resource libapache2-mod-python
$ sudo a2enmod python rewrite
Trac には Python が必要ですので,インストール後は Apache の Python モジュールを有効にします.必要がなく
なった場合には a2dismod を使用することでモジュールを外すことができます.
次に Trac の場所を設定します.今回は /trac にアクセスすると, /var/trac 以下を参照するように設定するため,
ディレクトリを作成しておきます.
$ sudo mkdir /var/trac
これを Apache の設定ファイルに記述します.今回は /etc/apache2/conf.d/trac に設定内容を記述することと
します.
# /etc/apache2/conf.d/trac
<Location /trac>
SetHandler mod_python
PythonHandler trac.web.modpython_frontend
PythonOption TracEnvParentDir /var/trac
PythonOption TracUriRoot /trac
</Location>
<LocationMatch "[[:alnum:]]+/login">
AuthType Basic
AuthName "Trac Authentication"
3.2 Trac と Subversion との連携
245
AuthUserFile /etc/apache2/trac.passwd
Require valid-user
</LocationMatch>
以上で設定が終了しました.最後に Apache を再起動して設定を有効にします.Apache の設定変更を有効にするに
は restart の他に reload も使用できます.
$ sudo /etc/init.d/apache2 restart
3.2 Trac と Subversion との連携
今回は Trac とバージョン管理システムの Subversion(第 9 回参照)を連携させます.まず,Subversion のリポジ
トリを作成します.リポジトリは以下のように設定して下さい.
$ sudo svnadmin create /var/svn/TestTrac
次に Trac の設定を行います.
$ sudo trac-admin /var/trac/TestTrac initenv
$ sudo trac-admin /var/trac/TestTrac wiki load
/usr/share/trac-ja-resource/trac/wiki/default-pages
最低限, Project Name と Path to repository は設定するようにしてください.例として以下のように設定して
いますので,適宜変更してください.
Project Name Trac Test
Path to repository /var/svn/TestTrac
最後に,ユーザの設定を行います.以下に示すコマンドは admin ユーザを作成するものです.ユーザ名とパスワー
ドは任意に設定してください.
$ sudo htpasswd -c /etc/apache2/trac.passwd admin
$ sudo trac-admin /var/trac/TestTrac permission add admin TRAC ADMIN
以上で Trac の設定が終了しました. http://localhost/trac/TestTrac にアクセスしてください.もちろん,外
部からアクセスする場合は localhost を IP アドレスに置き換えて下さい.
3.3 Trac の利用
3.3.1 Trac の機能
Trac では,作業や期限などを分割して登録することで,プロジェクト全体として運用を行うことができます.
コンポーネント(component) コンポーネントは開発プロジェクトの構成要素です.1 つの開発プロジェクトには複
数のサブプロジェクトが存在することが多く,サブプロジェクトおよびその目標をコンポーネントとして登録し
ます.Trac では複数のコンポーネントにまたがる作業を登録することはできないので,1 つの作業は必ず一意
のコンポーネント完成のために行われます.
第3章
246
Trac の導入と利用方法
マイルストーン(milestone) マイルストーンはコンポーネントの期限を示しています.作業はそれぞれ期限を設け
ていますが,それぞれの作業は相互に関係しあっている場合もあるため,それらの最終的な期限の区切りをマイ
ルストーンとして設定します.
チケット(ticket) 作業単位を表します.全ての作業はチケットを発行し,発行されたチケットの問題を解決する目
的で行うようにします.これにより,チケットの発行を伴わない作業を禁止することができ,開発に関わる全て
の作業を可視化することができるようになります.結果,作業の重複や手戻りを防ぐことができるため,開発の
効率化を図ることができます.
3.3.2 プラグインの利用
Trac には最小限の機能しか備わっていません.これは,プロジェクトの規模や開発環境によって必要な機能が変
わってくるからです.そのため,当該プロジェクトで必要とする機能はプラグインの形で導入します.ここでは,プロ
ジェクトの規模や開発環境に関わらず有用と思われるプラグインについて紹介します.
IniAdmin Trac の設定は, conf/trac.ini のファイルに記述します.当然, trac.ini ファイルは直接サーバ上で
操作するか,ssh などの遠隔ログインでファイルの読み書きをしなければなりません.しかし,サーバをサーバ
ルームにおいている場合やホスティングしている場合には直接操作することは難しいといえます.また,直接操
作することは他のシステムファイルを変更してしまう危険性もあります.そこで,設定ファイルをブラウザ上か
ら操作することを可能にするプラグインが IniAdmin です.これを利用することで,Web ブラウザ上から設定
の変更を行うことができます.また,遠隔ログインなどを行うためにはサーバ上に一定以上の権限を与える必要
がありますが,Trac 上から編集する場合には,サーバにアカウントを用意する必要はありません.バージョン
0.11 からは IniAdmin は標準で導入されていますが,それ以前のバージョンでは入っていないため注意が必要
です.
TracAccountManager Trac を利用する場合,ログインしなければ閲覧以外の機能は与えないのが一般的です.Trac
のユーザはベーシック認証もしくはダイジェスト認証によって管理されており,サーバ機上で操作(追加・削
除)する必要があります.そこで IniAdmin プラグイン同様に,これらユーザをブラウザ上から管理できる機能
を提供するプラグインが TracAccountManager です.これを利用することで,管理者さえいればどこからでも
ユーザの登録などができるようになります.
TracWebAdmin 作業成果であるコンポーネントや作業目標となるマイルストーンは,標準の状態では Web サーバ上
のコマンドから設定します.しかしながら,コンポーネントやマイルストーンは状況に応じて変更することが望
ましいといえます.そこで,IniAdmin や TracAccountManager と同様にこれらコマンドを Web ブラウザ上か
ら操作を可能にするプラグインが TracWebAdmin です.
以上のようなプラグインを用いることで,Trac を用いたバグ追跡や開発そのものの効率を大幅に向上させることが
できます.
このプラグインは以下のコマンドを実行することで導入できます.
$ sudo easy install http://trac-hacks.org/svn/iniadminplugin/0.11/
$ sudo easy install http://trac-hacks.org/svn/accountmanagerplugin/0.11/
また,設定ファイルに以下のように追記する必要があります.設定ファイルは Trac があるディレクトリ内の
conf/trac.ini です.ここまでに,ディレクトリ名などを変更していない場合は,/var/trac/TestTrac/conf/trac.ini
に存在します.
3.3 Trac の利用
247
[components]
iniadmin.* = enabled
acct_mgr.* = enabled
但し, components ディレクティブが存在する場合は,その下に記述するようにしてください.
3.3.3 Web ブラウザからの Trac の利用
前節までの設定により,これ以降はすべて Web ブラウザから利用できるようになります.そこで,Trac へのログイ
ンからコンポーネント,マイルストーン,そしてチケットの登録方法を紹介します.
第3章
248
Trac の導入と利用方法
Trac へのログイン
今回は TRAC ADMIN 権限のユーザでログインします.図 3.1 のように検索ボックスの下に Login のリンクがありま
す.このリンクから移動しようとすると,図 3.2 のようにダイアログでユーザ名とパスワードが聞かれますので,イン
ストール時に設定したユーザの情報を入力して下さい.
図 3.1 Trac へのログイン(1/3)
図 3.2 Trac へのログイン(2/3)
TRAC ADMIN 権限でログインした場合は,図 3.3 のように Admin (管理画面へのリンク)が現れます.
3.3 Trac の利用
249
図 3.3 Trac へのログイン(3/3)
第3章
250
Trac の導入と利用方法
Trac へのコンポーネントの追加
開発プロジェクトはコンポーネントによって構成されています.すべてのコンポーネントが完成して初めてプロジェ
クトが完了します.コンポーネントの編集を行うためには,図 3.4 のように左カラムのメニューから Components を選
択することで画面が遷移します.
図 3.4
コンポーネント編集画面
図 3.5 のように既存のコンポーネントを削除することも可能です.
図 3.5 コンポーネントの削除
また,コンポーネントを追加するには,図 3.6 のように右カラムのテキストボックスにコンポーネント名 (Name) と
責任者 (Owner) を入力し, Add ボタンを押すことで登録します.
図 3.7 のように無事に表示されれば成功です.
3.3 Trac の利用
251
図 3.6 コンポーネントの追加(1/2)
図 3.7 コンポーネントの追加(2/2)
第3章
252
Trac の導入と利用方法
Trac へのマイルストーンの追加
コンポーネントの期限はマイルストーンで設定します.コンポーネントが完成しないとプロジェクトは完了しないた
め,マイルストーンはすべて納期内に設定しなければなりません.マイルストーンも左カラムのメニューから移動でき
ます.基本的な操作はコンポーネントと同じで,図 3.8 のように削除を行うことができます.
図 3.8 マイルストーンの削除
また,追加する際は図 3.9 のように,マイルストーン名と期日を入力して下さい.
図 3.9 マイルストーンの追加(1/2)
正常に追加が行われると,図 3.10 のようになります.
3.3 Trac の利用
253
図 3.10
マイルストーンの追加(2/2)
第3章
254
Trac の導入と利用方法
Trac へのチケットの登録
チケットはコンポーネントの構成要素です.チケットがすべて完了しなければコンポーネントも完成しませんが,テ
ストのフェーズ,つまりバグの発見時にもチケットを登録するため,コンポーネントはテスト前に完成の状態になる場
合もあります.チケットはコンポーネントやマイルストーンとは異なり,標準の状態ではログインしたすべてのユーザ
に登録の権限が与えられています.図 3.11 のように上部のメニューから移動することでチケットを登録します.
図 3.11
チケット登録画面(1/2)
チケット登録の際には,図 3.12 のようにチケットタイトル,説明,担当者,優先度,対象コンポーネント,キーワー
ド,タイプ,マイルストーン,バージョンなどが設定可能です.
登録したチケットを閲覧するには,図 3.13 のように上部バーの View Tickets から移動します
チケットの閲覧時には,図 3.14 のように様々な検索フィルタが用意されていますが,ここでは例としてアクティブ
チケット,つまり Close されていないチケットの一覧を表示してみます.
登録されているチケットは,図 3.15 のように表示されます.
3.3 Trac の利用
255
図 3.12
チケット登録画面(2/2)
図 3.13
チケット確認画面(1/3)
第3章
256
図 3.14
チケット確認画面(2/3)
図 3.15
チケット確認画面(3/3)
Trac の導入と利用方法
第 10 回 演習課題
目標
Trac の使い方を習得します.
まず,ソフトウェア作成のためのコンポーネント,マイルストーン,チケットを登録して下さい.次に,登録し
たチケットを閲覧・ダウンロードして下さい.
課題 1 トラックへのチケットの登録と変更
1–1
自動車を動かすためのソフトウェアを作成するため Trac を利用することになりました.次のコンポーネントを登録
して下さい.
• 前進モジュール
• 後進モジュール
• 右折モジュール
• 左折モジュール
1–2
次のマイルストーンを登録して下さい.
2009.12.01 前後の移動テスト
2010.01.01 左右の移動テスト
2011.02.01 試乗テスト
2011.03.01 完成
1–3
対象とする自動車のコンポーネントで登録されたモジュールを完成させるため,様々なチケットを 20 以上登録して
下さい.仕様は各自で任意に定めて下さい.
それ以外にも,エンジンの回転数制御,ギアチェンジなどの基本機能から,バグのチケットなども登録してみて下さ
い.また,1.2 節で示したようにチケットの状態を変化させてみて下さい.
課題 2 チケットの閲覧とダウンロード
2–1
登録したチケット一覧を図 3.16 のように, All Tickets By Milestone (Including closed) を選択して表示
させ,下部のメニューにある Comma-delimited Text 形式でファイルをダウンロードして下さい.
第3章
258
図 3.16 チケット一覧を出力
第 10 回 演習課題
参考文献
[1] Mozilla Foundation, http://www.mozilla.org/
[2] Bugzilla.org http://www.bugzilla.org/doc
第 11 回
PHP の特徴と埋め込みプログラミング
PHP の概要と特徴について触れ,PHP の動作,ライセンス形態,代表的な利用方法などを紹
介します.また基本的なプログラミングができるように,変数,演算子,制御構文について説
明し,PHP を特徴付ける「埋め込みプログラミング」を解説します.演習では,簡単な埋込プ
ログラミングと,HTML フォームの作成を行い,PHP を用いた Web プログラミングについて
学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
PHP の概要
PHP(PHP: Hypertext Preprocessor)とは,Web 開発に適したオープンソースの汎用スクリプト言語です.開
始タグと終了タグで挟まれたコードのみを実行できるため,さまざまな形式のファイルに記述することができ,主に
HTML ファイルに記述されます.多くの基本構文は C 言語,Java,Perl が基になっているため,これらの言語を習得
済みであれば,動的な Web ページや Web アプリケーションを簡単に作成することができます.また,多くの Linux
ディストリビューションでは,PHP が標準でバンドルされているためすぐに使用することができます.
1.1 歴史
1995 年,Rasmus Lerdorf は PHP/FI (Personal Home Page/Forms Interpreter) という,C 言語で書かれたソフ
トウェアのソースコードを公開しました.このソフトウェアは,サーバの助けを借りずにログ情報をリアルタイムに見
たり,データベースにアクセスしたりすることができるものでした.その後,多くのユーザが改良,バグの修正に取り
組み,PHP/FI 2.0,PHP 3, そして PHP 4 を経て,オブジェクト指向などの多くの機能が追加,改良された PHP 5
が 2004 年 7 月に公開されています.
1.2 特徴
PHP は C 言語を使って書かれており,PHP 言語の開発元で完全なソースコードが配布されています(http:
//www.php.net/downloads.php).また,同じく C 言語で書かれた拡張モジュールと,PHP で書かれたライブラリ
がそれぞれのリポジトリで公開されているため,ただ与えられたものでスクリプトを組むだけではなく,PHP の開発
に参加することもできます.
なお,PHP の大きな特徴である埋め込みプログラミングについては第 3 章にて説明します.
1.2.1 拡張モジュールとライブラリ
PHP は内部構造がモジュール化されており,変数や配列などを扱う基本的のものから,データベースや PDF と連携
するためのモジュールなどが用意されています.また,PECL (PHP Extension Community Library) という PHP の
拡張モジュールを蓄積したリポジトリがあり,ここからモジュールをダウンロード,インストールすることで,HTTP
や Subversion との連携,統計関数の利用などが容易になります.
また,PHP には PEAR (PHP Extension and Application Repository) という公式リポジトリもあり,パッケージ
化されたライブラリやフレームワークが公開されています.PEAR プロジェクトでは標準コーディング規約の作成も
行われているため,自分の書いたスクリプトの公開を考えているなら,目を通しておく必要があります.なお,本テキ
ストに出てくるスクリプトは,標準コーディング規約に従っています.
1.3 動作環境
263
1.3 動作環境
1.2 節でも述べたとおり,PHP は C 言語で書かれているため,Linux,Mac OS X などの Unix 系や,Microsoft
Windows といった OS で使用することができます.さらに,多くの Linux ディストリビューションでは,パッケージ
化された PHP が用意されています.
また,Apache などの Web サーバにもモジュールが提供されているため,PHP と Web サーバ,Web ブラウザの 3
つを用意すればすぐに開発を始めることができます.
1.4 ライセンス形態
PHP はオープンソースであるため,個人,商用を問わず自由に使って開発することができます.ただし,著作権表示
やライセンスの条件項目,免責条項を記載することなどの条件を満たす必要があります.詳しくは,ライセンス(http:
//www.php.net/license/)を確認して下さい.なお,PHP のライセンスはオープンソース グループ・ジャパンで日本
語参考訳が公開されています(http://sourceforge.jp/projects/opensource/wiki/licenses/PHP License).
第2章
基本構文と,主な型/演算子/制御構文
本章では,PHP でプログラミングを行うために必要な基本構文を説明します.概要でも述べたとおり,PHP の記述
方法は,C 言語と Java, Perl が基になっています.そこで,PHP のサンプルソースには,必要に応じて似た動作をす
る C 言語や Java のソースコードを併記しています.
なお,本テキストで C 言語の規格は C89 とします.
2.1
基本構文
PHP には開始タグ( <?php )と終了タグ( ?> )があり,これらのタグに囲まれた部分のみが,PHP のコードとし
て実行されます.HTML ファイルなど,ほかの形式のドキュメントに PHP のコードを記述する場合は,タグの書き
忘れに注意して下さい.また,C 言語と同じように,各命令の最後にはセミコロンをつけます.コメントに関しては,
C 言語と同じものを使うことができます.
以下のスクリプトは,
「Hello World!!」と表示するスクリプトです. print() は,C 言語と違って関数ではなく言語
構造であるため,括弧がなくても同じ結果になります.このスクリプトにブラウザからアクセスすると,図 2.1 のよう
な動作結果が得られます.
<?php
// 「Hello World!!」と出力
print "Hello World!!";
?>
また,似た動作をする C 言語のソースコードを,参考に記載します.
#include <stdio.h>
int main(void) {
// 「Hello World!!」と出力
printf("Hello World!!");
return 0;
}
開始タグには,短縮形など他の記述方法もありますが,OS や設定の違いによって認識されないことがあるため,本
テキストで紹介したタグを使用して下さい.XML や XHTML の標準規約でもこの記述方法が標準規格となっていま
す.また,コメントには Perl やシェルで使う番号記号「#」も使うことができますが,標準コーディング規約で使うべ
2.2 変数
265
きではないとされています.
図 2.1 Hello World の動作結果
変数
2.2
PHP のスカラー型には,論理型(boolean),整数(integer),浮動少数点数(float),文字列(string)があります
が,論理型,整数,浮動小数点数は C 言語,または Java と同じように使えるため,ここでは述べず,変数の宣言と,
文字列の代入について説明します.
PHP の変数は,Perl と同じく変数名の前にドル記号「$」をつけて,以下のスクリプトのように宣言します.文脈に
応じて型を選択してくれるため,変数の型を宣言する必要はありません.また,キャスト変換も行うことができます.
<?php
$b = TRUE;
// 論理型
$i = 1;
// 整数
$f = 1.0;
// 浮動小数点数
$s = "abc";
// 文字列
$i2f = (float)$i; // 整数から浮動小数点数にキャスト変換
?>
また,似た動作をする C 言語のソースコードを,参考に記載します.
int main(void) {
int
b
= 1;
// 規格 C89 に論理型はない
int
i
= 1;
// 整数
= 1.0;
// 浮動小数点数
float f
char
s[] = "abc";
// 文字列
第 2 章 基本構文と,主な型/演算子/制御構文
266
float i2f = (float)i; // 整数から浮動小数点数にキャスト変換
return 0;
}
C 言語や Java で文字列を代入する時は,ダブルクオート「”」でくくりましたが,PHP ではダブルクオートのほか
に,シングルクオート「’」でくくることもできます.両者の大きな違いは,文字列に含まれる変数の扱いです.なお,
文字列の長さを考慮する必要はなく,どれだけ長い文字列でも代入することができます.
ダブルクオートでくくる場合は,文字列の中に変数(たとえば $var )が含まれる時,変数の値を出力します.ただ
し 2.5.2 節のスクリプトのように,変数名の後から続けて文字を出力する時は,変数を波括弧「{}」でくくる必要があ
ります.
また,多くのエスケープシーケンスを使うことがでますが,改行などのエスケープシーケンスは,HTML ソースに
しか反映されないため,ブラウザ上で改行したい場合は,「 <br /> 」などの HTML タグを出力して下さい.
次にシングルクオートでくくる場合は,文字列の中に変数が含まれる時,変数の名前をそのまま出力します.また,
文字列中でシングルクオートを出力する時は「\’」とし,文字列の最後にバックスラッシュを出力する時は,
「\\」とす
る必要があります.
以下のスクリプトは,1 行目で変数の値を,2 行目で変数名を出力するものです.動作結果は図 2.2 のようになりま
す.また,エスケープシーケンスの一覧を表 2.1 に示します.
<?php
$name = "Mirai Taro";
// 「My name is Mirai Taro」を出力
print "My name is $name";
// ブラウザ上で改行
print "<br />";
// 「My name is $name」を出力
print ’My name is $name’;
?>
また,似た動作をする C 言語のソースコードを,参考に記載します.
#include <stdio.h>
int main(void)
{
char name[] = "Mirai Taro";
// 「My name is Mirai Taro」を出力
printf("My name is %s", name);
2.2 変数
267
// 改行
printf("\n");
// 「My name is $name」を出力
printf("My name is $name");
return 0;
}
図 2.2 文字列の動作結果
表 2.1 エスケープシーケンス
記号
意味
\n
改行
\r
文頭に戻る
\t
水平タブ
\v
垂直タブ
\f
改ページ
\\
バックスラッシュを出力
\$
ドル記号を出力
\”
ダブルクオートを出力
第 2 章 基本構文と,主な型/演算子/制御構文
268
2.3
配列
PHP の配列は,C 言語や Java と同じように扱うことができますが,配列の作成には array() を使用します.また,
連想配列という,文字列を添え字とした配列も使用できます.
2.3.1
配列の作成
PHP の配列は,array() で作成します.array() には,「添え字 => 値」という引数を,コンマ「,」で区切っていく
つも渡すことができます.しかし,添え字を省略した場合,添え字は 0 から始まり,1 ずつ増えて値が代入されていき
ます.また,一度でも添え字を指定し,ほかの引数で添え字を省略した場合,今までに指定されたなかでもっとも大き
な添え字から始まり,1 ずつ増えて値が代入されていきます.
以下のスクリプトは,配列に値を代入し,出力するものです.print r 関数は,配列や変数をわかりやすい形式で出
力するもので,特に配列の添え字と値の関係を見やすく表示することができます.この時,print r 関数を HTML タグ
で整形済みテキストとしてブラウザ出力すると,より見やすくなります.動作結果は,図 2.3 のようになります.
<?php
// 配列の作成
$arr1 = array(2, 3, 5, 7, 11);
// $arr1 = array(0 => 2, 1 => 3, 2 => 5, 3 => 7, 4 => 11); と同じ
// すべて出力
for($i = 0; $i < 5; $i++)
print "$arr1[$i]";
print "<br />"; // 改行
// 添え字が 0 の値に代入
$arr1[0] = 0;
// すべて出力
for($i = 0; $i < 8; $i++)
print "$arr1[$i]";
print "<br />"; // 改行
// 途中から値を代入することもできる
$arr2 = array(6 => 3, 1 => 2.2, 4);
print_r($arr2);
?>
2.3 配列
269
図 2.3
2.3.2
配列の動作結果
連想配列
C 言語や Java において,配列の添え字は整数だけでしたが,PHP では文字列を添え字とすることもできます.この
ように,文字列を添え字とした配列のことを連想配列といいます.この場合も,array() や配列の扱い方は変わりませ
んが,array() に引数として渡す時や,配列の値にアクセスする時は,ダブルクオート,またはシングルクオートでく
くらなくてはなりません.
以下のスクリプトで,配列( $arr )は「eleven」,
「twelve」,
「thirteen」という添え字の要素に,それぞれ 11,12,
13 という値が代入されています.動作結果は,図 2.4 のようになります.
<?php
// 配列を作成
$arr_assoc = array("eleven" => 11, "twelve" => 20, "thirteen" => 13);
// 添字が"twelve"の値に,12 を代入する
$arr_assoc["twelve"] = 12;
// 配列の値を表示する
print "<pre>";
print_r($arr_assoc);
print "</pre>";
?>
第 2 章 基本構文と,主な型/演算子/制御構文
270
図 2.4
連想配列の動作結果
2.4 演算子
C 言語と Java の演算子は,PHP でも同じように使うことができるため,ここでは PHP で初めて見ることになる演
算子で,よく使われるものについて解説します.今回挙げなかった演算子の中には,エラー制御演算子や実行演算子,
型演算子があります.
論理演算子
2.4.1
PHP の論理演算子には,論理積と論理和のほかに排他的論理和が追加されており,
「 xor 」として条件文に使うこと
ができます.また,「 && 」,「 || 」の代わりに,「 and 」,「 or 」と書くこともできます.
以下のスクリプトは,条件式が真の時「真」と出力し,偽の時「偽」と出力するものです.動作結果は,図 2.5 のよ
うになります.
<?php
$true
= TRUE;
// 真
$false = FALSE; // 偽
if ($true xor $false) { // 片方のオペランドのみが真であるため,条件式は真
print "真";
} else {
print "偽";
}
if ($true and $false) { // 両方のオペランドがともに真でないため,条件式は偽
print "真";
2.4 演算子
271
} else {
print "偽";
}
if ($true or $false) {
// 片方のオペランドが真であるため,条件式は真
print "真";
} else {
print "偽";
}
?>
図 2.5 論理演算子の動作結果
表 2.2
2.4.2
論理演算子
記号
意味
&&, and
論理積
||, or
論理和
xor
排他的論理和
!
否定
比較演算子
C 言語や Java の条件式で,両方のオペランドが等しいか調べる比較演算子に「==」を使用しましたが,オペラン
ドの値しか評価しないため,整数と浮動小数点数を比較しても,値が等しければ真になります.しかし PHP では,値
だけではなく型まで比較することができます.「===」は,値も型も等しい時条件式は真になり,「!==」は値または
第 2 章 基本構文と,主な型/演算子/制御構文
272
型が異なる時,条件式は真になります.つまり,
「 1 === 1 」は両オペランドの値が等しく,型も整数ですので,条件
式は真になりますが,
「 1 === 1.0 」は両オペランドの値が等しくても,左のオペランドが整数,右のオペランドが浮
動小数点数と異なっているため,条件式は偽になります.そして,「 1 !== 1.0 」は両オペランドの型が異なってい
るため,条件式は真になりますが,
「 1 !== 1 」は値も型も両オペランドで等しいため,条件式は,偽になります.ま
た,「 <> 」を「 != 」と同じように使うことができます.
以下のスクリプトは,条件式が真の時「真」と出力し,偽の時「偽」と出力するものです.動作結果は,図 2.6 のよ
うになります.また,新しく出てきた演算子の真理値表を,表 2.3,表 2.4 に示します.
<?php
if (1 === 1) {
// 値も型も等しいため,条件式は真
print "真";
} else {
print "偽";
}
if (1 === 1.0) { // 値は等しいが型が異なるため,条件式は偽
print "真";
} else {
print "偽";
}
if (1 !== 1) {
// 値も型も等しいため,条件式は偽
print "真";
} else {
print "偽";
}
if (1 !== 1.0) { // 値は等しいが型が異なるため,条件式は真
print "真";
} else {
print "偽";
}
if (1 <> 1) {
print "真";
} else {
print "偽";
}
?>
// 値が等しいため,条件式は偽
2.4 演算子
273
図 2.6 比較演算子の動作結果
表 2.3
比較演算子「 === 」の真理値表
値が等しい
型が等しい
結果
偽
偽
偽
偽
真
偽
真
偽
偽
真
真
真
表 2.4
比較演算子「 !== 」の真理値表
値が等しい
型が等しい
結果
偽
偽
真
偽
真
真
真
偽
真
真
真
偽
第 2 章 基本構文と,主な型/演算子/制御構文
274
文字列演算子
2.4.3
C 言語では strcat 関数を使い,Java では加算演算子を使うことで文字列を結合することができました.PHP では,
結合演算子「.」を使い,文字列を結合します.また,文字列を追加する場合は,代数演算と同じように「.=」を使うこ
とができます.
以下のスクリプトは,1 行目に「FUTURE UNIVERSITY」,2 行目に「FUTUREUNIVERSITY-HAKODATE」
と出力するものです.動作結果は,図 2.7 のようになります.
<?php
$str1 = "FUTURE";
$str2 = " UNIVERSITY";
// $str3 に,$str1 と$str2 を結合して代入
$str3 = $str1.$str2;
// $str3 に,改行タグを結合して出力
print $str3."<br />";
// $str3 の最後に,「-HAKODATE」を結合
// $str3 = $str3."-HAKODATE"; と同じ
$str3 .= "-HAKODATE";
print $str3;
?>
また,似た動作をする Java のソースコードを,参考に記載します.
package helloWorld;
public class HelloWorld
{
public static void main(String[] args)
{
String a = "FUTURE";
String b = " UNIVERSITY";
// $c に「FUTURE UNIVERSITY」を代入
String c = a + b;
System.out.println(c);
// $c に「-HAKODATE」を追加
c += "-HAKODATE";
2.4 演算子
275
System.out.println(c);
}
}
図 2.7
2.4.4
文字列演算子の動作結果
配列演算子
2 つの配列の値が等しいか調べる時,C 言語や Java では比較演算子を使うことができませんでしたが,PHP では使
用できるようになっています.大まかな意味は変数の時と変わりませんが,値だけではなく添え字も関わってくるた
め,この節でもう一度まとめます.
「==」は,添え字と値の組み合わせがすべて等しい時,条件式は真になり,「!=」は添え字と値の組み合わせが 1 つ
でも異なる時,条件式は真になります.また,
「===」は,添え字と値の組み合わせが等しく,さらに型と要素の順番
も等しい時,条件式は真になり,
「!==」は添え字と値の組み合わせが異なるか,型や要素の順番が異なる時,条件式は
真になります.ただし,ある添え字を片方の配列が持っていない時は,NULL と比較します.
さらに,加算演算子「+」で配列同士を結合することもできます.この時,左のオペランドの配列にない添え字の値
は代入されますが,すでに値が代入されている場合は代入せず,左のオペランドの配列の値が残ります.
以下のスクリプトは,条件式が真の時「真」と出力し,偽の時「偽」と出力するものです.print r 関数で出力された
配列( $arr4 )には添え字が 1,3,5,0,2,の要素にそれぞれ,0,1,2,3,5 の値が代入されています.動作結果
は,図 2.8 のようになります.また,配列演算子の真理値表を,表 2.5,表 2.6,表 2.7,表 2.8 に示します.
<?php
$arr1 = array(1 => 0, 3 => 1, 5 => 2);
$arr2 = array(5 => 2, 3 => 1, 1 => 0);
if ($arr1 == $arr2) { // 添字と値の組み合わせがすべて等しいため,条件式は真
第 2 章 基本構文と,主な型/演算子/制御構文
276
print "真";
} else {
print "偽";
}
if ($arr1 === $arr2) { // 添字と値の組み合わせがすべて等しいが,要素の順番が異なるため,条件式は偽
print "真";
} else {
print "偽";
}
$arr3 = array(0 => 3, 1 => 4, 2 => 5);
// $arr3 の添字が 0,2 の要素は代入されるが,添字が 1 の要素は$arr1 に存在しているため,代入されない
$arr4 = $arr1 + $arr3;
print "<pre>";
print_r($arr4);
print "</pre>";
?>
図 2.8 配列演算子の動作結果
2.4 演算子
277
表 2.5
配列演算子「 == 」の真理値表
添え字と値の組み合わせがすべて等しい
型や要素の順番がすべて等しい
結果
偽
偽
偽
偽
真
偽
真
偽
真
真
真
真
表 2.6
配列演算子「 != 」の真理値表
添え字と値の組み合わせがすべて等しい
型や要素の順番がすべて等しい
結果
偽
偽
真
偽
真
真
真
偽
偽
真
真
偽
表 2.7
配列演算子「 === 」の真理値表
添え字と値の組み合わせがすべて等しい
型や要素の順番がすべて等しい
結果
偽
偽
偽
偽
真
偽
真
偽
偽
真
真
真
表 2.8
配列演算子「 !== 」の真理値表
添え字と値の組み合わせがすべて等しい
型や要素の順番がすべて等しい
結果
偽
偽
真
偽
真
偽
真
偽
偽
真
真
偽
第 2 章 基本構文と,主な型/演算子/制御構文
278
制御構文
2.5
if 構文や for 構文など,C 言語と Java の制御構文を,PHP でも同じように使うことができます.よって,ここで
は PHP で初めて見るであろう制御構文で,よく使われるものについて解説します.今回挙げなかった制御構文には,
declare 構文や,include 構文,require 構文などがあります.
また,PHP の制御構文のなかで,if 構文,while 構文,for 構文,switch 構文,そして後述する foreach 構文には,C
言語や Java と違った書き方も用意されています.今まで,制御構文で実行する式は波括弧「{}」でくくっていました.
しかし,PHP ではコロン「:」と「 endi; 」,
「 endwhile; 」
,
「 endfor; 」,
「 endforeach; 」
,
「 endswitch; 」でく
くることもできます.動作はどちらも変わりませんが,HTML ファイルにスクリプトを埋め込む場合や,複数の構文
の入れ子になる場合などは,後者の書き方をしたほうがスクリプトが読みやすくなります.
以下のスクリプトは FizzBuzz と呼ばれ,3 の倍数で「Fizz」,5 の倍数で「Buzz」,3 と 5 の公倍数で「FizzBuzz」
と出力し,それ以外の数はそのまま表示するものです.動作結果は図 2.9 のようになります.
<?
// C 言語や Java のような書き方
for ($i = 1; $i <= 30; $i++) {
if ($i%3 != 0 && $i%5 != 0) {
print $i;
} else {
if ($i%3 == 0) {
print "Fizz";
}
if ($i%5 == 0) {
print "Buzz";
}
}
print " ";
}
?>
また,こちらのスクリプトでは波括弧を使っていませんが,同じ動作をします.
<?
// PHP で用意されている別の書き方
for ($i = 1; $i <= 30; $i++): // for 構文の始まり
if ($i%3 != 0 && $i%5 != 0): // if else 構文の始まり
print $i;
else:
if ($i%3 == 0): // 1 つ目の if 構文の始まり
print "Fizz";
2.5 制御構文
279
endif;
// 1 つ目の if 構文の終わり
if ($i%5 == 0): // 2 つ目の if 構文の始まり
print "Buzz";
endif;
// 2 つ目の if 構文の終わり
endif; // if else 構文の終わり
print " ";
endfor; // for 構文の終わり
?>
図 2.9 FizzBuzz の動作結果
第 2 章 基本構文と,主な型/演算子/制御構文
280
switch 構文
2.5.1
switch 構文は C 言語と Java のように使うことができますが,PHP では文字列も変数として扱われるため,条件式
に使うことができます.
以下のスクリプトは,変数 color の値が「red」であるため,
「赤」と出力されます.動作結果は,図 2.10 のようにな
ります.
<?php
$color = "red";
switch($color) {
case "red":
print "赤<br />";
break;
case "green":
print "緑<br />";
break;
case "blue":
print "青<br />";
break;
}
?>
図 2.10 switch 構文の出力結果
2.5 制御構文
281
foreach 構文
2.5.2
配列の要素を最初からすべて順番に使用したい時,foreach 構文を使うと配列を単純に扱うことができます.foreach
構文は,
「 foreach($array as $value){ /* 処理 */ } 」,または「 foreach($array as $index => $value){
/* 処理 */ } 」と記述します.
前者はまず,1 つ目の要素の値を変数 value に代入し,波括弧の中の処理を実行します.次に,2 つ目の要素の値を変
数 value に代入し,波括弧の中の処理を実行する,という動作を,3 つ目以降も同じように行います.また,後者は配
列の要素の値だけではなく,添え字を変数 index に代入して処理を行います.なお,foreach 構文を終了した後も,変
数 value は配列の最後の要素を割り当てられたままになるため, unset() で割り当てを解除しておくのが望まれます.
以下のスクリプトは,まず配列の要素の値を 3 行で出力し,続いて添え字と要素の値を 3 行で表示するものです.な
お,変数 index は続いて文章が記述されているため, 2.2 節で述べたように変数と文章の区別をつけるために波括弧で
くくっています.動作結果は,図 2.11 のようになります.
<?php
$arr = array("red" => "赤", "green" => "緑", "blue" => "青");
// 要素の値のみを出力する
foreach ($arr as $value) {
print "$value<br />";
}
// 添字と要素の値を出力する
foreach ($arr as $index => $value) {
print "{$index}の値は$value<br />";
}
// 割り当ての解除
unset($value);
?>
282
第 2 章 基本構文と,主な型/演算子/制御構文
図 2.11 foreach 構文の出力結果
2.6 デバッグ
2.6
283
デバッグ
C 言語や Java はコードに文法の不備があると,遅くともコンパイル時に気づくことができます.しかし,PHP はブ
ラウザやコンソールで実行するまでエラーや警告が出力されません.本節では,エラーが出力されるバグと,エラーが
出力されないバグのデバッグ方法を説明します.
2.6.1
Parse error
パースエラーとは,コードに文法的なバグがある時に出力され,バグの原因と,バグがあると思われる場所を出力し
ます.図 2.12 のパースエラーは,以下のスクリプトをブラウザで実行した時に出力されたものです.
<?php
s = "Hello World!!"; // エラー発生
print $s;
?>
図 2.12 パースエラーの出力結果
まず,
「 syntax error, unexpected ’=’ 」とは,文法が間違っており,等号「=」の使い方を誤っている,という
意味になります.また,「 in /var/www/syntax error.php on line 2 」では,syntax error.php の 2 行目でパー
スエラーが出力されたと分かります.このように,「Parse error: 原因 in 出力されたファイル on 出力された行」と出
力されます.ただし,波括弧 {」の閉じ忘れをしてしまった時や,セミコロン「;」を付け忘れた時などは,必ずしも
パースエラーで示された行にバグがあるとは限らないため注意して下さい.
先ほどのスクリプトの 2 行目を見てみると,変数名を宣言する時にドル記号「$」を付け忘れていることから,変数
ではないものに文字列を代入しようとしたために,パースエラーが発生したと分かります.
第 2 章 基本構文と,主な型/演算子/制御構文
284
2.6.2
エラーが出力されないバグ
文法があっていても,考え方の間違いや,思い込みによって期待した結果が得られないこともあります.このよう
な時に便利な,変数や配列の情報を詳しく表示する var dump 関数をここで紹介します.var dump 関数は,論理型,
整数,または浮動少数点数の変数を引数として与えると,「型 (値)」と出力され,文字列の変数を引数とした時は,
「string(文字列の長さ)”文字列”」と出力されます.また,配列を引数とすると,添え字と値の関係も分かりやすく表示
されます.この時 print r 関数と同じように,var dump 関数を HTML タグで整形済みとしてブラウザ出力すると,よ
り見やすくなります.
以下のスクリプトは,print() を使うとすべて「1」と出力される 4 つの変数を,型も分かるように出力しています.
また,2 つ目の var dump 関数では配列の添え字と要素の値を分かりやすく出力しています.動作結果は,図 2.13 の
ようになります.
<?php
$b = TRUE; // 論理型
$i = 1;
// 整数
$f = 1.0;
// 浮動小数点数
$s = "1";
// 文字列
// すべて「1」と出力される
print "$b, $i, $f, $s";
// 「型 (値)」,または「string(文字列の長さ) "文字列"」と出力される
print "<pre>";
var_dump($b, $i, $f, $s);
// 配列の添字と要素の値の関係もわかりやすく出力する
$arr = array($b, $i, $f, $s);
var_dump($arr);
print "</pre>";
?>
2.6 デバッグ
285
図 2.13 var dump 関数の出力結果
第3章
埋め込みプログラミング
ある言語で書かれたソースコードに記述することができる,別の言語のことを「埋め込み型言語」と言います.
HTML ファイルの中にスクリプトを書くことができる PHP や JavaScript, eRuby のほかにも,C 言語や Java のソー
スコードで使用することができる SQL なども埋め込み型言語です.そして,埋め込み型言語を用いて,別の形式の
ファイルにスクリプトを書き込む,つまり埋め込むことを「埋め込みプログラミング」と言います.特に,HTML ファ
イルに PHP のスクリプトを埋め込むことで,動的な Web ページを容易に作成することができます.
本章では,HTML ファイルに PHP のスクリプトを埋め込む方法を解説します.
HTML ファイルに PHP スクリプトを埋め込む
3.1
PHP において,開始タグと終了タグに挟まれた部分以外は無視されるため,HTML タグなどで特別な書き方が発生
することはありません.ただし,PHP のスクリプトを書き込む際は,拡張子を「.php」として下さい.これから具体
例を用いながら,PHP のスクリプトを埋め込む方法を説明します.
まず,以下に示すものが PHP スクリプトを埋め込まない HTML のファイルです.動作結果は図 3.1 のようになり
ます.
<html>
<head>
<title>Hello World!!</title>
</head>
<body>
<b>Hello World!!</b>
</body>
</html>
3.1 HTML ファイルに PHP スクリプトを埋め込む
287
図 3.1 PHP スクリプトを埋め込まない Hello World の出力結果
また,以下に示すものが PHP のスクリプトを埋め込んだ,PHP のファイルです.動作結果は,PHP スクリプトを
埋め込まない時と変わりません.
<html>
<head>
<title>Hello World!!</title>
</head>
<body>
<?php
print "<b>Hello World!!</b>";
?>
</body>
</html>
一見,PHP の開始タグから終了タグまでそのまま出力されそうに思えますが,実際には print() によって,「Hello
World!!」だけが太字で出力されます.この例を見て分かるとおり,PHP のスクリプトを HTML に埋め込んだ場合,
PHP のスクリプトがそのまま出力されることはありません.
次に,スクリプトの途中で,HTML の記述が長くなる時は print() を使ってすべて出力するよりも,スクリプトを複
数に分けて埋め込む方が効率よく記述できることがあります.
以下のスクリプトは,青色の文字でループの回数を 0 回から 4 回まで数えて出力します.動作結果は図 3.2 のように
なります.
<html>
<head>
<title>スクリプトを分割する</title>
第3章
288
埋め込みプログラミング
</head>
<body>
<?php
$color = "blue";
for ($i = 0; $i < 5; $i++) { // ループ開始
?>
<!-- 文字の色と,ループの回数を埋め込む --!>
<font color="<?php print $color; ?>">
ループは<?php print $i; ?>回目です.</font><br />
<?php
} // ループ終了
?>
</body>
</html>
図 3.2
スクリプトを分割した出力結果
以下のスクリプトでどのような処理が行われているかをそれぞれの部分に分けて解説します.まずは,変数 color の
宣言と for 構文だけを抜き出してみます.
<?php
$color = "blue";
for($i = 0; $i < 10; $i++){ // ループ開始
?>
<?php
} // ループ終了
3.1 HTML ファイルに PHP スクリプトを埋め込む
289
?>
まず,変数 color には「blue」という文字列を代入して宣言しています.そして次の行で,for 構文が始まっています
が,その直後に終了タグがあり,スクリプトは終わっています.C 言語や Java の感覚だとエラーを出力するように見
えますが,さらに読み進めていくと,再び開始タグが現れ,波括弧が for 構文を閉じ,終了タグが記述されています.
このように PHP のスクリプトは,一度終了タグでスクリプトを閉じたとしても,また開始タグを書くことでスクリプ
トの続きを記述していくことができます.
次に,for 構文の中の処理を抜き出してみます.
<font color="<?php print $color; ?>">
ループは<?php print $i; ?>回目です.
</font><br />
まず,HTML の font タグは,文字のフォントや色,大きさなどを指定するタグです.ここで,color 属性の色を指
定するところで変数 color の値,つまり「blue」という文字列が出力されているため,color 属性に青色を指定すること
ができます.また,出力する文字列の中で変数 i の値が出力され,ループの回数を数えています.
最後に,このファイルをブラウザで開いた時の HTML ソースを記載します.これにより,ブラウザがこのスクリプ
トをどのように解釈しているかを確認することができます.
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>スクリプトを分割する</title>
</head><body>
<!-- 文字の色と,ループの回数を埋め込む -->
<font color="blue">ループは 0 回目です.</font><br>
<!-- 文字の色と,ループの回数を埋め込む -->
<font color="blue">ループは 1 回目です.</font><br>
<!-- 文字の色と,ループの回数を埋め込む -->
<font color="blue">ループは 2 回目です.</font><br>
<!-- 文字の色と,ループの回数を埋め込む -->
<font color="blue">ループは 3 回目です.</font><br>
<!-- 文字の色と,ループの回数を埋め込む -->
<font color="blue">ループは 4 回目です.</font><br>
<!-- 文字の色と,ループの回数を埋め込む -->
<font color="blue">ループは 5 回目です.</font><br>
<!-- 文字の色と,ループの回数を埋め込む -->
<font color="blue">ループは 6 回目です.</font><br>
<!-- 文字の色と,ループの回数を埋め込む -->
<font color="blue">ループは 7 回目です.</font><br>
<!-- 文字の色と,ループの回数を埋め込む -->
第3章
290
<font color="blue">ループは 8 回目です.</font><br>
<!-- 文字の色と,ループの回数を埋め込む -->
<font color="blue">ループは 9 回目です.</font><br>
</body></html>
埋め込みプログラミング
第4章
パッケージの使い方
本 章 で は ,HTML QuickForm を 例 に ,PEAR で 公 開 さ れ て い る ラ イ ブ ラ リ の 使 い 方 を 説 明 し ま す .
HTML QuickForm とは,HTML フォームに関する処理に便利なライブラリです.
4.1 HTML QuickForm のインストール
ライブラリはそれぞれパッケージにまとめられており,パッケージのインストールには PEAR インストーラを用い
ます.以下のコマンドを実行して,PEAR インストーラをインストールして下さい.
$ sudo apt-get install php-pear
次に,PEAR インストーラを使って HTLM QuickForm をインストールして下さい.
$ sudo pear install HTML QuickForm
これで,HTML QuickForm が使えるようになりました.
4.1.1 HTML QuickForm の使い方
以下のスクリプトはまず,テキストボックスと送信,取消ボタンを表示します.また,テキストボックスに文字を入
力し,送信ボタンを押すと,入力した値がそのままブラウザに出力されます.
<html>
<head>
<title>HTML_QuickForm</title>
</head>
<?php
//
// フォームの定義
//
// HTML_QuickForm の読み込み
require_once ’HTML/QuickForm.php’;
// HTML_QuickForm のインスタンスを生成
$form = new HTML_QuickForm(’htmlQF’, ’get’);
第 4 章 パッケージの使い方
292
// フォームに要素を追加
$form->addElement(’text’, ’name’, ’ 名前:’); // テキストボックス
$form->addElement(’submit’, null, ’ 送信’);
// 送信ボタン
$form->addElement(’reset’, null, ’ 取消’);
// 取消ボタン
// フォームに規則を追加
$form->addRule(’name’, ’ 名前を入力してください.’, ’required’, null, ’client’);
?>
<body>
<?php
// フォームの出力
$form->display();
// 規則の検証
if ($form->validate()) {
print htmlspecialchars($form->exportValue(’name’));
}
?>
</body>
</html>
上記のスクリプトを少しずつ抜き出しながら解説します.
require_once ’HTML/QuickForm.php’;
この行では,HTML QuickForm を使用するために必要なファイルを読み込んでいます.C 言語の「include」や,
Java の「import」と同じようなものだと考えても構いません.
$form = new HTML_QuickForm(’htmlQF’, ’get’);
この行では,HTML QuickForm クラスのインスタンスを生成しています.2 つ目の引数の「get」でデータの送信
形式を「GET」に指定し,サーバに送られるデータが見られるようにしていますが,デフォルトだと「POST」に設定
されるため省略することもできます.
$form->addElement(’text’, ’name’, ’ 名前:’); // テキストボックス
$form->addElement(’submit’, null, ’ 送信’);
// 送信ボタン
$form->addElement(’reset’, null, ’ 取消’);
// 取消ボタン
addElement 関数は,フォームにテキストボックスやテキストエリア,送信ボタンなどの要素を追加します.これら
の例だと,1 つ目の引数で追加する要素の種類を指定し,2 つ目で要素の名前,3 つ目で表示する文字列を設定してい
ますが,2 つ目以降は要素の種類によって渡す引数が変わる場合があるため,確認してから使用して下さい.
4.1 HTML QuickForm のインストール
293
$form->addRule(’name’, ’ 名前を入力して下さい.’, ’required’, null, ’client’);
addRule 関数は,フォームに検証規則を与えています.1 つ目の引数で規則を設定する要素の名前を指定し,2 つ目
が規則に違反した時に表示される文字列,3 つ目が規則の種類です.「required」とは,「要素の値が空ではない」とい
う規則です.なお,規則に文字列の長さなどの値が必要な時,4 つ目の引数でパラメータを指定しますが,「required」
の場合は必要ないため「null」としています.また,5 つ目の引数では規則の検証をサーバ側でするか,それともクライ
アント側でするかを指定しています.つまり,この例では「name という名前のテキストボックスの値は空ではない」
という規則をクライアント側で検証することになります.
$form->display();
display 関数は,addElement 関数で追加したフォームをブラウザに表示します.この関数を記述しないと定義した
フォームをブラウザで見ることができないため,書き忘れに注意して下さい.
if ($form->validate()) {
print htmlspecialchars($form->exportValue(’name’));
}
validate 関数は,addRule 関数で与えられた規則を検証し,フォームの要素が従っていれば TRUE,違反していれ
ば FALSE を返します.よって,この関数を条件式として if 構文を使用すれば,フォームの入力が正しい時だけ実行す
る処理を書くことができます.また,htmlspecialchars 関数では「&」など HTML の特殊文字をブラウザでそのまま
出力できる形式に変換し,exportValue 関数は引数で指定した名前の要素に入力された値を返しています.つまり,こ
こではテキストボックスに入力された値を,HTML の形式に直して表示しています.exportValue 関数で指定した名
前と,返される値は,ブラウザのアドレスバーに「名前=戻り値」と表示されているため,ここでも確認することがで
きます.
HTML QuickForm でテキストエリアや送信,取り消しボタン以外のフォームを使用する方法や,ほかのライブラリ
を使う方法は,PEAR Manual などで確認することができます.
第 11 回 演習課題
目標
埋め込みプログラミングを行います.
まず,スクリプトを作成し,ブラウザでの動作を確認して下さい.次に HTML QuickForm を用い,HTML フォー
ムを作成して下さい.
※ 発展は任意課題とします.余裕のある方は挑戦してみて下さい.
課題 1 埋め込みプログラミング
PHP のスクリプトを HTML に埋め込みます.HTML タグを使うことはできますが,ファイルの拡張子は php とし
て下さい.
1–1
2.1 節のスクリプトを作成し,Web ブラウザで「HelloWorld!!」と出力されることを確認して下さい.
1–2
「Hello World」を赤色,橙色,黄色,緑色,青色の順番で 5 行表示するスクリプトを作成し,Web ブラウザで確認
して下さい.動作結果は,図 4.1 のようになります.
2.3 節の配列や,2.5.2 節の foreach 構文を使用すると簡単にスクリプトを作ることができます.また,文字の色を変
える方法は,3.1 節のスクリプトを参考にすることができます.
課題 2 HTML QuickForm
HTML QuickForm を使い,HTML フォームを作成します.
2–1
本テキストの 4.1 節を参考にし,HTML QuickForm をインストールして下さい.
2–2
4.1.1 節のスクリプトを編集し,名前だけではなく本文も入力できるように,テキストエリアを追加して下さい.動
作結果は,図 4.2 のようになります.
発展
掲示板を作成して下さい.図 4.3 は,掲示板のシンプルな例です.
掲示板への書き込みや,過去の書き込みの出力を行う方法はいくつもありますが,名前と本文を csv 形式で管理する
方法は比較的簡単に実装することができます.ファイルの入出力を行う関数として,fopen 関数や fwrite 関数のように
C 言語と似た関数や,fgetcsv 関数というファイルから csv 形式として 1 行を読み込み,配列を返す関数などが用意さ
れています.この時,書き込みの保存や読み込みを行うファイルのパーミッションに気をつけて下さい.また,日本語
が文字化けしてしまう場合は,ダブルクオートでくくると解決することがあります.
295
図 4.1 課題 1-2 の出力結果
図 4.2
掲示板の作成例
第4章
296
図 4.3
掲示板の作成例
第 11 回 演習課題
参考文献
[1] The PHP Group, http://www.php.net/ (accessed 2009-7-20).
[2] Japan PHP Users Group, http://www.php.gr.jp/ (accessed 2009-7-20).
[3] The PHP Group, http://pear.php.net/ (accessed 2009-7-20).
[4] Keith Edmunds, http://www.midnighthax.com/quickform.php (accessed 2009-7-20).
第 12 回
Python の特徴と連想配列
Python の概要と特徴について触れ,Python の動作,ライセンス形態,代表的な利用方法など
を紹介します.また基本的なプログラミングができるように,型,演算子,制御構文などにつ
いて説明し,Python の特徴である簡潔で明解なプログラミングと連想配列について解説しま
す.演習では,Web ページから必要なデータを抽出(スクレイピング)するプログラムを作成
することにより,Python によるプログラミングの特徴を学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
Python の概要
Python は 1990 年代初頭に登場したオープンソースの汎用スクリプト言語の 1 つです.シンプルな文法と利便性の
高い標準ライブラリを数多く備えているため,生産性が高く,欧米では Perl と共に広く普及しています.用途は多種
多様であり,Web アプリケーションやデスクトップアプリケーション,コンピュータグラフィックスから Linux のイ
ンストーラなど,非常に広い範囲で利用されています.また,専門家でない人間でもプログラムを読みやすく,書きや
すいように配慮して設計されているため,非常に習得しやすく,プログラミング初心者の入門用としても最適な言語で
あると言われています.
1.1 歴史
1990 年,オランダにある Stichting Mathematisch Cetrum で Guido van Rossum 氏によって ABC と呼ばれる
言語の後継言語として生み出されました.Python という名前は,van Rossum 氏がファンであるイギリス BBC の
コメディ番組「Monty Python’s Flying Circus(空飛ぶモンティ・パイソン)」に由来しています.その後,いくつ
かのバージョンリリースを経て,2001 年 Python に関する知的財産を保有するための非営利組織 Python Software
Foundation (PSF) が立ち上げられました.そしてそこに参加する世界中の開発者と Python コミュニティメンバに
よって,下位互換性の維持を最大限に考慮しながら開発が継続されています. 2009 年 7 月現在での最新リリースは,
2.6.2 と 3.0.2 です.2.x 系までは下位互換性が保証されていますが,3.x 系からは一部互換性を破棄した仕様となって
おり,古い Python コードが動作しなくなる場合があります.
1.1.1 Python の設計思想と Python3000
Python の設計思想は「Zen of Python」として端的に表現されています.その中に以下のようなフレーズがあり
ます.
• ごちゃごちゃ難しいのより,白黒はっきりしてるのがいい (Explicit is better than implicit.)
• 間違えようのないやり方がひとつだけあるのがいいね (There should be one– and preferably only one –
obvious way to do it.)
Python は,とにかく「シンプル」に「誰でも分かりやすい」言語を目指して開発されてきました.同じ目的を達成す
る為の方法は複数ではなく常に 1 つになるように,Python は設計されています.そしてそれが誰にとっても分かりや
すく,単純明解であることが重視されています.Perl のように,1 つの目的を達成するためにたくさんの方法があり,
まるで魔法の呪文のような複雑なコードを書く必要はありません.暗黙より明示,複雑より単純,というのが Python
の基本的な思想です.
また,Python は過去のソフトウェア資産を最大限に活用できるよう,バージョンアップに際して下位互換性を保証
することを非常に重要視しています,そのため,開発者にとって明らかに有用で理にかなった仕様変更でも,互換性維
1.2 ライセンス形態
301
持のために破棄されるといった場合がたびたび発生していました.しかし,より一貫性のある理想の言語を目指すた
めに,下位互換性を崩す仕様変更が必要不可欠な状況であることは明白でした.そしてその理想の言語を目指すため
Python 3.0 の開発が始められることとなります.
Python 3000 という名前は,まだ Python が 1.5.2 であり,次期リリースバージョンである 1.6 の開発中だった 2000
年当時,その次にリリースされる予定だった Python 2.0 について van Rossum 氏が言及する形で初めて使用されまし
た.その由来は,次期バージョンがリリースされるまでにあと 1000 年はかかるという,当時 2000 年という年数にかけ
たシニカルなジョークだったのではないかとも言われています.実際,2.0 は政治的,マーケティング的な理由などか
ら理想とはほど遠い形で 2000 年末にリリースされることになるのですが,その後,理想的な仕様変更を含むバージョ
ンとなるであろう 3.0 については Python 3000,または Py3k と呼ばれ,開発や議論が進められることとなります.
1.2 ライセンス形態
Python の普及を推進するための非営利法人であり,数多くのスポンサー企業で構成されている Python Software
Foundation によって策定された GPL 互換ライセンスである「Python Software Foundation License」という独自の
ライセンス形態を持っています.このライセンスは,GPL とは異なり,変更したバージョンを配布する際に変更を
オープンソースにしなくても良いとされています.
1.3 代表的な利用方法
Python は汎用プログラミング言語であり,ソフトウェア開発の様々な場面で利用することができます.例えば,
Web プログラミングや GUI ベースのアプリケーション,CAD,3D モデリング,数式処理など幅広い分野で使用され
ています.あるいは,スクリプト言語としての特性から,従来は Perl やシェルスクリプトが主流だったシステム管理
用のスクリプトとして採用されることも多く, 大抵の Linux ディストリビューションには最初から Python インタプ
リタがインストールされています.また,その特性から他の言語と組み合わせて利用されることも多く,様々なソフト
ウェアに組み込まれています.
1.3.1 Python を利用した OSS
最も有名なものとしてプロジェクト管理ツールである「Trac」が挙げられます.その他にも以下のようなものがあり
ます.
• Web アプリケーションフレームワーク (Zope, Django, TurboGears, Pylons)
• CMS (Plone,MoinMoinWiki)
• バージョン管理システム (Bazaar,Mercurial)
• グラフィックソフト (Gimp)
• Xen(仮想マシンソフトウェア)
1.3.2 欧米ではポピュラーな Python
Python はそのシンプルさや生産性の高さから多くの企業で利用されており,Google や Yahoo!,最近では Youtube
など,主に Web 系の企業で利用されています.しかしそれだけではなく,NASA ではハードウェアや計測器の制御な
どに,ハリウッド映画の映像を手がける ILM では CG 製作に,そして米国軍太平洋司令部の諜報ドキュメント管理シ
ステムといった,Web 以外の用途にも,数多くの場面で積極的に利用されています.そして特に Google においては主
第 1 章 Python の概要
302
要言語の 1 つとして大変重要な役割を担っており,例えば Java プログラマを募集する際にも Python の経験を要求す
るほどです.
欧米での人気に反して,日本ではメジャーな言語であるとは言えず,利用している企業もあまり多くはありません.
その原因として,
「日本語処理に関する不安」と「日本語のドキュメントが少ない」ことが挙げられます.ただし,前者
については Python 2.4 以降標準で日本語がサポートされたため,不安は解消されたと言えます.後者についても,最
近では Google App Engine において,最初にサポートされた言語であること,Python 製の Web フレームワーク・ア
プリケーションが台頭してきたこと,などの理由により Web 上の記事や書籍なども増加しています.
1.4 Python の特徴
Python の強みとしてあげられるのは,「習得が容易」,「使いやすい」,「ライブラリが豊富」,「オーブンソース」,「マ
ルチプラットフォーム」,「オブジェクト指向」,「グルー言語」などがあり,先に述べたように,数々の企業で採用され
ている「実績十分」な言語でもあります.以下では,その中からトピックを絞って詳しく説明していきます.
1.4.1 習得が容易
Python はもともと教育用言語である ABC から発展した言語であり,その設計思想においても「非技術者」にとっ
て理解しやすく分かりやすい言語を目指しているため,プログラミング初心者にとっても非常に習得が容易な言語で
す.他のプログラミング言語と比べても文法がとてもシンプルで,覚えやすくなっています.また,予約語の数も他の
言語と比べると少なくなっています.予約語とは C 言語でいう「if」や「for」というようなあらかじめ言語側で「予約」
されていて,自由にプログラマが利用することのできないキーワードのことです.文法が複雑であるほど,この予約語
の数も多くなる傾向にあります.
表 1.1
各言語の予約語の数
言語
予約語の数
Python 2.6
31
Ruby 1.9
40
Perl 5.10
220
Java SE 6
50
1.4.2 使いやすい
Python には標準ライブラリという非常に高機能なライブラリが付属しています.例えば,Web やメールなど,イン
ターネット上のサービスを簡単に処理する機能から,ウィンドウやボタンなどを使った GUI アプリケーションを作る
機能までも提供しています.これを利用することによって,面倒な処理をゼロから作ることなく複雑なプログラムを書
くことが可能となっています.
また Python ではインデントによってブロック構造が定義されるようになっており,そのシンプルな文法とあいまっ
て,コードが非常に簡潔で短く,可読性に優れたものになっています.その上,曖昧さを排除した言語設計が徹底され
ているため,誰が書いても同じようなコードになり,他人が書いたコードでも読みやすくなっています.
以下に前回のテキストでも言及した FizzBuzz 問題について Python,C,Java のコードで記述したものを並べてみ
ました.好みの問題もありますが,Python のコードは C や Java より余分な括弧が少なく,簡潔な印象を受けると思
1.4 Python の特徴
います.
# Python で FizzBuzz
for i in range(1, 101):
if i % 15 == 0:
print ’FizzBuzz’
elif i % 3 == 0:
print ’Fizz’
elif i % 5 == 0:
print ’Buzz’
else:
print i
// C で FizzBuzz
#include <stdio.h>
int main()
{
int i;
for (i = 0; i <= 100; i++)
{
if (i % 15 == 0)
printf("FizzBuzz");
else if (i % 3 == 0)
printf("Fizz");
else if (i % 5 == 0)
printf("Buzz");
else
printf("%d", i);
printf("\n");
}
}
// Java で FizzBuzz
public class FizzBuzz
{
303
第 1 章 Python の概要
304
public static void main(String [] args)
{
for (int i = 1; i <= 100; i++)
{
if (i % 15 == 0)
System.out.print("FizzBuzz");
else if (i % 3 == 0)
System.out.print("Fizz");
else if (i % 5 == 0)
System.out.print("Buzz");
else
System.out.print(i);
System.out.println();
}
}
}
可読性に優れたコードは,様々な恩恵をもたらします.最も大きな利点は,コードを見た時に,そのコードが何をし
ようとしているのか,内容を理解しやすい点です.他人が書いたコードを解読する場合,内容を理解するのに時間がか
かってしまうのが一般的です.しかし,プログラムの内容を理解しやすければ,インターネット上にたくさんある他人
が書いたコード,またはオープンソースソフトウェアなどを利用する場合でも,機能追加などの改良を行いやすくなり
ます.また,複数人でプログラムを書いていくプロジェクトなどの場面においても少ない時間で作業を終えることがで
きます.自分が過去に書いて,内容を忘れてしまったプログラムに対しても,少ない労力で修正を行うことができます.
1.4.3 マルチプラットフォーム
Python はオープンソース由来の言語であるというバックグラウンドから,多くの OS 上で動作させることができる
ようになっています.つまり,Python で プログラミングを行えば,ほぼ全ての OS 上で動作可能なプログラムを書
くことができると言えます.また,Java VM 上で動作する Jython や,.NET Framework 及び Mono 上で動作する
Iron Python など異なる言語で実装されたものもあります.利用することのできる主なプラットフォームは以下の通り
です.
• Windows
• Macintosh
• 各種 UNIX
• Linux
• PalmOS
• S60
• ニンテンドー DS,ニンテンドーゲームキューブ
1.5 Python プログラミング
305
• プレイステーション 2,プレイステーション 3
• XBox
• Java (Jython)
• .NET Framework (Iron Python)
1.4.4 グルー言語
Python は他の言語で書かれたプログラムと簡単に連携させることができます.C や C++ のプログラムから
Python のライブラリを呼び出すことや,逆に Python のプログラムから C や C++ のプログラムを呼び出すことが
自由にできます.このように言語をつなぐ糊のような役割をすることから「グルー言語」と表現されています.また
Python は OS のサービスをライブラリとして実装していることから,言語間だけでなく OS 間のグルー言語としても
利用することができます.
また Python はそのシンプルさと高機能さから,短期間でコーディングが可能なため,ラピットプロトタイピングに
もよく利用されます.初めは Python のシンプルな文法でシステムのプロトタイプを作っておいて,後で,必要に応じ
て必要な部分だけ C や C++ などのコンパイラ言語に移行するといったことが可能です.
1.5 Python プログラミング
1.5.1 インストール
Linux や Mac OS X などには最初からバンドルされていることが多いのですが,もしインストールされていない場
合でも,比較的簡単に導入することができます.Windows と Mac OS X 用にはインストーラプログラムが用意されて
おり,Linux へはソースから直接ビルドするか yum や apt といったパッケージマネージャを利用してインストールし
ます.各 OS 用のインストーラプログラムやソースコードは,日本 Python ユーザ会の以下のページで確認することが
できます.
Python 標準リリースは,http://www.python.jp/Zope/download/pythoncore を参照して下さい.
1.5.2 Python プログラムの実行
Python プログラムを動かすには,
「インタラクティブシェル」と「スクリプトファイルから実行」という 2 つの方法
があります.前者は,エディタを立ち上げることなくその場でコードを打ち込み,実行させることができます.Linux
や Unix といった環境であれば,シェルを起動して python と打ち込むだけで,簡単にインタラクティブシェルを起動
することができます.後者は,何らかのエディタでファイルに Python コードを記述して保存し,ファイル名を指定し
て実行させる方法です.以下で,それぞれについて詳しく説明します.
インタラクティブシェル
Python がインストール済みの環境(Linux/Unix)であれば,シェル上で「python」と入力するだけでインタラク
ティブシェルを起動することができます.もし起動しない場合は,シェルの設定を見直して Python パスが通っている
かどうか確認してみて下さい.
インタラクティブシェルを起動すると, >>> と表示されます.これが入力待ちの状態です.この状態から自由にプ
ログラムを記述することができます.また ... と表示されている場合も,次の入力を待っている状態です.入力を中
止したい場合は,Ctrl-c を押すとその入力を中止して,次の入力待ち状態に移行することができます.インタラクティ
ブシェルを終了したい場合は,Ctrl-d で終了させることができます.
第 1 章 Python の概要
306
スクリプトファイルの実行
任意の場所に適当な Python コードを書いたファイル保存します.そしてシェル上で以下のコマンドを入力すると書
かれたプログラムが実行されます.
$ python ファイル名
1.6 Python 開発環境
Python でプログラミングを行う場合に際して,便利なツールを紹介します.最低限入れておきたいツールは,
Python モジュールを自動で検索してインストールやアップデートを行ってくれる easy install,そして標準のシェル
にマクロや履歴,補完など様々な便利機能を追加した iPython です.以下に導入方法と簡単な使用方法について説明
します.
1.6.1 easy install
easy install を使うとサードパーティ製の Python ライブラリを手軽にインストールすることができます.
Python には利便性の高い標準ライブラリが付属していますが,Google などの特定の Web サービスを利用するため
のライブラリや,あまり汎用的でないライブラリは,含まれていません.python.org では,標準ライブラリに含まれ
ていないサードパーティ製のライブラリを集積し,配布する PyPI(Python Package Index)というサービスを提供し
ています.この PyPI 内の膨大なライブラリをコマンド 1 つで簡単にインストールするためのツールが easy install
です. easy install はインストール時にライブラリの依存関係も解消してくれるので,インストール作業をかなり短
縮することができます.
インストール
http://peak.telecommunity.com/dist/ez setup.py からファイルをダウンロードして以下のコマンドを実行
するだけで環境にあった easy install がインストールされます.
$ sudo python ez setup.py
使い方
PyPI に登録済みのライブラリなら以下のコマンドでインストールできます.
$ sudo easy install パッケージ名
さらに,いくつかのオプションを指定する事も可能です.興味のある方は,以下のコマンドでオプション一覧と使い
方を確認してみて下さい.
$ easy install --help
1.6.2 iPython
iPython は補完や履歴など,様々な機能が追加された高機能なインタラクティブシェルです.標準のインタラクティ
ブシェルから iPython に切り替えるだけで,デバッグや開発作業をかなり効率化することができます.
1.6 Python 開発環境
307
インストール
easy install をインストール済みであれば以下のコマンドを実行するだけでインストールができます.
$ sudo easy install ipython
ソースコードからインストールする場合は,http://ipython.scipy.org/moin/Download からそれぞれの環境に
あったバージョンをダウンロードし,解凍して以下のコマンドを実行して下さい.
$ sudo python setup.py install
使い方
iPython は,以下のコマンドで起動します.
$ ipython
起動すると,In[1] と表示され,入力可能状態になります.下図のように,In[番号] の右側が入力可能部分,そしてそ
の実行結果が Out[番号] の左側に表示されます.In と Out の番号はそれぞれ対応しており,後からその番号を使った
履歴の実行などに利用されます.
In [1]: ’hello world!’
Out[1]: hello world
iPython の最も基本的かつ便利な機能は補完です.オブジェクト名やメソッド名の入力中にタブキーを押すことで,
補完が行われます.オブジェクト名の入力中であれば該当するオブジェクト名を絞り込んで補完,オブジェクトをドッ
トでつないだ時点であればそのオブジェクトの属性一覧を全て表示することができ,そこから絞り込みを行うことがで
きます.さらにマジックファンクションという独自の関数が定義されており,様々な機能が提供されています.例え
ば,オブジェクト名に続いて「?」を入力すると,そのオブジェクトの説明が表示されます.メソッドの場合は,引数に
何を指定すればよいかなども表示されるため,開発時にはリファレンス代わりにもなり非常に重宝することになるはず
です.その他にも処理時間を計測する timeit や変数情報を iPython 終了後も再利用可能にする store など,多くの機
能が提供されています.興味のある方は,iPython 上で「%」と入力したあとにタブキーを押してみるとマジックファ
ンクションが一覧表示されるので,興味のあるものを選択し,「?」を末尾に追加して説明を表示させてみて下さい.
iPython は,Ctrl-d で終了,Ctrl-c で実行中の処理を中止することができます.
Python 2.6.3 (r263:75183, Oct 17 2009, 01:11:24)
Type "copyright", "credits" or "license" for more information.
IPython 0.10 -- An enhanced Interactive Python.
?
-> Introduction and overview of IPython’s features.
%quickref -> Quick reference.
help
-> Python’s own help system.
object?
-> Details about ’object’. ?object also works, ?? prints more.
In [1]: %who?
第 1 章 Python の概要
308
Type:
Magic function
Base Class:
<type ’instancemethod’>
String Form:
<bound method InteractiveShell.magic_who of <IPython.iplib.InteractiveShell
object at 0x100425a90>>
Namespace:
IPython internal
File:
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/IPython/Magic.py
Definition:
%who(self, parameter_s=’’)
Docstring:
Print all interactive variables, with some minimal formatting.
If any arguments are given, only variables whose type matches one of
these are printed.
For example:
%who function str
will only list functions and strings, excluding all other types of
variables.
To find the proper type names, simply use type(var) at a
command line to see how python prints type names.
For example:
In [1]: type(’hello’)
Out[1]: <type ’str’>
indicates that the type name for strings is ’str’.
%who always excludes executed names loaded through your configuration
file and things which are internal to IPython.
This is deliberate, as typically you may load many modules and the
purpose of %who is to show you only what you’ve manually defined.
第2章
基本構文/主な型/演算子/制御構文
本章では,Python でプログラミングを行うために必要な基本構文を説明します.概要でも述べましたが Python の
特徴はインデントを利用した視覚的に訴えるコーディングスタイルと,シンプルで覚えやすい文法です.
本テキストでは,ほとんどのソースコードをインタラクティブシェルに直接入力することを前提にしており,その入
出力形式に似せたスタイルで記述しています.
2.1 基本構文
Python の最大の特徴はインデントによってプログラムの構造を区切ることです.例えば if 文の場合,C 言語と
Python を比べると以下のようになります.
# Python の if 文
if foo > 0:
print ’foo’
else:
print ’not foo’
// C の if 構文
if (foo > 0) {
printf("foo");
} else {
printf("not foo");
}
このように C 言語では「{」から「}」までを 1 つの処理の固まりとして表しますが,Python ではその固まりを行の
左側に空白を挿入することで表現します.このインデントがずれるとエラーになることがあるため,空白の数には注意
が必要です.一応,何を利用してインデントを表現しても良いのですが,一般的にはタブよりもスペースの利用が推奨
されています.タブ文字は環境によって空白の数が変わってしまうため,混乱を招く恐れがあるからです.PEP 標準
コーディング規約では標準的なインデントはスペース 4 つ分となっています.また,C 言語や Java では文の終わりを
セミコロンで表現しますが,Python には明示的に文の終わりを示す区切り文字はありません.Python は物理的な 1
行を文の終わりと解釈します.そのため,しばしば 1 行が異常に長くなってしまう状態が発生しますが,以下のように
バックスラッシュを挿入することで任意の箇所で改行することができます.また文法上,括弧の中はいくらでも改行で
きるようになっています.これらの条件をうまく利用して,なるべく見やすいコードになるようにうまく整形していき
第2章
310
基本構文/主な型/演算子/制御構文
ましょう.
# 括弧全般の中は自由に改行
[’%s was created by %s’ % (lang, author)
for lang, author in zip((’ruby’, ’python’, ’perl’),
(’matz’, ’guido’, ’larry’))]
# バックスラッシュで改行
if ’ 習得が容易’ in text and ’ 使いやすい’ in text and \
’ マルチプラットフォーム’ in text and ’ グルー言語’ in text:
print ’It\’s Python!’
# "It’s Python!"でも可.
このように Python プログラムは,インデントと物理的な行によって記述するため,処理の固まりが一目で理解しや
すく,誰が書いても整然とした綺麗なコードになるように設計されているのです.
2.2 変数
PHP と同じように,Python も文脈に応じて動的に変数の型を定めてくれるため,変数の型を宣言する必要はあり
ません.PHP のようにドル記号などを変数名につける必要もありません.よって以下のように変数を宣言することが
できます.参考までに,前回のテキストでも登場した C のコードを Python コードと対応する形で以下に示します.
# Boolean 型
b = True
# 整数
i = 1
# 浮動小数点数
f - 1.0
s = "abc"
# 文字列
i2f = float(i)
# 整数から浮動小数点数にキャスト
int b = 1;
// 規格 C89 に論理型はない
int i = 1;
// 整数
float f - 1.0;
// 浮動小数点数
char s[] = "abc";
// 文字列
float i2f = (float)i;
// 整数から浮動小数点数にキャスト
Python の変数は,常にオブジェクトへの参照です.上には「動的に変数の型を定める」と書きましたが,実は,変
数自体は型情報を保持していません.型情報を持っているのはオブジェクト自身であり,変数はそのオブジェクトに対
する参照を持っているだけなのです.例えば,数値の 1 を代入した変数 a を宣言し,後からその変数 a に文字列’abc’
を代入したとします.パッと見,変数の型変換が行われているように見えるかもしれませんが,変数側では特に型の変
換などといった処理は行っていません.とにかく,変数はオブジェクトへの参照です.この時内部で行われている処理
は,今まで数値オブジェクトの 1 を参照していた変数が,新しく生成したオブジェクトを参照するようになっただけ,
そして新たな参照先であるオブジェクトの型がたまたま文字列であっただけなのです.
>>> a = 1
2.3 Python のデータ型
311
>>> type(a)
<type ’int’>
>>> a = ’abc’
>>> type(a)
<type ’str’>
もう一度まとめますが,変数はオブジェクトへの参照情報だけを持ち,型情報を持っているのはオブジェクトです.
これが Python にとっての変数の位置づけであり,Python の特徴の 1 つです.
2.3 Python のデータ型
Python は「組み込み型」といってあらかじめよく使われる型が定義されています.主な組み込み型は以下のように
なっており,大きく分類すると数値,シーケンス,マップ,セットの 4 種類に分けられます.また,それぞれが「変更
不可能オブジェクト」と「変更可能オブジェクト」に分類できます.
数値(変更不可能)
• 整数型
• 長整数型
• 浮動小数点型
• 複素数型
シーケンス
• 文字列型(変更不可能)
• unicode 文字列型(変更不可能)
• リスト型(変更可能)
• タプル型(変更可能)
マップ
• 辞書型(変更可能)
セット
• 集合型(変更可能)
• 変更不能集合型(変更不可能)
数値や文字列が「変更不可能」というのは,少し違和感があるかもしれません.変更不可能なオブジェクトというの
は,内容が不変でなければならないということです.例えば,文字列はシーケンス型なのでインデックスを利用して要
素にアクセスすることが可能ですが,個々の要素を変更しようとすると以下のような「文字列オブジェクトはアイテム
の割当をサポートしていない」といった主旨のエラーが発生します.このように文字列型は,そのオブジェクトの内容
を変更できない仕様になっています.逆に「変更可能」なシーケンスであるリストは,同じ操作で要素の変更を行うこ
とが可能です.
>>> s = "abcdefg"
>>> s[0]
# インデックスで文字にアクセスできる
’a’
>>> s[0] = ’A’
# 文字(要素)単位で変更はできない
第2章
312
基本構文/主な型/演算子/制御構文
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ’str’ object does not support item assignment
>>> l = [’a’, ’b’, ’c’, ’d’]
>>> l[0]
’a’
>>> l[0] = ’A’
>>> l
[’A’, ’b’, ’c’, ’d’]
文字列は,下に示すコードのように代入演算子を使って足し算すると,文字列同士が連結して変数の内容が変わって
いるように見えるかもしれません.しかし,内部的には変数同士の足し算が行われて,新たな文字列のコピーが生成さ
れ,それが新たに変数に代入されているだけなのです.つまり,文字列オブジェクト自体が変更されているわけではな
く,文字列オブジェクトへの参照を持っている変数の参照先が,足し算によって新たに生成された文字列オブジェクト
に置き換わった,ということです.
>>> s = "abc"
>>> s += ’DEF’
# 代入演算子で文字列同士を連結
>>> s
’abcDEF’
また,Python のデータ型は全て,データだけではなく命令も一緒に持っています.このようにデータと命令を一緒
に持つものを「オブジェクト」と言います.そして,そのオブジェクトの持つ命令のことを「メソッド」と呼んでいま
す.メソッドは,オブジェクトに続けて「.」を書き,その後に記述します.例えば,文字列型であれば以下のようなメ
ソッドを持ちます.
>>> s = "文字列"
>>> s.find(’ 字’)
# 文字列を検索する
True
>>> s.split("字")
# 文字列を指定文字列で分割する
[’ 文’, ’ 列’]
>>> ’ と’.join(s)
# 文字列を指定文字列で連結する
’ 文と字と列’
>>> s.replace(’ 文字’, ’ 数’)
# 文字列を指定文字列で置き換える
’ 数列’
このように Python のデータ型は全てが「オブジェクト」です.そしてデータ型ごとに便利なメソッドが多数用意さ
れており,よくある処理を短く簡潔に記述することができます.
また,組み込み関数 dir を使うと対象のオブジェクトが保持している属性をメソッドも含め全て見ることができ,デ
バッグや開発作業中にインタラクティブシェルで確認しながら作業を行うと便利です.例えば,全ての組み込みオブ
ジェクトにアクセスするための,グローバル変数 builtins を dir ( builtins ) のように指定すると,全ての組み込み
2.3 Python のデータ型
313
型や組み込み関数の一覧が表示されます.
>>> dir(’ 文字列’)
# オブジェクトの属性を全て取得
[’__add__’, ’__class__’, ’__contains__’, ’__delattr__’, ’__doc__’, ’__eq__’,
’__format__’, ’__ge__’, ’__getattribute__’, ’__getitem__’, ’__getnewargs__’,
’__getslice__’, ’__gt__’, ’__hash__’, ’__init__’, ’__le__’, ’__len__’, ’__lt__’,
’__mod__’, ’__mul__’, ’__ne__’, ’__new__’, ’__reduce__’, ’__reduce_ex__’, ’__repr__’,
’__rmod__’, ’__rmul__’, ’__setattr__’, ’__sizeof__’, ’__str__’, ’__subclasshook__’,
’_formatter_field_name_split’, ’_formatter_parser’, ’capitalize’, ’center’, ’count’,
’decode’, ’encode’, ’endswith’, ’expandtabs’, ’find’, ’format’, ’index’, ’isalnum’,
’isalpha’, ’isdigit’, ’islower’, ’isspace’, ’istitle’, ’isupper’, ’join’, ’ljust’,
’lower’, ’lstrip’, ’partition’, ’replace’, ’rfind’, ’rindex’, ’rjust’, ’rpartition’,
’rsplit’, ’rstrip’, ’split’, ’splitlines’, ’startswith’, ’strip’, ’swapcase’,
’title’, ’translate’, ’upper’, ’zfill’]
2.3.1 文字列
Python の文字列は,シーケンス型といわれる型に分類されており,後に説明するリスト型と似たような構造とメ
ソッドを持っています.
Python の文字列型には,文字列型と unicode 文字列型の 2 種類が用意されています.主に数値やアルファベットと
いった ASCII 文字を扱うために利用する文字列型.そして,漢字やひらがななどの文字を含む,より広い範囲の文字
を扱うために利用するのが unicode 文字列型です.それぞれ以下のように記述します.
>>> "string"
# 文字列のリテラル
’string’
>>> ’string’
# ’’ でも""でもどちらでもよい
’string’
>>> u’ 日本語’
# 文字列リテラルの前に u をつけると unicode 文字列
u’\u65e5\u672c\u8a9e’
>>> u = unicode(’ 日本語’, ’utf8’)
# 文字コード指定して unicode 文字列に変換する
>>> u
u’\u65e5\u672c\u8a9e’
>>> u.encode(’utf8’)
# 文字コード指定して unicode 文字列から文字列に変換する
’\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e’
文字列同士は足し算やかけ算をすることができます.
>>> ’Hakodate’ + ’City’
’HakodateCity’
>>> ’Ika’ * 3
’IkaIkaIka’
第2章
314
基本構文/主な型/演算子/制御構文
>>> ’Ika’ * 5 + ’Odori’
’IkaIkaIkaIkaIkaOdori’
その他にも以下のような便利なメソッドを利用することができます.
>>> s = ’Hakodate’
# 文字列内に指定文字列が存在するか検索
>>> s.find(’a’)
True
# 文字列内で指定文字列が最初に出現する位置
>>> s.index(’a’)
1
# 文字列を指定文字列で分割
>>> s.split(’a’)
[’H’, ’kod’, ’te’]
>>> ’-’.join(s)
# 指定文字列で文字列を連結
’H-a-k-o-d-a-t-e’
>>> s.replace(’a’, ’o’)
# 指定文字列で文字列を置換
’Hokodote’
>>> s.upper()
# 文字列を全て大文字にする
’HAKODATE’
また他の C 言語と記述方法の似たフォーマット文字列というものもあります.文字列内に % 演算子と識別子を記述
すると,その部分に変数値を代入することができます.
>>> author = ’Guido van Rossum’
>>> language = ’Python’
>>> ’%s was created by %s in %d’ % (language, author, 1990)
Python was created by Guido van Rossum in 1990.
表 2.1
文字列フォーマット主なコード対応
コード
対応する型
%s
文字列
%d
10 進数の整数型
%f
10 進数の浮動小数点型
2.3.2 リスト
リストは C 言語などで言う配列と似たデータ型をしています.Python のリストには,どんな型のオブジェクトでも
格納することができます.そして C 言語などのように最初の型宣言やサイズを確保する必要はなく,必要に応じて言
語内で自動的に調整してくれます.このリスト型は,文字列型と同じシーケンス型に分類され,どちらも似たような挙
動を示します.
リストは C 言語の配列と同じように,インデックスを指定して格納されている要素を取り出すことができます.以
2.3 Python のデータ型
315
下に基本的な操作方法を示します.
>>> l = [’Python’, ’Ruby’, ’Perl’]
# リストの作成
# インデックスを指定して取り出す
>>> l[1]
’Ruby’
# 負数を指定すると右から数えたインデックス指定
>>> l[-2]
’Ruby’
# 要素数の取得
>>> len(l)
3
>>> l.append(’PHP’)
# 要素を末尾に追加
>>> l
[’Python’, ’Ruby’, ’Perl’, ’PHP’]
>>> l.remove(’PHP’)
# 指定要素を削除
>>> l
[’Python’, ’Ruby’, ’Perl’]
スライスという機能を利用するとリストが持つ複数の要素を簡単に取り出すことができます.
>>> l = [’Python’, ’Ruby’, ’Perl’, ’PHP’]
# インデックス 1 以上の要素を取り出すスライス
>>> l[1:]
[’Ruby’, ’Perl’, ’PHP’]
# インデックス 1 以上 3 未満の要素を取り出すスライス
>>> l[1:3]
[’Ruby’, ’Perl’]
# 2 つ毎に要素を取り出すスライス
>>> l[::2]
[’Python’, ’Perl’]
その他にも以下のような操作をすることができます.
# 0 から始まる要素数 10 の整数リストを作る
>>> l = range(10)
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l.insert(0, ’Python’)
# 0 番目の要素の前に指定オブジェクトを追加
[’Python’, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l.reverse()
# 要素を逆順にする
>>> l
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ’Python’]
>>> l.sort()
# 要素をソートする
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ’Python’]
>>> l.pop()
’Python’
# 末尾から要素を消去して取り出す
第2章
316
基本構文/主な型/演算子/制御構文
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l + [’Python’, ’Ruby’, ’Perl’]
# リスト同士を連結したコピーを返す
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ’Python’, ’Ruby’, ’Perl’]
# リストを繰り返し連結したコピーを返す
>>> l * 3
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2.3.3 辞書
辞書はリストと同様に複数の値を格納することのできるデータ型です.このデータ型については次章で詳しく説明し
ます.
2.3.4 タプル
タプルはリスト型とよく似たデータ型です.タプルはリストと同じく,シーケンス型に分類されるデータ型で,リス
トと同じように,様々な型のオブジェクトをインデックスによる管理のもとで格納しておくことができます.しかし,
リストは格納している要素を書き換えることができますが,タプルにはそれができません.一度作ったタプルは長さを
変更することも,代入して要素を書き換えることもできません.sort() のようなタプル自体を書き換えるメソッドも
持っていません.とにかく,タプル自体を書き換えるような操作は一切できないようになっています.ただし,足し算
や代入演算子を使って,擬似的に変更したように見せることは可能です.実際には,演算によって新たなタプルが生成
され,そのタプルへの参照が変数に代入されるだけなので,内容が変更されているわけではありません.
>>> (’Python’, ’Perl’, ’Ruby’)
# タプルのリテラルは ()
(’Python’, ’Perl’, ’Ruby’)
# 要素数 1 のタプルは最後にコンマが必要
>>> (’Python’,)
(’Python’,)
>>> t = tuple([’Python’, ’Perl’, ’Ruby’])
# tuple 関数でタプルに変換可能
>>> t
(’Python’, ’Perl’, ’Ruby’)
>>> t[0]
# リストと同じようにインデックスで要素にアクセスできる
’Python’
>>> t[0] = ’PHP’
# リストのように内容を変更することができない
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ’tuple’ object does not support item assignment
>>> t += (’PHP’,)
>>> t
# 足し算などで新たなタプルを生成することは可能
# 変数の参照先が変わっただけなのでタプル自体は変更されてない
(’Python’, ’Perl’, ’Ruby’, ’PHP’)
2.4 演算子
317
リストに比べて自由度の低い印象のあるタプルですが,いくつか利点があります.タプルはリストと異なり,辞書の
キーとして利用することができるのです.これは例えば,IP アドレスととホストの対応辞書や,電話番号と名前の辞
書を作成するような場面で有効になります.以下に示すような電話番号と名前の辞書の場合,(市外局番,市内局番,加
入者番号) のようなタプルを作成し,それをキーとして名前と対応させることで,市内局番や市外局番単位で一致する
名前を検索しやすい辞書を作成することができます.
>>> telmap = {(0123, 00, 0000): ’Ika.inc’,
(090, 0000, 0000): ’Taro Hakodate’
(0123, 11, 1111): ’Ika Shop}
>>> [(tel, name) for tel, name in telmap.items() if tel[0] == 0123]
[(0123, 00, 000), ’Ika.inc’), ((0123, 11, 1111), ’Ika Shop’)]
このように,タプルは複数の要素を持つシーケンスを辞書のキーとして利用したい場合に威力を発揮します.
2.4 演算子
C 言語や Java で使うような演算子を,Python でもほぼ同じように使うことができます.Java や C にはあり,
Python にないものには,論理演算子の「&&」,
「||」や算術演算子の「++」,
「−−」などがあります.論理演算子につ
いては代替表現の「and」
,
「or」
,算術演算子は代替表現が存在しないので「+=」
,
「−=」などを利用して同じような結
果になるように工夫します.
表 2.2 は,代表的な演算子を優先順位の高い順に示したものです.複数の演算子が混在する場合は,優先順位の高い
演算の方が優先して実行されます.
表 2.2 演算子と優先順位
演算子
説明
x**y
べき乗
x*y,x/y,x//y,x%y
乗算,除算,切り捨て除算,剰余
x+y,x-y
加算,減算
x<<y,x>>y
左シフト,右シフト
x&y
ビット単位の論理積(AND)
x^
y
ビット単位の排他的論理和(XOR)
x|y
ビット単位の論理和(OR)
x<y,x<=y,x>y,x>=y,x!=y,x==y
比較(小なり,以下,大なり,以上,不等価,等価)
x is y, x is not y
アイデンティティの評価
x in y,x not in y
メンバシップの評価
not x
論理否定(NOT)
x and y
論理積(AND)
x or y
論理和(OR)
算術演算子は,各オブジェクトによって挙動が異なります.辞書,集合の各オブジェクトは算術演算をサポートして
いません.主な演算結果については以下に示します.
第2章
318
基本構文/主な型/演算子/制御構文
# 整数同士の除算は小数点以下が切り捨て
>>> 1 / 2
0
# どちらかを浮動小数点にすると小数点以下も計算
>>> 1.0 / 2
0.5
>>> ’Python’ + ’Ruby’ # 文字列を連結する
’PythonRuby’
# 文字列を繰り返し連結する
>>> ’Python’ * 3
’PythonPythonPython’
>>> [1, 2, 3] + [3, 2, 1]
# リストを連結する
[1, 2, 3, 3, 2, 1]
>>> [1, 2, 3] * 3
# リストを繰り返し連結する
[1, 2, 3, 1, 2, 3, 1, 2, 3]
Java や C に存在しない演算子に is や in があります. is はアイデンティティの評価, in はメンバシップの評価
を行う条件演算子です. is は同 1 のオブジェクトであるかの判定を行うため, == 演算子で True であっても is 演算
子では False になる可能性があります. in はシーケンスなどのオブジェクトの中に該当する要素が含まれているかの
判定を行います.
>>> l = [1, 2, 3]
>>> l == [1, 2, 3]
# 要素が全て等しいので真
True
>>> l is [1, 2, 3]
# オブジェクトが異なるため偽
False
>>> l is l
# 同一のオブジェクトなので真
True
>>> 1 in l
# オブジェクト内に要素が存在しているので真
True
>>> 10 in l
# オブジェクト内に要素が存在していないので偽
False
2.5 制御構文
C 言語や前回学習した PHP と同じように,Python でも if や for,while などの制御構文を利用することができます.
ただし,C 言語のように処理のまとまりを波括弧「{}」ではなくコロン「:」とインデントで記述します.このような処
理のまとまりのことをブロックと呼びます.その他にも今回は取り上げませんが,例外処理を行うための try/except
文などがあります.
2.5 制御構文
319
2.5.1 if 文
Python の if 文の基本的な動作は,他の言語とほとんど変わりません.条件が真のときには if ブロック内,条件が偽
のときは else ブロック内の処理が実行されます.複数の条件を評価する場合は,elif を使用しすることで,上から順に
条件評価を行っていき,真になるブロックで処理を実行して終了します.
>>> langs = [’python’, ’ruby’, ’perl’]
>>> if ’python’ in langs:
...
print ’python is in langs’
... else:
...
print ’python is not in langs’
...
’python is in langs’
Python には switch 構文が存在しません.switch のような処理を行いたい場合は,if 文と elif を利用します.
>>> def switch(input):
# 引数を 1 つ受け取る関数を定義
...
# 0 に等しい
if input == 0:
...
...
print ’input == 0’
elif input == 1:
# 上の if が偽の場合,1 に等しい
...
print ’input == 1’
...
elif 2 >= input >= -2:
...
...
# 上の elif が偽の場合,-2 以上 2 以下
print ’2 > input > -2’
else:
...
# 前の条件が全て偽だった場合
print ’else’
...
>>> switch(0)
’input == 0’
>>> switch(1)
’input == 1’
>>> switch(-2)
’2 > input -2’
>>> switch(3)
’else’
2.5.2 ループ
Python でループ処理を行うには,for 文と while 文があります.while 文は他の言語とほぼ同じように利用すること
ができますが,for 文については C 言語などと比べると,書き方や挙動が少し特殊になっています.Python の for 文
には他の言語でいうカウンタのようなものが存在しません.対象シーケンスの要素が無くなるまで,要素を取り出しな
第2章
320
基本構文/主な型/演算子/制御構文
がら繰り返しを続けていきます.他の言語で言うと PHP の foreach 文と少し似ているかもしれません.簡単な例を以
下に示します.
# 0∼4 までの整数リストをループ処理
>>> for i in range(5):
...
print i,
...
0 1 2 3 4
>>> l = range(5)
# リストが空(偽評価)になるまでループ処理
>>> while l:
...
# 0∼4 までの整数リストを作成
# リストから末尾の要素を削除して取り出し
print l.pop(),
...
4 3 2 1 0
そして,Python のループ構文の大きな特徴として else の存在があります.ループ構文で用いられる else ブロック
は,break によってループが強制終了されなかった場合にのみ,実行されます.else を利用すると,他の言語ではフラ
グ変数を用意しなければならないような処理を,簡潔に表現することができます.
>>> def loop(input):
...
...
# 引数を 1 つとる関数を定義
for i in input:
if i % 7 == 0:
# 要素から 7 を割った余りが 0 の場合
...
print ’break’,
...
break
...
...
...
print i,
else:
# break が呼び出されずループが終了した場合
print ’End’,
...
>>> loop([0, 2, 4, 6, 8])
0 2 4 6 8 ’End’
>>> loop([1, 3, 5, 7, 9])
1 3 5 7 ’break’
2.6 デバッグ
Python はスクリプト言語であるため,PHP と同じように実行されるまでエラーや警告が出力されません.本節で
はエラーが出力された場合の,エラーメッセージの読み方について説明します.
Python では通常出力されるエラーメッセージのことをトレースバックと呼びます.このトレースバックにはエラー
が発生するまでの情報が関数やモジュールの呼び出し順に出力さるため,上から順番にどこで何が起こったのかを追っ
ていくことができます.最下行にはエラーの種類が表示されるようになっているので,トレースバックを見る場合は,
まず最下行を見てエラーの種類を確認してから,最初の行に戻ってエラーが発生した場所を順次確認していくといいで
しょう.
実際にエラーが発生した場合の例を以下に示します.このコードには,引数を URL として受け取り,標準モジュー
2.6 デバッグ
321
ルの urllib を使って Web ページの HTML を取得する urlopen 関数が定義されています.
# -*- coding: utf-8 -*import urllib
# web ページの HTML を取得して返す関数
def urlopen():
obj = urllib.urlopen(’htp://example.com’)
return obj.read()
# URL にアクセス
# HTML を文字列として返す
# コマンドラインから実行された場合のみ実行する
if __name__ == ’__main__’:
print urlopen()
# 関数 urlopen を呼び出して結果を表示
このコードをスクリプトファイル demo.py としてカレントディレクトリに保存し,コマンドラインから呼び出すと,
以下のようなトレースバックが表示されます.
$ python demo.py htp://example.com
Traceback (most recent call last):
File "demo.py", line 11, in <module>
print urlopen()
File "demo.py", line 6, in urlopen
obj = urllib.urlopen(’htp://example.com’)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/urllib.py",
line 87, in urlopen
return opener.open(url)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/urllib.py",
line 203, in open
return self.open unknown(fullurl, data)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/urllib.py",
line 215, in open unknown
raise IOError, (’url error’, ’unknown url type’, type)
IOError:
[Errno url error] unknown url type:
’htp’
このトレースバックの最下行を見ると「IOError: [Errno url error] unknown url type: ’htp’」と表示されています.
url の型がおかしいというエラーの可能性があります.「htp」という型は存在しないと指摘されています.ここで,最
初の行に戻ってトレースバックを眺めてみると,「File ”demo.py”, line 11, in ¡module¿」とあり,次の行に「print
urlopen()」と表示されています.demo.py の module 内,11 行目にある処理が原因のようです.さらに下の行を見て
いくと,「File ”demo.py”, line 6, in urlopen」,「obj = urllib.urlopen(’htp://example.com’)」と表示されています.
今度は,demo.py の 6 行目,urlopen 関数中のこの処理でつまずいていると考えられます.この部分をよく見てみる
と,引数に渡している URL のスキーマを「htp」と打ち間違えているようです.実際にソースコードを確認してみる
と,該当箇所を typo(タイプミス)しています,この部分を「http」と修正し,再びスクリプトファイルを実行すると
トレースバックが表示されなくなりました.このように Python のトレースバックでは,エラーの発端から全ての関連
第2章
322
基本構文/主な型/演算子/制御構文
する処理を Python 自身のライブラリファイル内まで追っていくことができます.何のどのような処理が原因でエラー
が起こっているのか,ソースコードレベルで深く追う事ができるのです.また,今回は紹介しませんでしたが,Python
の標準モジュールには pdb というデバッガが含まれています. pdb を使用することにより,ブレークポイントの設定
や,エラー発生時の変数の状態をインタラクティブシェルで逐次確認するなど,デバッグ作業をかなり効率的に行うこ
とができます. pdb について詳しくはライブラリリファレンスを参照して下さい.
2.6.1 エンコード宣言
上記ソースコードの 1 行目に「# -*- coding: utf-8 -*-」というコメントが書いてありますが,これはただのコメン
トではなくきちんとした意味を持っています.このように「coding: 文字コード名」のような書式で書かれたコメント
のことを「エンコード宣言」と言います.エンコード宣言を書くことによって,そのスクリプトファイルがどの文字
コードで書かれているかを明示的に Python に通知することでき,文字列リテラルから uicode への変換処理などをス
ムーズに行うことができるようになります.逆にこの宣言が書かれていない場合は,ソースコードに日本語が含まれて
いる場合に,うまく動作しない可能性もあるので,なるべく明記した方がよいでしょう.この文字コード宣言の書き方
にはいくつかルールがあり,記述場所は,ソースコードの 1 行目,または 2 行目と定められています.書式について
は,emacs または vim が認識できる書式と定められており,一般的には以下の 2 種類がよく使われています.
emacs
• # -*- coding: <encoding name> -*vim
• # vim:fileencoding=<encoding name>
第3章
連想配列(辞書)
辞書はリストと同じく,数値や文字列からリスト,辞書自体に至るまで様々なオブジェクトを格納することができる
データ型です.非常に柔軟で強力な Python を特徴づける機能の 1 つであり,データ構造の表現など様々な用途に利用
されています.
本章では,辞書について基本的な使い方から少し踏み込んだ利用法までを解説していきます.
3.1 辞書とは
先の概要でも触れたように,辞書は非常に利便性の高いデータ型です.PHP の連想配列と同じように,文字列のよ
うな添字を利用して格納している要素にアクセスします.添字と要素がペアで格納されたものとイメージすると分かり
やすいかもしれません.辞書ではこの添字のことを「キー」,要素のことを「値」と呼びます.
辞書が PHP と異なるのは,キーに文字列以外のオブジェクトを利用できる点です.キーには文字列の他に数値やタ
プルなど,いわゆる「変更不可能」なオブジェクトを利用することができます.逆にリストや辞書などの変更可能なオ
ブジェクトは,辞書のキーに指定することができません.
値についてはリストと同じようにどんなオブジェクトでも指定可能です.辞書自体を格納することもできるため,ネ
ストした(入れ子)構造も表現することができます.
3.2 辞書の基本
辞書のリテラルは「{}」です.この中に「:」で連結したキーと値のペアを「,」で分けて記述します.また,組み込
み関数の dict を利用することにより,リストから辞書を生成することもできます.辞書の値はキーを使って個別に取
り出すことが可能です.
>>> {}
# 空の辞書作成
{}
>>> d = {’Ohizumi’: ’Yo’, 99: ’ ナインティナイン’}
# 辞書の作成
>>> d
{’Ohizumi’: ’Yo’, 99: ’ ナインティナイン’}
>>> dict(Hokkaido=’ 寒い’, Nankyoku=’ かなり寒い’)
# dict 関数の利用
{’Hokkaido’: ’ 寒い’, ’Nankyoku’: ’ かなり寒い’}
>>> dict([(’Hokkaido’, ’ 寒い’), (’nankyoku’: ’ 寒い’)])
{’Hokkaido’: ’ 寒い’, ’Nankyoku’: ’ かなり寒い’}
>>> d[’Ohizumi’]
# 値にアクセス
# タプルのリスト指定も可
第 3 章 連想配列(辞書)
324
’Yo’
>>> d[’Kitajima’]
# 存在していないキーにはアクセスできない
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: ’Kitajima’
>>> d.get(’Kitajima’)
# 存在しないキーでもエラーがでない(None が返る)
>>> d.get(’Kitajima’, ’Saburo’)
# デフォルトの返り値を指定できる(辞書へ追加はしない)
’Saburo’
>>> d[’Kitajima’] = ’Saburo’
# キーと値の追加
>>> d[’Kitajima’]
’Saburo’
>>> del d[’Kitajima’]
# キーの削除(紐づく値も削除される
>>> d[’Kitajima’]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: ’Kitajima’
3.3 辞書の操作
他のデータ型と同じように辞書にも便利なメソッドがたくさん付属しています.ここではその中から代表的なものに
ついて使い方を説明します.オプションや詳しい使い方については,ライブラリリファレンスを参照して下さい.
>>> d = {’python’: ’guido’, ’ruby’: ’matz’, ’perl’: ’larry’}
# キーの一覧取得.でも順序はバラバラ
>>> d.keys()
[’perl’, ’python’, ’ruby’]
>>> d.values()
# 値の一覧取得.でも順序はバラバラ
[’guido’, ’larry’, ’matz’]
>>> d.items() # キーと値のペア一覧取得
[ (’perl’, ’larry’), (’python’, ’guido’), (’ruby’, ’matz’)]
>>> ’php’ in d
# キーの存在を調べる
False
>>> len(d)
# キーの数を調べる
>>> 3
>>> d.update({’java’: ’sun’, ’c’: ’dennis’})
# 辞書の内容を更新する
>>> d
{’c’: ’dennis’, ’java’: ’sun’, ’perl’: ’larry’, ’python’: ’guido’, ’ruby’: ’matz’, }
>>> d.setdefault(’php’, ’rasmus’)
キーを作成する
’rasmus’
>>> d
# キーが存在していればその値を返し,なければデフォルト値で新しく
3.3 辞書の操作
325
{’c’: ’dennis’, ’java’: ’sun’, ’perl’: ’larry’, ’php’: ’rasmus’, ’python’: ’guido’,
’ruby’: ’matz’, }
辞書は決まった順序を持ちませんが,for 文でキーを取り出すことができます.辞書の内容について逐次処理を行い
たい場合などに活用できます.
>>> d = {’python’: ’guido’, ’ruby’: ’matz’, ’perl’: ’larry’}
>>> for key in d: # 辞書を for ループにかけるとキーが取り出される
...
d[key] = ’_’.join(d[key])
# 値の文字列を改変
...
>>> d
{’python’: ’g_u_i_d_o’, ’ruby’: ’m_a_t_z’, ’perl’: ’l_a_r_r_y’}
>>> for key, value in d.items(): # items でキーと値の一覧がセットで取得できる
...
d[key] = value.replace(’_’, ’’) # 値の文字列を改変
...
>>> d
{’python’: ’guido’, ’ruby’: ’matz’, ’perl’: ’larry’}
>>> dict([(value, key) for key, value in d.items()])
{’guido’: ’python’, ’larry’: ’perl’, ’matz’: ’ruby’}
...
# リスト内包表記でキーと値を反転させる
第4章
標準ライブラリを使う
本章では,Python に付属している標準ライブラリの使い方,そしてその中でも WWW へのアクセスに利用する
urllib について説明します.
4.1 モジュールとパッケージ
Python にはモジュールとパッケージという概念があります.「1 モジュール=Python の 1 スクリプトファイル」で
あり,モジュールをインポートすることにより,そのスクリプトファイルに書かれている変数やクラス,関数などを利
用できるようになります.またそのモジュールをグループ化し,内包するディレクトリのことをパッケージと呼びま
す.ただし,ただのディレクトリではなく, init .py ファイルを内包していることが必須条件です.このパッケージ
とモジュールの概念により,Python では通常,使用する機能や処理を最小限に保ち,必要に応じてモジュールを取り
込むことで大きなプログラムの開発にも対応できるようになっています.標準ライブラリとは Python があらかじめ保
持しているこのようなモジュールとパッケージの集合体です.
4.2 モジュールのインポート
以下のように import 文と from 文を利用することで,モジュールをインポートすることができます.import 文はモ
ジュール全体のインポート,from 文と import 文を組み合わせるとモジュールの一部を明示的にインポートすること
ができます.パッケージについても特に明確な違いはありません.階層の深いモジュールや関数については,どちらも
通常のオブジェクトのように,ドットで区切ってアクセスしていきます.モジュール名は,ファイル名の「.py」より
前がそのまま適用され,パッケージ名もディレクトリ名がそのまま適用されます.
以下の例では,標準ライブラリから itertools,urllib モジュールの urlopen 関数と urlencode 関数,xml パッケー
ジの etree モジュールの ElementTree クラスをそれぞれインポートし,vars 関数で確認しています.組み込み関数の
vars は,現在の名前空間に定義されている名前と,それに対応するオブジェクトの path などを見ることができます.
基本的に from 文には 1 つしか指定できませんが,import 文には複数の名前を指定することが可能です.
>>> import itertools
>>> vars()
# モジュール全体をインポート
# 現在定義されている名前とオブジェクトの辞書を表示
{’__builtins__’: <module ’__builtin__’ (built-in)>, ’__name__’: ’__main__’,
’itertools’: <module ’itertools’ from ’/usr/lib/python2.5/itertools.pyc’>,
’__doc__’: None, ’__package__’: None}
>>> from urllib import urlopen, urlparse
>>> vars()
# モジュールの一部をインポート,複数指定可能
4.3 実際に標準ライブラリを使ってみる
327
{’urlencode’: <function urlencode at 0x10072cb18>, ’__builtins__’: <module
’__builtin__’ (built-in)>, ’__package__’: None, ’urlopen’: <function urlopen at
0x10056d848>, ’itertools’: <module ’itertools’ from ’/usr/lib/python2.5/itertools.
pyc’>, ’__name__’: ’__main__’, ’__doc__’: None}
>>> from xml.etree import ElementTree
# 深い階層のインポート
>>> vars()
{’urlencode’: <function urlencode at 0x10072cb18>, ’__builtins__’: <module
’__builtin__’ (built-in)>, ’__package__’: None, ’urlopen’: <function urlopen at
0x10056d848>, ’itertools’: <module ’itertools’ from ’/usr/lib/python2.5/itertools.
pyc’>, ’__name__’: ’__main__’, ’ElementTree’: <module ’xml.etree.ElementTree’ from ’/
usr/lib/python2.5/xml/etree/ElementTree.pyc’>’__doc__’: None}
4.3 実際に標準ライブラリを使ってみる
今回は Web ページの解析を行うことを目的とし,標準ライブラリの urllib モジュールと外部モジュールの
BeautifulSoup について解説します.
4.3.1 urllib
urllib モジュールは WWW へアクセスするための便利な機能を提供しています.ここでは,その中でも Web ペー
ジからの HTML 取得や URL エンコードを行うための関数など,よく利用するものについて説明していきます.
使い方
urlopen 関数は,指定した URL にあるファイルを,ファイルライクオブジェクトとして取得します.ファイルライ
クオブジェクトとは,組み込み型のファイルオブジェクトに類似した機能を持つオブジェクトのことです.urlopen 関
数で使用されるファイルライクオブジェクトの場合は,ファイルの内容を全て文字列として展開する read,1 行毎に文
字列として取得する readline,ファイルを閉じる close などの類似メソッドを持っています.
通常,urlopen 関数を使ってファイルを取得する際には,GET リクエストが送信されますが,第 2 引数にクエリ
データを指定した場合は,自動的に POST リクエストに切り替えられます.この際,クエリとして渡されるデータは
URL エンコードされていなければなりません.その URL エンコードするための関数が urlencode です.urlencode
関数は,クエリ文字列の name=value がキーと値に対応した辞書を引数にとり,URL エンコードした文字列を返しま
す.この文字列を引数として urlopen 関数に渡すと POST リクエストになりますが,クエリ付きの GET リクエスト
を送りたい場合は,url に直接連結することで GET リクエストが送信されます.
>>> import urllib
>>> f = urllib.urlopen(’http://example.com/’)
# URL の HTML をファイルライクオブジェクトとして取
得
>>> html = f.read()
# ファイル内容を文字列として取得
>>> html
’<HTML>\r\n<HEAD>\r\n
<TITLE>Example Web Page</TITLE>\r\n</HEAD> \r\n<body>
\r\n<p>You have reached this web page by typing &quot;example.com&quot;,\r\n&quot;
第 4 章 標準ライブラリを使う
328
example.net&quot;,\r\n
or &quot;example.org&quot; into your web browser.</
p>\r\n<p>These domain names are reserved for use in documentation and are not
available \r\n
txt">RFC \r\n
for registration. See <a href="http://www.rfc-editor.org/rfc/rfc2606.
2606</a>, Section 3.</p>\r\n</BODY>\r\n</HTML>\r\n\r\n’
>>> q = urllib.urlencode({’foo’: ’test’, ’bar’: ’ 日本’})
>>> f = urllib.urlopen(’http://example.com’, q)
>>> f = urllib.urlopen(’http://example.com’ + q)
# クエリデータを URL エンコードする
# クエリデータを POST で送信する
# クエリデータをを GET で送信する
4.3.2 BeautifulSoup
BeautifulSoup はサードパーティ製の XML/HTML パーサーです.XML や HTML を階層的なデータ構造に変換
して,Python で簡単に操作できるようにしてくれます.実は,標準モジュールにも ElmentTree という XML パーサ
があるのですが,厳密な XML でなければうまくパースすることができない(例えば br タグは <br /> のようにきち
んと閉じていなければエラーになる)ため,Web ページの HTML などを解析するような用途には,あまり向いていま
せん.それに比べて,BeautifulSoup は少々壊れた HTML/XML でも柔軟に解析してパースしてくれます.操作性に
関しても,ElementTree よりも豊富なメソッドを有しており,より簡易に処理することができます.
インストール
BeautifulSoup はサードパーティ製のモジュールですが,既に PyPI で公開しているため easy install でインス
トールすることができます.
$ sudo easy install BeautifulSoup
使い方
BeatifulSoup は引数に HTML/XML の文字列,またはファイルライクオブジェクトを指定すると,XML/HTML
をパースしてツリー構造のデータ型である BeautifulSoup オブジェクトに変換します.このオブジェクトはかなり
の数のメソッドや属性を持っており,様々な角度から解析することができます.ここではまず,最もよく使うであ
ろう findAll メソッドについて説明します.findAll メソッドは引数に検索したいタグ名や class, id などの属性名を
指定すると,その条件に AND で一致する DOM 要素を取得します.例えば,div タグの要素を取得したい場合は,
「soup.findAll(’div’)」とします.id や href といった属性値を利用して検索することも可能で,id 名が column1 の div
タグ要素を取得したい場合は「soup.findAll(’div’, id=’column1’)」,または「soup.findAll(’div’, ’id’: ’column1’」と
します.ほとんどの属性についてはこの方法で取得できるのですが,class 属性だけは後者の方法で取得することがで
きません.ただしよく使われる属性のため,キーワードを省略して指定できるようになっており,class 名が「item」の
div タグを取得したい場合,「soup.findAll(’div’, ’item’)」のように記述できます.
ここで取得した DOM 要素達は ResultSet オブジェクトというリストライクなオブジェクトに格納された形で返さ
れます.ただし,この ResultSet オブジェクトの扱いには少し注意が必要です.読み込んだ HTML や XML に日本語
や中国語などのマルチバイト文字を含んでいる場合に,このオブジェクトをそのまま print 文などで出力しようとする
と,環境によっては UnicodeDecodeError になる可能性があります.この部分でエラーが出るのを防ぐため,デバッ
グ作業などでも ResultSet オブジェクトを直接 print などで出力するのは控えましょう.出力するのであれば,その中
に格納されている Tag オブジェクトの各属性について表示していくほうがよいでしょう.
この ResultSet オブジェクト内の要素は BeautifulSoup.Tag オブジェクトです.Tag オブジェクトも非常に多くの
属性とメソッドを持っており,その中からさらに findAll メソッドを使って絞り込み検索することもできます.また
4.3 実際に標準ライブラリを使ってみる
329
属性としては,name や string,contents などがあり,それぞれに HTML 要素の属性や,内容などが格納されていま
す.詳しくは公式のドキュメントを参照するか,iPython やインタラクティブシェルで実際に触りながら処理してみま
しょう.
>>> import urllib
>>> from BeautifulSoup import BeautifulSoup
>>> f = urllib.urlopen(’http://example.com/’)
# URL の HTML をファイルライクオブジェクトとして取
得
>>> html = f.read()
# ファイル内容を文字列として取得
>>> soup = BeautifulSoup(html)
>>> ps = soup.findAll(’p’)
# BeautifulSoup でパース
# HTML の中の全ての p タグ一覧を取得
>>> ps
[<p>You have reached this web page by typing &quot;example.com&quot;,
&quot;example.net&quot;,
or &quot;example.org&quot; into your web browser.</p>,
<p>These domain names are reserved for use in documentation and are not available
for registration. See <a href="http://www.rfc-editor.org/rfc/rfc2606.txt">RFC
2606</a>, Section 3.</p>]
>>> for p in ps:
# タグの名前
...
print ’=’ * 5, p.name, ’=’ * 5
...
print ’string: %s’ % p.string
...
print ’contents: %s’ % p.contents
...
print ’attrs: %s’ % p.attrs
...
print ’=’ * 10
# タグ内に文字列しかない場合その文字列を取得
# タグ内のタグや文字列など
# タグの属性の一覧
...
===== p =====
string: You have reached this web page by typing &quot;example.com&quot;,
&quot;example.net&quot;,
or &quot;example.org&quot; into your web browser.
contents: [u’You have reached this web page by typing &quot;example.com&quot;,
\r\n&quot;example.net&quot;,\r\n
or &quot;example.org&quot; into your web browser.’]
attrs: []
==========
===== p =====
string: None
contents: [u’These domain names are reserved for use in documentation and are not
available \r\n
for registration. See ’, <a href="http://www.rfc-editor.org/rfc/
rfc2606.txt">RFC
2606</a>, u’, Section 3.’]
attrs: []
==========
第 12 回 演習課題
目標
Python のライブラリを用いてスクレイピングを行います.
まず,iPython を用いて HTML を取得・保存して下さい.次に,保存した HTML に対しスクレイピングを行っ
て下さい.
※発展は任意課題とします.余裕のある方は挑戦してみて下さい.
課題 1 スクレイピング
Web サイトのデータを必要な部分だけ抽出して利用することを「スクレイピング」と呼びます.本課題では,
Yahoo !ニュースの Web ページから HTML を取得し,その内容の解析を行います.
1–1
5.1 節を参考にして easy install と iPython をインストールし, BeautifulSoup をインストールして下さい.そ
して Firefox に firebug をインストールして下さい.
1–2
Python 2.x 系はデフォルトのままでは,ASCII 文字がデフォルトエンコーディングに指定されているため,日本語
のエンコードでは問題が発生する可能性があります.その問題解消のために site-packages 内に以下の内容を記述した
ファイルを sitecustomize.py と名付けて保存して下さい.
import sys
sys.setdefaultencoding(’utf-8’)
site-packages の場所は,以下のコマンドを実行すると見つけることができます.
$ python -c "from distutils.sysconfig import get python lib; print
get python lib()"
1–3
4.3 で解説した urllib モジュールを使って,Yahoo!ニュース(http://headlines.yahoo.co.jp/hl)のページか
ら「ダルビッシュ」でニュース検索した検索結果ページの HTML を取得して下さい.そしてその HTML をファイル
としてホームディレクトリに保存して下さい.
その際, iPython を起動し, iPython を使って HTML の取得・保存を行って下さい.
ファイルの取り扱い方法は以下を参考にして下さい.
>>> f = open(’file.html’, ’w’)
# 書き込みモードでファイルを開く
331
>>> contents = ’abcdefg’
# 文字列を書き込む
>>> f.write(contents)
# ファイルを閉じる
>>> f.close()
>>> f = open(’file.html’)
>>> f.read()
# さっきのファイルを開く
# 内容を全て文字列として出力する
’abcdefg’
>>> f.read()
# オブジェクトが空になる(物理的なファイルそのものの中身は変更されない)
’’
>>> f.close()
# ファイルを閉じる
1–4
前問と同じように HTML を取得し,その検索結果ページから記事のタイトルを抜き出して,順番に出力するコード
を書いて下さい.今回は,darvish.py というファイルを作成し,その中に処理を記述して下さい.
その際に Firefox からも検索結果ページを表示し,Firebug を起動して HTML のどの要素にタイトルが含まれてい
るのかを確認しつつ,iPython でも処理を逐次確認しながら作業を行うと効率的に作業が進みます.
以下,簡単な Firebug の使い方について説明します.Firebug をインストールして Firefox を再起動したら,以下の
ようにして Web ページ内の HTML 構造を調査して下さい.
1. Firefox のステータスバーにあるホタルアイコンをクリック
2. Firebug ウィンドウが表示されるので,左上左から 2 番目のボタンをクリック
3. そのまま Web ページ上にマウスオーバーさせると,その直下の HTML 構造をインタラクティブに表示
ここでは HTML のインスペクト機能についての説明のみにとどめますが,他にも直接 CSS や HTML を修正して見
た目を変更したり,JavaScript を実行したりなど,Firebug には Web 開発を行うにあたって非常に便利なデバッグ環
境が数多く提供されています.興味のある方は,Web 上に多くの解説記事や説明が出ているので,参照してみること
をおすすめします.
HTML のテキストを処理するのには文字列操作の知識が必要です.文字列の操作方法については以下を参考にして
下さい.
>>> s = ’Hokkaido’
# 特定の文字列で分割する
>>> s.split(’o’)
[’H’, ’kkaid’, ’’]
>>> s.split(’o’, 1)
# 分割回数を指定できる
[’H’, ’kkaido’]
>>> s.rsplit(’o’, 1)
# 右から 1 回だけ分割する
[’Hokkaid’, ’’]
本課題では,文字列のメソッドによって文字列を分解し,分解した文字列に対してスライスをうまく利用することで
処理がしやすくなります.
発展
前問のスクリプトを改良し,検索結果ページから記事のタイトルと更新日時,報道機関名を抜き出し,’title’: 記事タ
イトル, ’date’: 更新日時, ’press’: 報道機関名となるような辞書のリストを作成して,表示させるスクリプトを書いて
第4章
332
第 12 回 演習課題
下さい.今回のファイル名は darvish dict.py とします.
[{’title’: ’ ダ ル ビ ッ シ ュ..’, ’date’: ’12 月 16 日 (火) 10 時 32 分’, ’press’: ’ 毎 日 新
聞’}, {’title’: ’ ダル...’, ’date’: ’12 月 16 日 (火) 12 時 30 分’, ’press’: ’ スポーツ報知’}, ...]
発展
前問で書いたスクリプトを,全ての検索結果ページについて処理を行うように改良し,報道した回数が多い順に報道
機関名でソートして,以下のような体裁で結果を出力して下さい.ファイル名は darvish all.py とします.
sum press
===============
100 毎日新聞
60
スポーツ報知
20
日刊スポーツ
.
.
.
参考文献
[1] Python Programming Language, http://python.org/
[2] Python Japan User’s Group, http://www.python.jp/Zope
[3] 特集:もっと知りたい Python3000 | gihyo.jp … 技術評論社, http://gihyo.jp/dev/feature/01/python3000
[4] Beautiful Soup, http://www.crummy.com/software/BeautifulSoup/
第 13 回
Web サービス入門
サービスとしてのアプリケーションという考え方と Web サービスが登場した背景について解
説し,Web サービスのベースとなる XML の基本について具体的に解説し,その応用例を示し
ます.また,SOAP メッセージの形式と標準化についても解説します.演習では,XML ドキュ
メントの妥当性の検証や DTD の定義を行い,XML プログラミングの基本について学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
Web サービス
Web サービスとは分散した端末間の相互運用を行うための仕組みで,SOAP により XML と HTTP を用いて通信
を行うよう規定したシステムです.Web サービスでは適切な Web サービスを検索し,そのサービスの場所や仕様など
の情報を取得し,自律的に相互通信を行うことが可能なシステムが構築されています.
1.1 Web サービスとは
Web サービスの概念図を図 1.1 に示します.
普段,私たちが Web ブラウザなどのデスクトップアプリケーションから利用している Web 上のシステムは,Web
サーバで稼働している Web アプリケーションと HTTP などのプロトコルを用いて通信を行うことで実現しています.
通信とは図 1.1 左のクライアントと中央の Web サーバ間での通信です.ここでいう,Web アプリケーションとは Web
サーバ上で稼働しているウェブに関わるソフトウェアを指します.Perl
*1 や
PHP(第 11 回参照),Python (第 12 回
参照)などのスクリプト言語を利用した CGI スクリプト(第 3 回参照)による実装が代表的です.
しかし,Web サービスとは,このクライアントと Web サーバ間の通信のことを指しません.Web サービスの実体は
クライアントと直接通信を行っている Web サーバではなく,さらにその先の Web サービスが稼働している Web サー
バにあります.Web サービスでは「Web サービスを提供している Web サーバ」と「Web サービスのクライアント」
との間で SOAP(4 章参照)などのプロトコルを用いて XML データによる相互通信を行っています.これは図 1.1 中
央の Web サーバ (クライアント) と右の Web サーバ間での通信です.この相互通信はエージェントによって自律的に
行われます.従って,クライアントが直接通信を行っている Web サーバ(Web アプリケーションが稼働している Web
サーバ)は,Web サービスのクライアントでもあると言えます.
このように,Web サービスを利用する際には,普段私たちが Web サーバと直接行っている通信とは別に,Web サー
ビスを提供している Web サーバとの相互通信が自律的に行われています.人間が利用するのが Web アプリケーショ
ンであるのに対して,コンピュータが利用するのが Web サービスであると言えます.
1.2 Web サービスの定義
Web 技術に関する標準化団体である W3C(5.1.1 節参照)では,Web サービスを以下のように定義しています [6].
A Web service is a software system designed to support interoperable machine-to-machine interaction over
a network. It has an interface described in a machine-processable format (specifically WSDL). Other systems
interact with the Web service in a manner prescribed by its description using SOAP messages, typically conveyed
using HTTP with an XML serialization in conjunction with other Web-related standards.
*1
Practical Extraction and Report Language.スクリプト言語のひとつで柔軟な正規表現による文字操作や連想配列の採用,モジュール・
ライブラリ (CPAN) による拡張性の高さなどが特徴.
1.2 Web サービスの定義
337
図 1.1
Web サービスと Web アプリケーション
この定義によると,Web サービスとはネットワーク上の端末同士が,相互に利用可能なソフトウェアシステムのこ
とを指すとしています.また,Web サービスのインタフェイス情報(使用するプロトコルやサービスの URL 情報な
ど)は,機械処理可能な形式で記述された文書を利用するとしています.このインタフェイス情報の利用には「特に
WSDL」と記述されており,WSDL(1.3 節参照)を利用することを明記しています.また,端末間の通信プロトコル
には,HTTP によって XML で記述されたデータをやりとりする SOAP(4 章参照)を用いるとしています.
ここでは,言及しませんが,標準化団体 OASIS(5.1 節参照)によって標準仕様とされている UDDI(1.3 節参照)
という Web サービスを管理する仕組みも存在します.これは,企業が公開している Web サービスの概要や設置場所,
管理者などの情報を管理するデータベースです.
図 1.2 Web サービスの検索
これらをまとめた Web サービスの概念図を,図 1.2 に示します.Web サービスを利用する際には,まず UDDI に
よって Web サービスを検索し,WSDL によってその利用方法を理解します.そして,実際の Web サービス利用には
第 1 章 Web サービス
338
SOAP によって XML データを送受信することになります.Web サービスの提供者も同様に,UDDI にサービスを登
録し,WSDL に利用方法を記述します.そして,実際の Web サービス提供には,XML データを用いて SOAP によっ
てデータを送受信します.
ただし,これらは W3C による定義であり,一般に Web サービスという場合,必ずしもプロトコルとして SOAP を
用いるとは限らず,WSDL や UDDI などの仕組みを使用するとも限りません(本テキストで「Web サービス」とあ
る場合,特別な断り書きがない限り前述の W3C による定義を指すこととします).例えば,REST (Representational
State Transfer) は,SOAP や WSDL,UDDI を使用することなく Web サービスを提供できます.REST はリソース
に着目することでシンプルな通信方式を実現しています.必要な情報(リソース)がどこにあるのか,ということに
着目した方式で,通信に必要となるのはリソースの URI です.従って,URI で問い合わせるだけなので,この方式の
プロトコルには一般的に用いられている HTTP を用いることで実現可能で,あり WSDL のようにプロトコルなどを
規定したインタフェイス情報も必要としません.このような,REST の思想に則った Web サービスを RESTful Web
サービスと呼ぶこともあります.REST については,第 15 回で解説します.
1.3 Web サービスの技術
Web サービスの主な要素技術には UDDI や WSDL, XML, SOAP などがあります.この節では簡単にそれぞれの
概要を紹介します.
1.3.1 UDDI
UDDI (Universal Description, Discovery and Integration) は Web サービスの詳細情報が登録されているデータベー
スです.2005 年に UDDI version 3.0 が OASIS 標準となっています [18].
UDDI は主に企業間の取引において,必要な Web サービスを検索するためのデータベースです.登録情報には表 1.1
に示す 4 つのカテゴリが存在します.これらのような情報が登録されているデータベースを用いることで,企業名や
サービス内容,または技術的要素といった側面から Web サービスを検索することが可能となります.
表 1.1
UDDI の登録カテゴリ
category
summary
Business Entity (White Pages)
企業の名前などの詳細情報など
Business Service (Yellow Pages)
サービス内容やカテゴリ情報など
Binding Template (Green Pages)
サービス内容の技術内容
tModel
インタフェイス情報(WSDL での当該情報へのポインタ)
1.3.2 WSDL
WSDL (Web Services Description Language) は Web サービスの通信プロトコルやデータ型,サービスの URL など
といったインタフェイス情報を定義します.2001 年に W3C によって WSDL 1.1 が勧告されています [7].
WSDL は XML で記述され,その名前空間 URI (2.6 節参照) は http://schemas.xmlsoap.org/wsdl/となります.
WSDL 定義文書は通常,Web サービスが稼働している Web サーバに設置されます.Web サービスに UDDI と WSDL
を用いる場合,UDDI の tModel にはこの WSDL 文書へのポインタが記述されます.
1.3 Web サービスの技術
339
1.3.3 SOAP
SOAP は Web サービスにおいて,Web サーバと Web サーバのクライアント間での相互通信を行う際の通信方式な
どを規定したプロトコルです.詳細は 4 章で解説します.
1.3.4 XML
XML は構造化したデータを表現するためのマークアップ言語のひとつです.Web サービスでは,SOAP を用いた
通信の際の共通言語として用いられます.詳細は 2 章で解説します.
第2章
XML
XML (Extensible Markup Language) はデータや文書をその論理構造や意味情報などに基づいて,タグ付けを行うこ
とによって記述するマークアップ言語のひとつです.XML では,その目的に応じて任意のタグを定義し,記述するこ
とができます.1998 年に W3C によって XML 1.0 が,2004 年には XML 1.1 が勧告されています [8, 9].
2.1 XML の基本要素
XML はタグによって文書の構造化を行います.タグの基本的な構成要素は,要素と属性です.ここでは,XML 文
書の詳細な解説の前に,前提知識として必要となるタグの記述方法とその用語について解説します.
2.1.1 要素
XML で最も基本的な概念は要素 (element) です.文書の内容 (content) を要素のタグ (tag) によってマークアッ
プ (markup) することで文書を意味付けします.タグとは,< 要素名 > のように要素名を < > で括ったものです.タ
グには,開始タグ (start-tag) と終了タグ (end-tag) があります.終了タグは </要素名 > のように開始タグの要素名
の先頭に / を付加します.XML 文書は,その内容を開始タグと終了タグで囲むこと(マークアップ)により,文書を
意味付けして記述します.基本的なタグの表現は以下のようになります.
<開始タグ>内容<終了タグ>
以下に,具体的な内容を要素タグを用いて表現した例を示します.
<都道府県>北海道</都道府県>
<市>札幌</市>
<市>富良野</市>
<町>洞爺湖</町>
<湖>洞爺湖</湖>
ここで,北海道を都道府県要素,札幌,富良野を市要素としてマークアップしています.また,洞爺湖に対しては,
町という要素と湖という要素でマークアップしています.
XML は文書の意味情報に基づいて記述するため,同じ洞爺湖という内容でも,どのような文脈で用いられるか考慮
する必要があります.このような指向から,XML では装飾の目的でのマークアップは認められていません.本テキス
トでは扱いませんが,XML 文書の装飾目的として開発された言語に XSL (eXtensible Stylesheet Language) があり
ます.
2.1 XML の基本要素
341
2.1.2 属性
要素は,属性 (attribute) を持つことができます.これによって,同一の要素名であっても異なるデータを表現でき
ます.属性は開始タグ内の要素名以降に属性=”属性値” ,もしくは 属性=’ 属性値’ と記述します.
<開始タグ 属性名="属性値">内容<終了タグ>
以下に同一の要素名を属性値を用いることで異なるデータとして表現した具体的な例を示します.
<市 都道府県="青森">青森</市>
<市 都道府県="青森">八戸</市>
<市 都道府県="岩手">盛岡</市>
<市 都道府県="宮城">仙台</市>
これらの例では市が要素であり,その内容は青森や八戸などです.また,都道府県が属性としてそれぞれ付加されて
おり,その属性値にそれぞれ青森や岩手などを付加することで,それぞれの市要素を区別しています.
2.1.3 空要素
内容が存在しない要素は空要素 (empty–element) と呼び,開始タグと終了タグで囲む以外にも単一の空要素タ
グ (empty–element tag) で表現することができます.以下に,空要素の表現例を示します.
<要素名></要素名>
<要素名 />
<要素名 属性="属性値"></要素名>
<要素名 属性="属性値" />
空要素は <tag></tag> と記述することができますが,これは <tag /> のように省略することができます.終了タ
グ </tag> とは異なることに注意して下さい.また,空要素であっても,その要素に対する属性値を与えることができ
ます.
以下に,空要素の具体例を示します.
<br></br>
<hr />
<img src="./img/image.jpg" />
補足
XML では,<br> や <hr> などのように,開始タグのみで終了タグのない要素は認められません.しかし,<br> は
HTML 4 において改行要素として問題なく扱えます.これは,HTML 4 は SGML の仕様に基づく言語であり,XML
ではないからです.一方で,XML の仕様を踏襲した XHTML や HTML 5 などでは,改行要素は <br />,または
第 2 章 XML
342
<br></br> と記述する必要があります.
2.1.4 XML の構造
XML 文書は階層構造で表現されます. ルート要素を頂点に,要素を入れ子構造(ネスト: nest)として記述するこ
とで,階層的なデータ構造が表現されます.以下に,階層化された単純な XML 文書の例を示します.
<ルート要素>
<要素 A 属性="属性値">内容1</要素 A>
<要素 B>
<要素 C>内容2</要素 C>
</要素 B>
</ルート要素>
この例では,ルート要素は要素 A と要素 B を含んでおり,要素 B には要素 C が含まれています.
XML の木構造
これらの要素の入れ子関係を要素の親子関係としてみなすことで,XML 文書を木構造として捉えることができます.
例えば,ルート要素に対して要素 A と要素 B は入れ子になっていることから,この関係はルート要素を親,要素 A と
要素 B を子とする親子関係とみなすことができます.さらに,要素 B に対して要素 C が入れ子になっていることか
ら,この関係は要素 B を親,要素 C を子とする親子関係にあります.また,ルート要素に対して要素 C は孫要素であ
ると言えます.
この XML 文書の木構造を視覚的に表現した図を図 2.1 に示します.この図で枠で囲まれているノードは要素を表し
ています.要素の属性が存在する場合は,要素の枠中の 2 行目に括弧書きで属性と属性値を示しています.また,枠で
囲まれていない端点のノードは要素の内容を示しています.
このように,XML 文書の各要素は階層構造を取っており,その関係は木構造として表現できます.
誤った XML 構造
XML 文書を記述する際には要素の入れ子の関係が厳密に記述されている必要があります.以下に,誤った XML 文
書の例を示します.
<ルート要素>
<要素 A>
<要素 B>内容
</要素 A>
</要素 B>
</ルート要素>
ここでは,要素 B は要素 A の子要素ですが,子要素の要素 B が閉じられる前に,親要素の要素 A が閉じられていま
す.このように,入れ子関係が正しく対応していない文書は XML として認められず,扱うことができません.
2.1 XML の基本要素
343
図 2.1 XML の木構造
第 2 章 XML
344
2.2 XML 文書の構造
XML 文書は XML 宣言,DTD (DOCTYPE 宣言),そして XML インスタンスの 3 つの部分からなります.これら
は,この順序で記述する必要がありますが,XML 宣言と DTD は必ずしも記述する必要はありません.
図 2.2 に XML 文書の例を示します.XML 宣言は XML 文書の先頭に記述し,XML のバージョン情報や XML 文
書のエンコード情報などを宣言します.DTD は XML 文書の構造を定義するもので,XML 文書に含まれる要素や属
性,実体,記法の定義を行います.ここでは,文書に含まれる要素の親子関係や順序,回数,属性の定義,実体参照
(文字列の置換)などが定義されます.XML インスタンスは XML 文書の実際のデータが記述される部分です.DTD
が記述されている場合は DTD に基づき,文書をタグ付きデータとして記述します.
図 2.2
XML 文書の構造
2.3 XML 宣言
345
それぞれの詳細を解説していきます.
2.3 XML 宣言
XML 文書の先頭には,この文書が XML 言語に従って記述されていることを示す宣言文を記述します.XML 宣言
には 3 種類の属性があり,使用する XML 言語のバージョンの指定を行う version 属性,記述されている文書の文字
コードの指定を行う encoding 属性,外部の DTD を用いるかどうかを指定する standalone 属性があります.表 2.1 に
属性とその属性値の例を示します.
表 2.1
XML 宣言の属性
属性
属性値
version
1.0, 1.1
encoding
utf-8, euc-jp, shift-jis など
standalone
yes, no
version 属性では XML のバージョンを指定します.2010 年現在,XML 1.0 と XML 1.1 が勧告されており,属性値
として 1.0,および 1.1 が指定可能です.encoding 属性には XML 文書の文字コードを指定します.ここで,XML 文
書の文字コードが UTF–8,もしくは UTF–16 であれば encoding 属性は省略することができますが,XML の言語仕
様ではその場合であっても encoding 属性を記述することが推奨されています.standalone 属性は XML 文書の定義を
行う DTD(文書型定義)を外部のものを参照するか,内部のものを参照するかを指定します. 外部 DTD を参照する
場合は no を指定し,内部 DTD を参照する場合は yes を指定します.
従って,多くの場合,例えば以下のような宣言文を XML 文書の先頭に記述することになります.なお,この宣言文
は文書の先頭に記述する必要があり,さらに宣言文の前に空白や改行などを挿入しないように気を付ける必要があり
ます.
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
2.4 DTD(文書型定義)
DTD(Document Type Definition/Declaration
*1 :
文書型定義)は SGML
*2 や
XML 言語の文書構造を定義するた
めのスキーマ言語(文書構造を定義するための言語)のひとつです.DTD によって文書の構造を定義することで,文
書の妥当性を検証することができます.
DTD は,以下の 4 種類の宣言によって構成されます.
• 要素型宣言 (Element Type Declaration)
• 属性リスト宣言 (Attribute-list Declaration)
• 実体宣言 (Entity Declaration)
• 記法宣言 (Markup Declaration)
*1
*2
SGML は Document Type Definition,XML は Document Type Declaration.
Standard Generalized Markup Language.文書の電子化の目的で開発された,HTML や XML の元となったマークアップ言語.ISO に
より 1986 年に標準化.
第 2 章 XML
346
これらの宣言文はどの順序で記述しても構いません.また,それぞれの宣言文は,宣言の種別でまとめて記述する必
要はなく,宣言の種別に関わらず混在して記述することができます.
以下それぞれについて解説します.
2.4.1 要素型宣言
要素型宣言は文書内に記述する要素名を宣言し,関連要素の親子関係や子要素の出現順序,出現数を定義します.
要素型宣言は以下のように記述します.
<!ELEMENT 要素名 構成要素>
要素名には親要素名を記述し,構成要素は親要素が持つ子要素名を記述します.子要素としてもつ構成要素には
表 2.2 に示す 4 種類があります.
表 2.2
表現
構成要素の種類
意味
’EMPTY’(空要素) 空要素の宣言.’EMPTY’ と記述.
’ANY’(任意要素) 宣言された要素の順序を規定しない.’ANY’ と記述.
要素内容
子要素に内容を持たず,要素のみを子要素として持つ場合.
混合要素
子要素に内容と要素を持つ場合.
空要素
空要素は,親要素の内容が空であるものを指します.この場合,構成要素には EMPTY と記述します.以下に,具体
的な例を示します.
<!ELEMENT br EMPTY>
<!ELEMENT hr EMPTY>
この例では,br 要素と hr 要素は空要素として定義されていますので,文書中では¡br /¿や¡hr /¿などと記述します.
任意要素
任意要素は親要素が持つ子要素を特に規定しません.従って,DTD によって定義された要素であれば,出現順序な
どを気にすることはなく,自由に子要素として持つことができます.構成要素には ANY と記述します.
<!ELEMENT element ANY>
要素内容
要素内容 (Element Content) は親要素が内容を持たず,要素のみを子要素として持つ場合を指します.例えば,以
下のような場合です.
2.4 DTD(文書型定義)
347
<親要素>
<子要素 1>内容 1</子要素 1>
<子要素 2>内容 2</子要素 2>
</親要素>
この場合,以下のように,構成要素に子要素を列挙することで定義します.列挙する場合の構成要素は,子要素を括
弧で括ります.
<!ELEMENT 親要素 (子要素 1, 子要素 2)>
また,子要素は文書中に出現する順序を定義することができます.子要素の出現する順番は,要素を「,」(カンマ)
や「—」
(縦棒)で区切ることで定義します.「,」で区切った場合には,親要素の子要素としてすべての要素が出現する
必要がありますが,「—」で区切った場合はそれらの要素のいずれかひとつが出現する場合を意味します.
具体的な要素型宣言の例を挙げます.
<!ELEMENT 市 (名前, 人口)>
<!ELEMENT シンボル (花 | 木 | 鳥)>
この例では,市要素は子要素に名前と人口を持ち,この順番に必ず記述されることを定義しています.また,シンボ
ル要素は子要素に花と木,鳥要素のうちのいずれか 1 つが出現することを定義しています.
さらに,子要素は文書中に出現する回数を定義できます.表 2.3 に子要素の出現数の規則に使用できる記号を示しま
す.子要素の出現数(文書全体の出現数ではなく,親要素に対する出現数)は「?」や「+」,「*」の記号を用いて指定
します.
「?」は一度,もしくは出現しない場合を意味し,
「+」は 1 回以上出現する場合,
「*」は 0 回以上出現する場合
をそれぞれ意味します.特に記号を用いない場合は,必ず一度だけ出現する場合を表します.
表 2.3
表現
要素型定義に使用できる表現
意味
?
出現しないか,1 回だけ出現する
+
1 回以上出現する
*
0 回以上出現する
記号なし
1 回だけ出現する
以下に,出現回数の定義を含んだ,具体的な要素型宣言の例を挙げます.
<!ELEMENT 市 (名前, 人口, シンボル +)>
<!ELEMENT シンボル (木 | 花 | 鳥 | その他*) >
この例では,親要素である市要素は名前,人口,およびシンボル要素の少なくとも 3 つの子要素を持ち,この順番で
出現することを定義しています.名前と人口要素は一度だけ出現し,シンボル要素は「+」が付加されているため,1
回以上出現することが定義されています.また,「,」で区切っているため要素の内容が存在しない場合であっても要素
348
第 2 章 XML
を空要素として記述する必要があります.
親要素のシンボル要素は,子要素として木,花,鳥,およびその他要素を持ちます.木,花,鳥要素は「—」で区切
られているため,いずれかひとつの要素のみが出現します.また,その他要素に付加されている「*」は 0 回以上出現
する場合を意味しますので,内容がない場合と複数存在する場合にも対応しています.
なお,この定義からシンボル要素は市要素に対する孫要素であると言えます.
混合要素
混合要素 (Mixed Content) は親要素が子要素として内容と要素を持つ場合を指します.混合要素は,その順序を規
定しません.また,子要素として要素を持たず,内容のみを持つ場合も混合要素と呼ばれます.
混合要素は,例えば以下のような場合です.
<親要素>
内容 A
<子要素 1>内容 1</子要素 1>
内容 B
<子要素 2>内容 2</子要素 2>
内容 C
</親要素>
要素の内容を示すには,構成要素に#PCDATA と記述します.この場合,構成要素に以下のように記述することで
定義します.
<!ELEMENT 親要素 (#PCDATA | 子要素 1 | 子要素 2)* >
混合要素は,その出現順序を規定しないので,「—」で区切ります.また,出現回数も制限しないため,全体に「*」
を付加することで定義します.
これは,実際には HTML や XHTML での段落要素 (p) に対する,強調要素 (emph) などの定義に用いられていま
す.この宣言の例と (X)HTML 文書の例を,以下に示します.
宣言文
<!ELEMENT p (#PCDATA | emph)* >
文書の例
<p><emph>混合要素</emph>は親要素が子要素として<emph>内容と要素を持つ場合</emph>を指します.</p>
また,子要素に要素を持たず,内容のみを持つ場合は,以下のように記述することで定義できます.
<!ELEMENT string (#PCDATA) >
この例では,string 要素は子要素として要素を持たず,文字列のみが記述された内容のみを持つことを定義してい
2.4 DTD(文書型定義)
349
ます.
2.4.2 属性リスト宣言
属性リスト宣言では,文書内の要素が持つ属性の型やその初期値を定義します.属性リスト宣言は,以下の書式に
よって定義されます.
<!ATTLIST 要素名 属性名 属性値の型 "初期値">
属性値の型として用いることができるものを表 2.4 に示します.また,初期値として指定することができるものを
表 2.5 に示します.ここで,記述形式の名前とは,XML で要素名や属性名などに使用することが許されている文字で
構成されてるものを指し,名前トークンとは 1 文字目に数字や「-」(ハイフン),「.」(ピリオド)を使用できる名前を
指します.例えば,名前は 1 文字目に数字を使用することができませんが,名前トークンでは 1 文字目に数字を使用す
ることができます.
表 2.4 属性リスト宣言に指定する属性値の型
型
意味
記述形式
CDATA
文字データ
任意
ID
識別子 (id 属性)
名前の形式で記述
IDREF
ID 型の参照値
名前の形式で記述
IDREFS
複数の ID 型の参照値
複数の名前を記述
ENTITY
実体参照
名前の形式で記述
ENTITIES
複数の実体参照
複数の名前を記述
NMTOKEN
名前トークン型文字列
名前トークンで記述
NMTOKENS
複数の名前トークン型文字列
複数の名前トークンで記述
表 2.5 属性リスト宣言に指定する属性値の初期値
記述方法
意味
”文字列”
文字データ
#REQUIRED
属性の記述が必須.
#IMPLIED
属性の記述が省略可能.
#FIXED ”文字列”
”文字列”以外の指定が不可.
CDATA 型
CDATA (character data) 型は,属性値に自由な文字列を記述することができます.CDATA 型を含んだ具体的な属性
リスト宣言の例を,以下に示します.
<!ELEMENT シンボル (木, その他 +)>
<!ELEMENT 木 (#PCDATA)>
第 2 章 XML
350
<!ELEMENT その他 (#PCDATA)>
<!ATTLIST その他 種別 CDATA #IMPLIED>
この例では,その他要素の種別属性を定義しています.属性値の型が CDATA なので属性値には文字列が記述され,
初期値には#IMPLIED が記述されているため属性値が省略可能であることを定義しています.
ID 型
ID 型は,文書全体で一意な属性値をとります.従って,ID 型の属性を参照することにより,特定の要素を識別する
ことができます.ID 型を含んだ具体的な属性リスト宣言の例を,以下に示します.
<!ELEMENT 都道府県 (名前, 人口)>
<!ATTLIST 都道府県 コード ID #REQUIRED>
<!ELEMENT 名前 (#PCDATA)>
<!ELEMENT 人口 (#PCDATA)>
この例で都道府県は 47 種類しか存在しないため,それぞれを個別に区別することができます.このように,文書中
で一意に決まる要素に対する属性を設定する場合に,ID 型を用います.
また,ID 型は初期値として,#REQUIRED か#IMPLIED のいずれかをとります.
複数の属性の定義
属性値を複数指定したい場合があります.そのような場合の属性リスト宣言は,以下のように属性の定義を列挙して
記述します.
<!ELEMENT 都道府県>
<!ATTLIST 都道府県 コード ID #REQUIRED
…………………………
…………………………
名前 CDATA #REQUIRED>
2.4.3 実体宣言
DTD で定義された文字列やファイルを実体 (entity: エンティティ) と呼びます.実体参照を用いることで,XML イ
ンスタンスに繰り返し登場する文字列を置換したり,外部ファイルを参照することができます.
実体宣言は以下のように行います.
<!ENTITY 実体名 "文字列">
<!ENTITY 実体名 識別子 "URI">
2.4 DTD(文書型定義)
351
実体参照を用いた文字列の置換
DTD 中で実体宣言された実体は,XML インスタンス中で&実体名; とすることで,その実体を呼び出すことができ
ます.以下のように宣言を行うことにより,XML インスタンスから実体参照ができるようになります.
<!ENTITY 実体名 "文字列">
具体的な宣言と実体の呼び出しを以下に示します.
実体宣言
<!ENTITY deadline "2010/03/31">
XML インスタンス
<date>&deadline;</date>
この例では,XML インスタンス中で,&deadline; として実体 deadline が呼び出されるため,実際には XML イン
スタンスに¡date¿2010/03/31¡/date¿と記述したことと同義になります.
実体参照を用いたファイルの呼び出し
URI を用いて,ファイルの呼び出しを行うことができます.ファイルの実体宣言には URI を利用したシステム識別
子を用いる方法と,公開識別子を用いる方法があります.
<!ENTITY 実体名 識別子 "URI">
識別子には,システム識別子を用いる場合には SYSTEM を,公開識別子を用いる場合には PUBLIC を指定します.
以下に,システム識別子を用いた URI を利用して参照する例を示します.
<!ENTITY municipality SYSTEM "http://example.com/municipality.xml">
このように,http などのプロトコルを用いた URI を利用してファイルを指定することができます.ほかにも,file や
ftp などを指定することが考えられます.
標準化団体や業界団体によって定められ,広く一般に公開されている識別子を公開識別子と呼びます.公開識別子は
以下のように記述されます.
"-//組織名//データの種類 識別名//言語"
例えば,XHTML 1.1 の DTD を表す公開識別子は "-//W3C//DTDXHTML1.1//EN" のように記述されます.これは,
公開している組織名が W3C で,データの種類が DTD,識別名は XHTML 1.1,言語が EN であることから英語であ
るということが分かります.
公開識別子による実体参照は,以下のような形式で記述します.
第 2 章 XML
352
<!ENTITY 実体名 PUBLIC 公開識別子 "URI">
また,XHTML 1.1 の DTD ファイルの実体の URL は "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
です.従って,公開識別子を指定した XHTML 1.1 の実体参照は以下のようになります.
<!ENTITY html "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2.4.4 DOCTYPE 宣言
これまで,DTD による XML インスタンスの定義方法を見てきましたが,これらの定義は DOCTYPE 宣言に DTD
を含めることによって宣言されます.また,DTD で定義した宣言は XML インスタンスに適用することで XML 文書
としての妥当性を検証できます(2.7 節参照).DOCTYPE 宣言はファイルを参照する外部サブセットを用いる方法
と,XML 文書中に直接記述する内部サブセットを用いる方法があります.
内部サブセットを用いる場合
内部サブセットを用いる場合には,以下のように DTD を直接 DOCTYPE 宣言内に記述します.
<!DOCTYPE ルート要素名 識別子 [DTD]>
DTD に記述する各宣言の順番などは任意であり,出現順番や宣言の種類などに関わらず自由に記述することができ
ます.また,行頭に空白が挿入されていても問題がないため,宣言を XML インスタンスの構造に従ってインデントさ
れた形で記述するなど自由に記述して構いません.
具体的な宣言の例を以下に示します.
<!DOCTYPE city [
<!ELEMENT city (name, population)>
<!ATTLIST city code CDATA #REQUIRED>
<!ELEMENT name (#PCDATA)>
<!ELEMENT population (#PCDATA)>
]>
この宣言に従って構成された XML インスタンスの例を示します.
<city code="100">
<name>札幌</name>
<population>1889352</population>
</city>
2.5 XML インスタンス
353
外部サブセットを用いる場合
外部サブセットを用いる場合は,2.4.3 節での実体参照の場合とほぼ同様に宣言できます.
識別子には PUBLIC(公開識別子)か SYSTEM(システム識別子)のいずれかを指定します.システム識別子を用
いる場合は,以下のように DTD の URI を直接指定します.URI には http や file などを指定することができます.
<!DOCTYPE ルート要素名 SYSTEM "DTD の URI">
具体的な宣言文の例は以下のようになります.
<!DOCTYPE municipality SYSTEM "http://example.com/municipality.dtd">
また,公開識別子を指定する場合には,DTD の組織名などの情報を併記します.以下に,公開識別子を指定する場
合の例を示します.
<!DOCTYPE ルート要素名 PUBLIC "-//組織名//DTD 識別名//言語" "DTD の URI">
以下に,W3C によって定義された外部サブセットを指定した,XHTML による XML 文書の DOCTYPE 宣言の例
を示します.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2.5 XML インスタンス
XML インスタンスは XML 文書の実際のデータを記述した部分です.XML インスタンスは要素の入れ子構造が正
しい関係性になっている必要があり,DTD による定義がなされている場合にはその定義に従った構造である必要があ
ることが求められます.XML の基本的な構成要素は 2.1 節で解説しましたので,ここでは具体的なデータベースの
XML 文書を構成する例を示します.
日本の市区町村を都道府県ごとにまとめ,それぞれの人口と制定されているシンボルを表現する XML 文書を作成す
ることとします.まず,基本的な要素単位のひとつである市の情報の構成例を示します.
<市 コード="100">
<名前>札幌市</名前>
<人口>1889352</人口>
<シンボル>
<木>ライラック</木>
<花>スズラン</花>
<鳥>カッコウ</鳥>
<虫 />
第 2 章 XML
354
<魚 />
</シンボル>
</市>
図 2.3 市の情報をまとめた XML の木構造
市の情報全体を市要素で表現します.市は複数存在するので,ここではコード属性を設定して区別することにし
ます.
市要素は,名前,人口,シンボル要素をそれぞれ持つこととします.
また,多くの自治体で複数のシンボルを制定しているため,木や花,鳥要素を作成します.シンボルとして制定され
るものには木や花,鳥の他にも,例えば旭川市では虫としてカンタン,函館市では魚としてイカを制定しているようで
す.そこで,札幌市では制定していませんが,虫,魚要素を空要素として記述しています.この XML 文書を木構造で
表現した図を図 2.3 に示します.
また,この XML 文書は要素として表現していたシンボル要素の子要素である木や花要素などをシンボル要素の属性
として指定することも考えられます.以下に,シンボル要素に種別属性を設定し,XML 文書を構成した例を示します.
また,その木構造を図 2.4 に示します.
<市>
<コード>100</コード>
<名前>札幌</名前>
<人口>1889352</人口>
<シンボル 種別="木">ライラック</シンボル>
2.5 XML インスタンス
355
<シンボル 種別="花">スズラン</シンボル>
<シンボル 種別="鳥">カッコウ</シンボル>
</市>
図 2.4
シンボル要素に種別属性を付加した XML の木構造
これまで,市単位での XML の構成を行ってきましたが,今度は XML 文書全体の構成を考えてみます.
国や都道府県,市区町村は複数存在するため,それぞれを区別する必要があります.そこで,国要素には属性に
ISO 3166-1 alpha-3 で定義されている 3 桁の数字を付加することで区別し,各都道府県と市区町村は属性として
JIS X 0401 および JIS X 0402 で規格化されている都道府県コードと市区町村コードを付加することで区別すること
にします
*3
[1, 2, 3].
国や都道府県,市区町村要素のそれぞれの属性名は,区別せず単にコードとしています.また,都道府県や市区町村
はそれぞれ複数あるので,都道府県や市要素には全都道府県や全市といった親要素を作成することにします.
また,各市町村ではシンボルとして木,花,それに鳥の 3 種類が制定されている場合が多いようです.そこで,シン
ボル要素には下位要素として木と花,鳥要素を作成し,例外への対策としてその他要素を作成することとします.さら
に,その他要素には属性として種別を付加し,そのシンボルの種別が判別できるようにします.
これらの設計を元に,全体を構成した例の一部を示します.図 2.5 には,この XML 文書の木構造の一部を示します
(要素名,属性名などを英語表記にしています).
<国 コード="392">
<名前>日本</名前>
<全都道府県>
<都道府県 コード="01">
<名前>北海道</名前>
<全市>
<市 コード="100">
<名前>札幌</名前>
*3
総務省ではこれらの都道府県コード 2 桁と市区町村コード 3 桁に,1 桁の検査数字を加えた 6 桁のコードを全国地方公共団体コードとして使
用しています [4].
第 2 章 XML
356
<人口>1889352</人口>
<シンボル>
<木>ライラック</木>
<花>スズラン</花>
<鳥>カッコウ</鳥>
<その他 />
</シンボル>
</市>
<市 コード="204">
<名前>旭川</名前>
<人口>354572</人口>
<シンボル>
<木>ナナカマド</木>
<花>ツツジ</花>
<鳥>キレンジャク</鳥>
<その他 種別="虫">カンタン</その他>
</シンボル>
</市>
</全市>
</都道府県>
<都道府県 コード="47">
<名前>沖縄</名前>
<全市>
<市 コード="20">
<名前>那覇</名前>
<人口>314739</人口>
<シンボル>
<木>フクギ</木>
<花>ブーゲンビリア</花>
<鳥>ホウオウボク</鳥>
<その他 />
</シンボル>
</市>
</全市>
</都道府県>
</全都道府県>
</国>
2.6 XML 名前空間
357
図 2.5 全体の設計を行った XML の木構造の一部分の例
2.6 XML 名前空間
ある XML 文書に対して複数の XML を記述することができます.例えば,Web ページ中に数式を使用したいと考
えたならば,html 文書を表現する XHTML と数式を表現する MathML の 2 つの XML 言語を同一の XML 文書に
記述することで実現できます.このようなときに,双方で同じ名前の要素が定義されている場合には,どちらの XML
の要素なのかが判別できなくなり,要素名の衝突が起きます.これを解決するために考えられたのが,XML 名前空
間 (XML namespace) です.
2.6.1 接頭辞
要素名の衝突を避けるために,その要素がどの名前空間のものであるかを明示する必要があるため,名前空間接頭
辞 (namespace prefix) を付加して衝突を回避します.以下に,名前空間の定義例を示します.
<data xmlns:ns="http://www.example.com/municipality">
<ns:city>
<ns:name>札幌</ns:name>
<ns:population>354572</ns:population>
</ns:city>
第 2 章 XML
358
</data>
名前空間はルート要素に xmlns 属性を付加することで指定します.この例では,data 要素で ns という接頭辞を指定
しています.接頭辞 ns で表される名前空間で有効になる要素には¡ns:city¿ や¡ns:name¿などとして明示的に名前空間
を指定できます.
また,名前空間とその接頭辞は,以下のように複数指定することもできます.
<data xmlns:mu="http://www.example.com/municipality"
xmlns:cd="http://www.example.com/code">
<mu:city>
<mu:code>100<mu:code>
<mu:name>札幌</mu:name>
<cd:flag>
<cd:code>011002</cd:code>
<cd:flag>
</mu:city>
</data>
この例では,code 要素が複数存在しますが,名前空間を指定することで異なる情報を示していることが判別でき
ます.
2.6.2 デフォルト名前空間
標準で使用する名前空間(デフォルト名前空間)を指定することができます.xmlns 属性に接頭辞を指定せずに URI
を指定することでデフォルト名前空間を指定できます.デフォルト名前空間で指定された要素は,以下のように名前空
間の記述を省略することができます.
<data xmlns="http://www.example.com/data">
<city xmlns="http://www.example.com/municipality"
xmlns:cd="http://www.example.com/code">
<code>100<code>
<name>札幌</name>
<cd:flag>
<cd:code>011002</cd:code>
<cd:flag>
</city>
<data>
この例では,xmlns 属性で http://www.example.com/municipality の名前空間をデフォルト名前空間として指
定しているため,接頭辞を付加する必要がなくなりました.ただし,http://www.example.com/code の名前空間は
デフォルト名前空間ではありませんので,この名前空間を使用している要素には xmlns:cd と指定しているため接頭辞
cd を付加し,区別します.
2.7 XML 文書の正しさ
359
さらに,デフォルト名前空間を途中で切り替えることによって,接頭辞の記述を省略することができます.
<city xmlns="http://www.example.com/municipality">
<code>100<code>
<name>札幌</name>
<flag xmlns="http://www.example.com/code">
<code>011002</code>
</flag>
</city>
この例では,文書全体のデフォルト名前空間は http://www.example.com/municipality ですが,4 行目で flag 要
素にデフォルト名前空間を指定しているため,flag 要素の子要素である 5 行目の code 要素は 2 行目の code とは異な
る名前空間を利用しています.
2.7 XML 文書の正しさ
XML 言語はその文書の文法を厳密に規定している言語です.これまでにも見てきたように,タグの入れ子関係が
誤っていたり,DTD の定義に即さない文書などは XML 文書として認められません.
タグの関係性や要素名などの命名規則が正しいなど,XML の文法や規則に即する XML 文書を整形式 XML 文書と
呼び,さらに,DTD による定義に則する XML 文書を妥当な XML 文書と呼びます.また,整形式 XML であり妥当
な XML 文書であることが認められた XML 文書は検証済み XML 文書と呼びます.
2.7.1 整形式 XML 文書
整形式 XML 文書 (well–formed XML document) は,XML 言語の文法に即した文書を指します.整形式 XML 文
書には DTD は必要ありませんし,DTD の定義に即さない記述がある場合でも,XML 言語の文法に即していれば整
形式 XML 文書であると言えます.
XML 言語の文法に即しているとは,例えば,タグの記法や関係性が適切であるといった点や,要素名や属性名が命
名規則に則しているといった点などが挙げられます.このような整形式であるために定められた規則のことを整形式制
約 (well–formedess constraints) と呼びます.整形式制約の一部を表 2.6 に示します.また,整形式 XML 文書である
ためには,この整形式制約を満たすことを含む以下の 3 つの条件を満たす場合を指します.
1. document というラベルの生成規則にしたがう
2. 整形式制約にしたがう
3. 実体参照された実体が整形式である
以下に整形式制約を満たさない XML 文書の例を示します.
<cities>
<city code="100" code="1">
<name>札幌</name>
第 2 章 XML
360
表 2.6
整形式制約
制約
内容
要素型の一致 (Element Type Match)
終了タグの要素名が開始タグの要素名と一致している
属性名の一意性 (Unique Att Spec)
同じ開始タグや空要素タグに同じ属性を複数指定しない
文字の正さ (Legal Character)
用いられる文字が定められた生成規則に従っている
属性値に¡を含まない (No¡ in Attribute Values)
属性値には¡を含まない
..
.
..
.
<population>1889352</population>
<symbol>
</city>
</city>
この例では,以下の 3 つで整形式制約を満たしていません.
2 行目 city 要素に code 属性が複数存在します.これは,「属性名の一意性」を満たしません.
5 行目 symbol 要素の開始タグのみが記述されています.空要素を表現するのであれば,¡symbol /¿とするか,終了タ
グで閉じる必要があります.これは,「要素型の一致」の違反に対応します.
7 行目 cities 要素の終了タグが間違っています.これは,「要素型の一致」を満たしていません.
上記を修正した整形式 XML 文書の例を以下に示します.
<cities>
<city code="100" id="1">
<name>札幌</name>
<population>1889352</population>
<symbol />
</city>
</cities>
2.7.2 妥当な XML 文書
妥当な XML 文書 (valid XML document) とは,整形式 XML 文書のうち,XML インスタンスが DTD による定
義に即している XML 文書を指します.XML 文書の構造の妥当性は,DTD の定義に照らし合わせることで検証でき
ます.従って,妥当な XML 文書には DTD が記述されている必要があります.
妥当な XML 文書とは,DTD の定義に従っているかを検証し,定義に従っている XML 文書のことを指します.
この定義に従っているかを検証する(XML 文書の妥当性を検証する)ための規則のことを,妥当性制約 (validity
constraints) と呼びます.また,この妥当性制約を検証した XML 文書を検証済み XML 文書と呼び,妥当性制約に即
する XML 文書を妥当な XML 文書と呼びます.
この妥当性制約の規則の一部を表 2.7 に示します.
以下に,DTD と XML インスタンスを記述している XML 文書の例を示します.この XML 文書は,妥当性制約を
2.7 XML 文書の正しさ
361
表 2.7
妥当性制約
制約
内容
ルート要素型 (Root Element Type)
ルート要素の名前が DOCTYPE 宣言でのルート要素と一致している
要素の正さ (Element Valid)
要素の宣言されており,その型が正しい
属性値の型 (Attriute Value Type)
属性と属性の型が宣言されており,属性値が正しい
ID 型の一意性 (One ID per Element Type)
ひとつの要素に複数の ID 型の属性が存在しない
ID 属性の初期値 (ID Attribute Default)
..
.
ID 型の属性は#IMPLIED か#REQUIRED である
..
.
満たしていません.
<!DOCTYPE city [
<!ELEMENT city (name, population)>
<!ATTLIST city ruby ID "sapporo"
prefecture ID #IMPLIED>
<!ELEMENT name (#PCDATA)>
]>
<cities>
<city ruby="sapporo" prefecture="hokkaido">
<name>札幌</name>
<population>1889352</population>
</city>
</cities>
この XML 文書は,以下に示す 3 つの妥当性制約を満たしていないため,妥当な XML 文書と呼ぶことができません.
1 行目, 8 行目 ルート要素が DOCTYPE 宣言と異なります.これは「ルート要素型」を満たしません.
2 行目 親要素 city の子要素として name,population が定義されていますが,population 要素が定義されていません.
これは「要素の正しさ」を満たしていません.
3 行目 ID 型は初期値に文字列を取ることができません.これは「ID 属性の初期値」を満たしません.
4 行目 ruby と prefecture が ID 型で定義されていますが,ひとつの要素に複数の ID 型を定義することはできません.
これは「ID の一意性」を満たしません.
以上の点を修正した妥当な XML 文書の例を以下に示します.
<!DOCTYPE cities [
<!ELEMENT cities (city)>
<!ELEMENT city (name, population)>
<!ATTLIST city ruby ID #REQUIRED
第 2 章 XML
362
prefecture CDATA #REQUIRED>
<!ELEMENT name (#PCDATA)>
<!ELEMENT population (#PCDATA)>
]>
<cities>
<city ruby="sappro" prefecture="hokkaido">
<name>札幌</name>
<population>1889352</population>
</city>
</cities>
第3章
XML の実装例
XML 言語ではタグを自由に定義することができますが,ある特定の目的のための定義を規定し,広く使用されて
いる実装例として XHTML や SVG,MathML,DocBook などがあります.これらの XML は画像や数式の扱い,ド
キュメント文書の記述や効率的なデータの収集などの目的に基づいて設計,実装されています.
ここでは,Web サービスや Web アプリケーションとしての利用の観点から,Web ブラウザへの実装が進んでいる
実装例として XHTML と SVG, MathML を取り上げます.また,これらを同一の XML 文書に記述し,Web ブラウ
ザ上で描画する例を示します.
3.1 XHTML
XHTML (eXtensible Hyper Text Markup Language) は HTML を XML によって定義付けされたマークアップ言
語です.SGML によって定義されていた HTML 4 を XML 1.0 によって再定式化したものが XHTML です.2000 年
に W3C によって XHTML 1.0 が,2001 年には XHTML 1.1 が勧告されています [13, 14].
また,XHTML では,他の XML 言語を文書内に含め,Web ページの一部として表示することができます.この具
体例は 3.4 節に示しています.
3.1.1 DOCTYPE 宣言
XHTML 1.0 は,SGML であった HTML 4.01 から移行したという経緯などから,複数の DTD が存在します.
Strict, Transitional,Frameset の 3 種類の DTD です.XHTML では HTML を XML として再定義する過程で,い
くつかの XML として必要のない要素や属性(例えば,装飾目的の要素)を非推奨要素や属性として XHTML に採用
しませんでした.これらの非推奨要素や属性が定義されていない完全な XHTML の DTD が Strict であり,非推奨要
素や属性をある程度許容する DTD が Transitional,また,非推奨要素としているフレーム要素まで広く寛容的に定義
している DTD が Frameset です.XHTML 1.1 ではこれらは区別されず,非推奨要素や属性を許容しない Strict な
DTD のみが定義されています.
厳密に定義された Transitional 以外の非推奨要素を許容した DTD が用意されている背景には,HTML 4.01 以前の
文書が大量に存在するため,これらの資産を有効に活用できるという点が挙げられます.従って,今後新たに XHTML
による XML 文書を作成する際には,XHTML 1.0 Strict,もしくは XHTML 1.1 Strict の DTD による定義を用いるべ
きだと言えます.
公開識別子を用いた XHTML 1.0, 1.1 の DOCTYPE 宣言の例を以下に列挙します.DOCTYPE 宣言では,ルー
ト要素を指定する必要がありますが,XHTML のルート要素は html であることに注意します.また,XML 文書の言
語が日本語であるからといって言語の指定を JP に変更してはいけません.これは,DTD の言語を指定するもので,
XML 文書の言語を指定するものではないからです.
第 3 章 XML の実装例
364
XHTML 1.0 Strict
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml10/DTD/xhtml1-strict.dtd">
XHTML 1.0 Transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml10/DTD/xhtml1-transitional.dtd">
XHTML 1.0 Frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
"http://www.w3.org/TR/xhtml10/DTD/xhtml1-frameset.dtd">
XHTML 1.1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3.1.2 名前空間
XHTML の名前空間は,http://www.w3.org/1999/xhtml です.XHTML のルート要素である html 要素に xmlns
属性として指定します.また,html 要素では属性値を用いて XML 文書の言語を指定できます.html 要素に xml:lang
属性と lang 属性を付加することで指定します.XHTML 1.0 では,これらの言語指定は xml:lang, lang の双方を記述
するよう規定されています.XHTML 1.1 では,lang 属性は廃止され,xml:lang のみを指定するよう規定されていま
す.これらを踏まえた XHTML の名前空間を指定したルート要素 html の記述例を,以下に示します.
XHTML 1.0 の場合
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp" lang="jp">
XHTML 1.1 の場合
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp">
3.1.3 XHTML による XML 文書の記述例
XHTML は XML ですから,その文書記述は XML に則ったものになります.従って,図 2.2 のように,XML 文書
は XML 宣言, DTD, XML インスタンスの順に記述します.XML 宣言は必須ではありませんが,XHTML の仕様では
記述することを強く推奨されています.
3.2 SVG
365
XHTML 1.1 による,単純な XML 文書の例を以下に示します.なお,詳細な要素,属性などの解説は省略します.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp">
<head>
<title>xhtml sample</title>
</head>
<body>
<h1>XHTML SAMPLE</h1>
<p>これは,XHTML による XML 文書の例です.</p>
<hr />
<h2>XML Structure</h2>
<img src="./xmlstructure.png" alt="XML の文書構造"/>
</body>
</html>
先頭には,XML 宣言を記述しています.続いて,DOCTYPE 宣言によって公開識別子を用いた DTD を指定し,
XHTML 1.1 を使用することを宣言しています.ルート要素は html を指定します.XML インスタンスでは html を
ルート要素とする,XML を記述しています.ここで,html 要素において xmlns 属性でデフォルト名前空間を指定し
ているため,それぞれの要素は接頭辞を記述する必要はありません.また,水平線要素 (hr) や埋め込み画像要素 (img)
は空要素であるため,単に¡hr¿などではなく¡hr /¿などとしていることに注意して下さい.
3.2 SVG
SVG (Scalable Vector Graphics) は XML によって記述された,ベクタ画像 (vector graphics) を扱うことのできる
言語です.2003 年に W3C によって SVG 1.1 が勧告されています [15].
ベクタ画像では,その画像情報をベクトル表現による座標情報などとして扱っています.拡大や縮小,変形などの操
作を行った際でも,画像情報は数値計算によって座標データが変化するだけなので,画像の編集による画質の劣化がお
きません.また,扱う画像情報は XML なので,編集も容易です.SVG は対応した画像処理ソフトウェアで作成や編
集を行ったり,対応した Web ブラウザでも描画することができます.
3.2.1 DOCTYPE 宣言
SVG の公開識別子は "-//W3C//DTDSVG1.1//EN" です.また,DTD の URI は "http://www.w3.org/Graphics/
SVG/1.1/DTD/svg11.dtd" です.ルート要素には svg を指定します.従って,SVG の DOCTYPE 宣言は以下のよ
うになります.
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
第 3 章 XML の実装例
366
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3.2.2 名前空間
SVG のルート要素は svg で,その名前空間は "http://www.w3.org/2000/svg" です.名前空間の指定は以下のよ
うになります.
<svg xmlns="http://www.w3.org/2000/svg">
ここで,svg の属性として描画する範囲を定める viewBox など,必要となる属性も指定します.
<svg style="shape-rendering:geometricPrecision;"
viewBox="0 0 400 400"
xml:space="preserve"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid meet">
3.2.3 描画例
以下に SVG の定義に基づいた XML 文書の例を示し,図 3.1 にグラフィクスソフトウェアを用いて閲覧した例を示
します.ここでは,テキストエディタで XML を記述したものを,対応したグラフィクスソフトウェアから開いていま
す.グラフィクスソフトウェアで画像を作成し,SVG 形式で書き出すこともできます.なお,詳細な要素,属性など
の解説は省略します.
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg style="shape-rendering:geometricPrecision;"
viewBox="0 0 400 400"
xml:space="preserve"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid meet">
<path d="M 0,0 C 0,400 400,0 200,200 Z"
fill="lightblue" stroke="blue" />
<rect width="120" height="80" x="120" y="80"
fill="pink" stroke="red" />
<circle cx="120" cy="80" r="50"
3.3 MathML
367
fill="none" stroke="green" />
</svg>
図 3.1 SVG による描画の例
3.3 MathML
MathML (Mathematical Markup Language) は,数式を記述するために開発された XML 言語です.2003 年に
W3C によって MathML 2.0 が勧告されています [16].
MathML はコンピュータで表現が困難であった数式を記述するためのマークアップ言語として開発されました.コ
ンピュータで数式を処理する言語には TEX などがありますが,MathML ではそれと比較すると人間にとってその表現
が煩雑で一見して分かりにくいものになっています.しかし,機械的に処理でき,汎用的な XML の形式で表現されて
いることは,MathML が Web サービスにおいて活用される機会を生むことに繋がるかもしれません.
3.3.1 DOCTYPE 宣言
MathML の公開識別子は "-//W3C//DTDMathML2.0//EN" です.また,DTD の URI は "http://www.w3.org/
Math/DTD/mathml2/mathml2.dtd" です.ルート要素には math を指定します.
<!DOCTYPE math PUBLIC "-//W3C//DTD MathML 2.0//EN"
"http://www.w3.org/Math/DTD/mathml2/mathml2.dtd">
3.3.2 名前空間
MathML のルート要素は math で,名前空間は xmlns="http://www.w3.org/1998/Math/MathML" です.よって,
名前空間の指定は以下のようになります.
<math xmlns="http://www.w3.org/1998/Math/MathML">
第 3 章 XML の実装例
368
3.3.3 表示例
MathML による XML の例を以下に示します.また,Web ブラウザでの表示例を図 3.2 に示します.なお,詳細な
要素,属性などの解説は省略します.
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<!DOCTYPE math PUBLIC "-//W3C//DTD MathML 2.0//EN"
"http://www.w3.org/Math/DTD/mathml2/mathml2.dtd">
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>
<mi>x</mi>
<mo>=</mo>
<mfrac>
<mrow>
<mrow>
<mo>-</mo>
<mi>b</mi>
</mrow>
<mo>±</mo>
<msqrt>
<mrow>
<msup>
<mi>b</mi>
<mn>2</mn>
</msup>
<mo>-</mo>
<mrow>
<mn>4</mn>
<mi>a</mi>
<mi>c</mi>
</mrow>
</mrow>
</msqrt>
</mrow>
<mrow>
<mn>2</mn>
<mi>a</mi>
</mrow>
</mfrac>
</mrow>
3.4 複数の XML 規格の混在
369
</math>
図 3.2 MathML の例
3.4 複数の XML 規格の混在
XHTML では,その文書中に SVG や MathML などの XML 文書を含め,Web ブラウザ上でコンテンツの一部とし
て表示することができます.
以下に,デフォルト名前空間に XHTML を指定し,SVG と MathML を混在させた例を示します.この例では,ルー
ト要素 html で,デフォルト名前空間として XHTML,接頭辞 m とした MathML,接頭辞 s とした SVG の名前空間
を指定しています.
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
m:xmlns="http://www.w3.org/1998/Math/MathML"
s:xmlns="http://www.w3.org/2000/svg"
xml:lang="ja">
<head>
<meta http-equiv="Content-Type" content="application/xhtml-xml; charset=utf-8" />
<title>xmlns sample</title>
</head>
<body>
<div>
<m:math>
<m:mi>E</mi>
<m:mo>=</mo>
<m:mi>m</mi>
<m:msup>
<m:mi>c</mi>
<m:mn>2</mn>
</m:msup>
</m:math>
第 3 章 XML の実装例
370
<s:svg style="shape-rendering:geometricPrecision;"
viewBox="0 0 400 400"
xml:space="preserve"
xmlns:xlink="http://www.w3.org/1999/xlink"
preserveAspectRatio="xMidYMid meet">
<s:circle cx="20" cy="20" r="10"
fill="lightgreen" stroke="green" />
</s:svg>
</div>
</body>
</html>
この XML (XHTML) 文書を Web ブラウザで読み込むと,図 3.3 のように表示されます.
図 3.3 XHTML, MathML, SVG を混在させた例
また,これは以下のように,デフォルト名前空間をその都度指定した記述と同義です.
html で XHTML のデフォルト名前空間のみを指定し,数式を表示する部分で math 要素に MathML のデフォルト
名前空間を指定,画像を表示する部分で svg 要素に SVG のデフォルト名前空間を指定することで,接頭辞の記述を省
略しています.
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="application/xhtml-xml; charset=utf-8" />
<title>xmlns sample</title>
</head>
<body>
<div>
<math xmlns="http://www.w3.org/1998/Math/MathML">
3.4 複数の XML 規格の混在
<mi>E</mi>
<mo>=</mo>
<mi>m</mi>
<msup>
<mi>c</mi>
<mn>2</mn>
</msup>
</math>
<svg style="shape-rendering:geometricPrecision;"
viewBox="0 0 400 400"
xml:space="preserve"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid meet">
<circle cx="20" cy="20" r="10"
fill="lightgreen" stroke="green" />
</svg>
</div>
</body>
</html>
371
第4章
SOAP
SOAP は XML を用いたデータ通信のプロトコルです.SOAP ではやり取りする XML データと,その処理を行う
プロトコルとを同一のメッセージ中に記述します.
SOAP は 2003 年に W3C によって SOAP Version 1.2 が勧告されています [10].なお,Version 1.1 では,SOAP
は Simple Object Access Protocol の略でしたが,Version 1.2 からは単に SOAP としています.
4.1 SOAP の構成
SOAP メッセージはプロトコルヘッダと XML によって記述された SOAP エンベロープで構成されます.図 4.1 に
SOAP メッセージの構成例を示します.SOAP エンベロープはさらに,SOAP ヘッダと SOAP ボディによって構成さ
れます.ただし,SOAP ヘッダは必ずしも記述する必要はありません.
4.1.1 SOAP エンベロープの構成
SOAP エンベロープは Envelop, Header, Body 要素を持ちます.以下に,SOAP エンベロープの部分を示します.
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Header>
………………………
</SOAP-ENV:Header>
<SOAP-ENV:Body>
………………………
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
このように,SOAP-ENV 要素を 用いて SOAP メッセージ全体を括ります.Envelope 要素では,名前空間と
エンコーディング規則を指定します.名前空間は http://schemas.xmlsoap.org/soap/envelope/ です.また,
encodingStyle 属性によって指定するエンコーディング規則のデフォルトの URI は http://schemas.xmlsoap.org/
soap/encoding/ です.
4.1 SOAP の構成
373
図 4.1 SOAP メッセージの構成
4.1.2 SOAP ヘッダの構成
SOAP ヘッダを用いることで SOAP メッセージを拡張することができます.拡張の必要がない場合は省略すること
ができます.Header 要素は Envelop 開始タグの直後に置く必要があります.さらに,必ず名前空間を用いて修飾する
必要があります.
mustUnderstand 属性
SOAP メッセージを受信した際に,SOAP ヘッダを必ず処理すべきかどうかを指定することができます.ここで,
mustUnderstand 属性に 1 を指定するとヘッダを必ず処理する必要があることを示し,0 を指定するとヘッダの処理は
任意でよいことを示します.SOAP ヘッダを指定した例を示します.
第4章
374
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<SOAP-ENV:Header>
<ns:ID xmlns:ns="URI" SOAP-ENV:mustUnderstand="1">
1234
</ns:ID>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
………………………
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
4.1.3 SOAP ボディの構成
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<SOAP-ENV:Body>
<nsb:Municipality xmlns:nsb="URI">
<population>127288419</population>
</nsb:Municipality>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
4.1.4 SOAP メッセージの例
以下に,単純な SOAP メッセージの例を示します.
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<SOAP-ENV:Header>
<nsh:Transaction xmlns:nsh="URI-1" SOAP-ENV:mustUnderstand="1">
1
</nsh:Transaction>
</SOAP-ENV:Header>
SOAP
4.1 SOAP の構成
<SOAP-ENV:Body>
<nsb:Municipality xmlns:nsb="URI-2">
<population>127288419</population>
</nsb:Municipality>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
375
第5章
標準化技術
5.1 標準化団体
5.1.1 W3C
W3C (World Wide Web Consortium) は WWW における技術の標準化を推進するために設立された非営利の国際
標準化団体です.これまでに本章で登場した XML や XML 名前空間, XHTML, SVG なども W3C によって勧告され
ている規格です.
W3C の標準化の過程は以下の様に進められます [5].
• 作業草稿 (Working Draft: WD)
• 最終草案 (Last Call Working Draft: CR)
• 勧告案 (Proposed Recommendation: PR)
• W3C 勧告 (W3C Recommendation: REC)
表 5.1 に W3C により勧告されている代表的な規格を示します.
表 5.1
W3C により勧告されている代表的な規格
CSS
DOM
HTML
MathML
OWL
RDF
SVG
SOAP
WSDL
XHTML
XML
XML Schema
XPath
XQuery
XSL
XLink
5.1.2 OASIS
OASIS (Organization for the Advancement of Structured Information Standards, 構造化情報標準促進協会) は
非営利の国際コンソーシアムです [17].OASIS は 1993 年に SGML に準拠した製品間の相互運用性に関するガイドラ
イン策定のために設立されましたが,XML などの標準化活動の拡大に伴い,1998 年に OASIS に名称変更しています.
OASIS によって標準化された代表的な仕様のうち Web サービスに関するものは DocBoos, ebXML, SPML, UDDI,
WebCGM などがあります.
第 13 回 演習課題
目標
XML 文書の構造を理解し,文書構造に厳密性が要求されることをすることを学びます.
また,整形式 XML 文書と妥当な XML 文書の違いを理解し,その誤りを指摘できるようにします.さらに,DTD
による XML 文書構築の基礎を身につけます.
※ 発展は任意課題とします.余裕のある方は挑戦してみて下さい.
課題 1 XML データの構造理解
1–1
以下の文書は,XML 文書として不適切です.誤っている箇所を探し,整形式に訂正して下さい.
<city code="sapporo" prefecture="hokkaido">
<name>札幌</name>
<population>1889352</population>
<symbol>
<tree>ライラック<tree>
<flower>スズラン</flower>
<bird>カッコウ</bird>
</other>
</city>
1–2
訂正した XML 文書を hokkaido.xml としてファイルを作成し,Web ブラウザから http://192.168.69.xxx/
hokkaido.xml にアクセスして閲覧可能な状態にして下さい.
1–3
実際に作成した XML 文書を,Web ブラウザで閲覧し XML ツリーが表示されていることを確認して下さい.エラー
が表示されている場合は,XML 文書を適切に訂正して下さい.
1–4
作成した XML 文書に XML 宣言を記述して下さい.ただし,ここでは standalone 属性を記述する必要はありま
せん.
また,前問と同様に,Web ブラウザから http://192.168.69.xxx/hokkaido.xml にアクセスして閲覧可能な状態
にし,エラーが表示されていないことを確認して下さい.
第5章
378
第 13 回 演習課題
1–5
作成した XML 文書を表現する DTD を定義して下さい.前述の XML 文書と,以下に示した条件を満たすよう定義
して下さい.
また,XML 宣言に standalone 属性の指定を追加して下さい.
city 要素の code 属性の属性は ID 型で,初期値を必ず指定します.
city 要素の prefecture 属性は文字列型で,初期値を必ず指定します.
other 要素は一度以上出現します.
other 要素以外の要素は,全て一度のみ出現します.
other 要素は type 属性をもち,type 属性は文字列型で,初期値の指定は任意です.
1–6
作成した XML 文書を http://www.validome.org/xml/validate/ にアップロードして,妥当性の検証を行って
下さい.妥当な XML 文書であれば,The Document is valid. と表示されます.もし,妥当な XML 文書ではないと表
示された場合は,エラーメッセージを参考に DTD の定義を再考して下さい.
発展
city 要素は通常複数存在します.city 要素の親要素 cities を定義し,cities 属性の子要素としてに city 要素が一度以
上出現する DTD を変更して下さい.DTD に従って,XML インスタンスに cities 要素を記述して下さい.
また,作成した XML 文書は http://www.validome.org/xml/validate/ でその妥当性の検証を行って下さい.
[注意] XML 文書のルート要素は cities 要素になります.
発展
あなたの出生地やその周辺の市などの情報を,XML 文書に追加して下さい.
また,作成した XML 文書は http://www.validome.org/xml/validate/ でその妥当性の検証を行って下さい.
参考文献
[1] Standard Country and Area Codes Classifications (M49), United Nations Statics Division, http://unstats.
un.org/unsd/methods/m49/m49alpha.htm
[2] 日本興業標準調査会:データベース - JIS 詳細表示, 日本興業標準調査会, http://www.jisc.go.jp/app/pager?
id=82
[3] 日本興業標準調査会:データベース - JIS 詳細表示, 日本興業標準調査会, http://www.jisc.go.jp/app/pager?
id=6
[4] 地方公共団体コード住所, 財団法人 地方自治情報センター (LASDEC), http://www.lasdec.nippon-net.ne.
jp/cms/1,0,14.html
[5] World Wide Web Consortium Process Document 14 October 2005, http://www.w3.org/2005/10/
Process-20051014/
[6] W3C Working Group Note February 2004, Web Services Architecture, http://www.w3.org/TR/sw-arch/
[7] W3C Note 15 March 2001, Web Services Description Language (WSDL) 1.1, http://www.w3.org/TR/wsdl
[8] W3C Recommendation 26 November 2008, Extensible Markup Language (XML) 1.0 (Fifth Edition), http:
//www.w3.org/TR/2008/PER-xml-20080205/
[9] W3C Recommendation 04 February 2004, edited in place 15 April 2004, Extensible Markup Language (XML)
1.1, http://www.w3.org/TR/2008/REC-xml-20081126/
[10] W3C Recommendation 27 April 2007, SOAP Version 1.2 Part 0: Primer (Second Edition), http://www.w3.
org/TR/soap12-part0/
[11] W3C Recommendation 07 April 2004, Document Object Model (DOM) Level 3 Core Specification Version
1.0, http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/
[12] W3C Recommendation 16 August 2006, Namespaces in XML 1.0 (Second Edition), http://www.w3.org/
TR/REC-xml-names/
[13] W3C Recommendation 26 January 2000, revised 1 August 2002, XHTML 1.0 The Extensible HyperText
Markup Language (Second Edition) A Reformulation of HTML 4 in XML 1.0, http://www.w3.org/TR/
xhtml1/
[14] XHTML 1.1 - Module-based XHTML, W3C Recommendation 31 May 2001, http://www.w3.org/TR/
xhtml11/
[15] W3C Recommendation 14 January 2003, edited in place 30 April 2009, Scalable Vector Graphics (SVG) 1.1
Specification, http://www.w3.org/TR/SVG11/
[16] W3C Recommendation 21 October 2003, Mathematical Markup Language (MathML) Version 2.0 (Second
Edition), http://www.w3.org/TR/MathML2/
[17] OASIS: Advancing open standards for the global information society, http://www.oasis-open.org/home/
index.php
参考文献
380
[18] UDDI Spec Technical Committee Draft, Dated 20041019, UDDI Version 3.0.2, htp://uddi.org/pubs/
uddi-v3.0.2-20041019.htm
第 14 回
マッシュアップ入門(1)
Web サービス API を活用することで,付加価値の高い複合的なサービスの提供を実現する
マッシュアップ技術について解説します.また,マッシュアップの要素技術である JavaScript,
Ajax,DOM についても解説します.演習では,JavaScript により XML ドキュメントの操作を
行うプログラムを作成することにより,マッシュアッププログラミングの基本を学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
マッシュアップ
1.1 マッシュアップとは
マッシュアップ (Mashup) は,複数の Web サービス(第 13 回参照)を組み合わせて Web アプリケーションを構成
することにより,新しい Web サービスを用いた Web アプリケーションを提供しているよう構成する手法を指します.
なお,ここでは複数の Web サービスを利用した Web アプリケーションを用いて構築された Web ページや Web サイ
トをマッシュアップサイトと呼ぶこととします.
1.2 マッシュアップサイトの特徴
Web サイトの構築に,複数の Web サービスの利用によるマッシュアップを行う利点は,以下のような点が考えられ
ます.
• 短期間の開発
• 開発コストの軽減
• 新たな価値の創造
• 自分が所有しないリソース(資源,データベース)を活用できる
また,欠点として以下のような点が挙げられます.
• API の仕様変更に対応する必要がある
• 1 つの Web API が使用できなくなると,他との連携にも不都合が生じる可能性がある
• API によって仕様が異なるため,仕様を理解する負担がかかる
1.3 マッシュアップの構成要素
マッシュアップによる Web サイトの構築では,複数の Web サービスを主に非同期通信によって処理することによっ
て,あたかも 1 つの Web サービスを利用しているように Web アプリケーションを構築できます.
図 1.1 にマッシュアップサイトの概念図を示します.マッシュアップサイトの構築には,一般に公開されている Web
サービスを複数利用することで,自分が保有していない情報を組み合わせて提供することが可能になったり,これまで
にはなかった価値観の Web サイトを構築できるという利点があります.Web サービスを用いることで,例えば,地図
情報に天気予報や旅行の情報を掲載するなどといった,複合的な情報を含んだ Web アプリケーションを構築できます.
1.3 マッシュアップの構成要素
383
図 1.1
マッシュアップサイトの構成
第2章
JavaScript
この章では,JavaScript 言語について解説します.
なお,JavaScript を用いた非同期通信については 3 章で,XML データの DOM 操作については 4 章でそれぞれ解
説しますので,JavaScript 言語の文法についての知識を既に有する場合には,この章を読み飛ばして次章へ進んで構い
ません.
2.1 JavaScript の概要
JavaScript は,1995 年に Web ブラウザの 1 つである Netscape Navigator 2.0 の機能として登場しました.その
後,Microsoft Internet Explorer 3.0 には,JavaScript と互換性を持つ JScript が搭載されました.この 2 つのスクリ
プト言語は互いに似通った言語でしたが異なる部分も多く,また,Netscape 社,Microsoft 社によって,それぞれ独自
に言語を拡張したため,実装バージョンが増え,それに従い,その互換性をとることが困難になっていきました.Web
ブラウザによってスクリプトの挙動が異なることは,ページの制作者にとっても,ページの閲覧者にとっても不都合な
ことでした.
そこで,標準化団体 Ecma International
*1 によって,JavaScript
と JScript 双方の特徴を採用した中核的な仕様をま
とめた ECMAScript が 1999 年に標準化されました.現在,Web ブラウザに実装されているものは,この ECMAScript
に準拠した JavaScript や JScript の実装です.このため,基盤となる ECMAScript の仕様にあたる部分の機能は Web
ブラウザの違いによって挙動の相違が生じません.本テキストでは,ECMAScript,および ECMAScript に準拠した
JavaScript と JScript を総称して,JavaScript と呼ぶこととします.
2.2 (X)HTML 文書への記述
JavaSctipt の既述には,(X)HTML 文書に直接記述する方法と,外部ファイルに記述し (X)HTML から読み込む方
法があります.
2.2.1 (X)HTML 文書へ直接記述する方法
(X)HTML で JavaScript などのスクリプト言語を記述する際には,script 要素を用います.script 要素には type 属
性として”text/javascript”を指定します.この script 要素中に JavaScript のコードを記述しますが,JavaScript のコー
ド中に不等号記号などが存在すると適切に解釈されないため,それらを扱うことのできる CDATA 型
*2 を¡![CDATA[
JavaScript のコード ]]¿として指定することで対応します.また,開始タグや終了タグは JavaScript には解釈できない
ため,先頭に「//」などを付加して JavaSctipt としてはコメント行として扱います.
*1
*2
元々は ECMA(European Computer Manufacturers Association: 欧州電子計算機工業会).1994 年に Ecma International に改称.
文字データ型.第 13 回 図 2.4 参照
2.2 (X)HTML 文書への記述
385
<script type="text/javascript">
// <![CDATA[
ここに JavaScript のコードを記述する.
// ]]>
</script>
XHTML 1.1 で定義した XHTML 文書に JavaScript を埋め込んだ例を以下に示します.XHTML の宣言について
は第 13 回 3.1 節を参照して下さい.
sample.xhtml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp">
<head>
<title>JavaScript sample</title>
</head>
<body onload="hoge()">
<h1>JavaScript SAMPLE</h1>
<p>これは,XHTML に JavaScript を埋め込んだ例です.</p>
<hr />
<h2>実行例</h2>
<script type="text/javascript">
<![CDATA[
var hello="Hello, JavaScript!!!";
var sample = document.createElement(’div’);
sample.innerHTML = hello;
document.getElementsByTagName(’body’)[0].appendChild(sample);
]]>
</script>
</body>
</html>
2.2.2 外部ファイルを指定する方法
通常,JavaScript を記述したファイルの拡張子は js とします.script 要素の src 属性に JavaScript ファイルを指定
します.
以下に,外部ファイルを読み込む場合の (X)HTML への記述を示します.
sample.xhtml
第 2 章 JavaScript
386
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp">
<head>
<title>JavaScript sample</title>
</head>
<body onload="hoge()">
<h1>JavaScript SAMPLE</h1>
<p>これは,XHTML に JavaScript を埋め込んだ例です.</p>
<hr />
<h2>実行例</h2>
<script type="text/javascript" src="sample.js"></script>
</body>
</html>
sample.js
var hello="Hello, JavaScript!!";
var sample = document.createElement(’div’);
sample.innerHTML = hello;
document.getElementsByTagName(’body’)[0].appendChild(sample);
2.3 JavaScript の記法の特徴
JavaScript は他の多くの言語にみられるよう,if や else if, for, do/for, while, do/while, switch, break, return,
continue などの文が使用できます.ここでは,それらの文の詳細な記述方法については扱わず,変数の宣言に使用する
var 文についてのみ扱います.
2.3.1 JavaScript の構造
JavaScript には,コード中で一番最初に実際の実行が行われる関数(例えば,C 言語での main 文にあたる関数)は
存在しません.関数で記述されていない部分(グローバルコード)を文書の先頭から順に処理を行っていきます.
2.3.2 変数
JavaScript では変数は全てオブジェクトであり,型を持ちません.例えば,C 言語には,整数型(int 型)や文字型
(char 型),単精度浮動小数点型(float 型)などの変数型が存在しますが,JavaScript の変数はこれらのような区別は
なくすべてオブジェクトです.
2.3 JavaScript の記法の特徴
387
変数を宣言するためには,var 文を用います.変数の宣言時には,=演算子を用いて変数の初期値を設定することが
できます.また,初期値を指定しない変数はその値に undefined が設定されます.
以下に,変数の宣言例を示します.
var hensu;
var locate = hokkaido;
var date = new Date();
変数のスコープ
JavaScript では,変数を宣言せずに用いることができます.変数を使用する場合,var 文による宣言は省略すること
ができます.ただし,宣言を行わずに用いた場合の変数はすべてグローバル変数となります.変数を関数内でのみ通用
する局所変数として使用したい場合には,明示的に var 文によって宣言する必要があります.
var hensu;
var locate = hokkaido;
var date = new Date();
2.3.3 オブジェクト
JavaScript はオブジェクト指向 (object–oriented) 型のスクリプト言語の 1 つです.
オブジェクト指向型のプログラム言語では命令や変数などのデータといった要素を 1 つの部品 (オブジェクト) とし
て捉えます.オブジェクトは,命令を示すメソッドやデータを示すプロパティといった要素を持ちます.
JavaScript では,変数や命令,関数といった要素の他に,Web ブラウザの管理する構成要素もオブジェクトとして
扱うことができます.図 2.1 に Web ブラウザの管理する HTML 文書のオブジェクトを示します.
オブジェクトは下位のオブジェクトを「.」で区切って記述することで,目的のオブジェクトにアクセスすることがで
きます.例えば,Web 文書中に一番最初に出現する画像を指定するには,window.document.image[0] とします.ただ
し,window は省略することができるので,document.image[0] とすることで指定できます.
また,要素の属性値にも同様に「.」で区切ることでアクセスできます.例えば,Web 文書中に記述された画像要素
の URL を取得するには,document.images[0].src とします.また,Web 文書中に記述された画像要素の src 属性と alt
の一覧を取得するには以下のようにします.
for(var i = 0; document.images.length; i++) {
alert(document.images[i].src);
alert(document.images[i].alt);
}
2.3.4 オブジェクトの生成
オブジェクトの生成には new を用います.以下に,オブジェクトを生成する例を示します.
第 2 章 JavaScript
388
図 2.1 Web ブラウザの管理するオブジェクトの例
var obj = new Object();
var date = new Date();
var s = new String("Hello, JavaScript!!!");
ここで,obj や date,s など,オブジェクトとして利用可能になったものをインスタンスと呼びます.
インスタンスメソッドとクラスメソッド
var date = new Date(); で生成された date インスタンスは,Date オブジェクトの持つメソッドを呼び出すことが
できるようになります.例えば,Date のもつメソッドには,日にちを参照する getDate() メソッドや曜日を参照する
getDay() メソッド,日にちを設定する setDate() メソッドなどがあります.date インスタンスを生成することで,以
下のように date.getDate(); などとして,Date オブジェクトのメソッドを呼び出すことができるようになります.こ
2.3 JavaScript の記法の特徴
389
のような,インスタンスを用いたメソッドのことをインスタンスメソッドと呼びます.
var date = new Date();
alert(date.getDate();
また,特定のオブジェクトのインスタンスを生成することなく利用できるメソッドもあります.例えば,Math オ
ブジェクトの持つメソッドは,インスタンスを生成することなく,呼び出すことができます.例えば,Math オブ
ジェクトには,引数の絶対値を返す abs() メソッドや乱数を生成する random() メソッドなどがあります.これは,
Math.abs(value); などのようにして,インスタンスを生成することなく直接呼び出すことができます.このような,イ
ンスタンスの生成を必要としないメソッドのことをクラスメソッドと呼びます.
また,Math オブジェクトには,メソッドの他に変数も定義されています.この変数は変更不可能な変数であり,定
数を意味します.例えば,円周率を表す PI や自然対数の底を表す E などです.これらは,メソッドの呼び出しのよう
に,Math.PI などとすることで呼び出すことができます.
2.3.5 関数
JavaScript で関数を作成する場合には,function を用いて,以下のように記述します.ここで,前に述べたように,
変数はオブジェクトですから引数に変数の型を指定する必要はありません.
function 関数名 (引数 1, 引数 2, ...) {
関数の中身
return 返り値;
}
第3章
Ajax
Ajax (Asynchronous JavaScript+XML) は JavaScript と XML を用いた非同期通信によるデータ処理方式です.
Ajax の重要な点は非同期通信にあり,必要なデータを必要な時に取得することでページの遷移をすることなく,ス
ムーズにデータの書き換え処理を行うことができます.Ajax は決して新しい技術ではなく,枯れた技術の集合によっ
て生み出された新しい概念です.新しい技術を必要とせずに標準技術のみによって構成されているので,従来の多くの
Web ブラウザでも動作させることができます.
3.1 Ajax の登場
Ajax とは,Asynchronous JavaScript+XML からなる造語で,2005 年に Jesse James Garrett 氏の「Ajax: A New
Approach to Web Applications [1]」の中で初めて登場しました.この中で Google Maps と Google Suggestion が取
り上げられており,これらの Web サービスにおける,Web サーバと Web ブラウザとの間で XML データのやりとり
を非同期に (Asynchronous) 通信を行い,DOM (Document Object Model) によって Web ページのコンテンツの一
部を動的に書き換える手法に着目しています.そして,この手法を Ajax と呼んでおり,Ajax の定義を以下のように
定義しています.
• Standards–based presentation using XHTML and CSS;
(XHTML と CSS と用いた標準規格による表現)
• dynamic display and interaction using the Document Object Model;
(DOM を用いた動的な表示とインタラクション)
• data interchange and manipulation using XML and XSLT;
(XML と XSLT を用いたデータの変換と操作)
• asynchronous data retrieval using XMLHttpRequest;
(XMLHttpRequest を用いた非同期データ検索)
• and JavaScript binding everything together.
(そして,JavaScript がこれらすべてを統合する.)
3.2 従来の Web アプリケーションとの違い
図 3.1 に従来の Web アプリケーションモデルでの通信方式と Ajax モデルによる通信方式を示します.従来の Web
アプリケーションモデルでは,クライアント(Web ブラウザ)と Web サーバ側とのやりとりを同期通信によって行
います.この通信方式では,クライアントが Web サーバへリクエストを行ってからレスポンスを受け取るまでの間,
Web ブラウザの操作ができません.ユーザは何らかの操作を行った後,データが返ってくるまで待たねばなりません
3.3 Ajax の特徴
391
でした.一方で,Ajax による非同期通信では,Web サーバとの通信はユーザの操作に関係なくバックグラウンドで実
行され,データのやり取りを行っている間も操作が可能です.
3.3 Ajax の特徴
Ajax の特徴を図 3.1 に示し,以下にその特徴を解説します.
3.3.1 待ち時間の低減
Ajax では非同期通信を行っているため,ユーザの待ち時間が減少します.これは,Web サーバへのデータ通信の
間,ユーザは他の操作を行うことができるからです.これによって,ユーザの待ち時間に関わる負担が軽減されます.
3.3.2 ブラウザへの依存
Ajax では,一般的にクライアントサイドの言語に JavaScript を用います.また,動的な処理を行うため DOM 操作
を行うことが多くあります.これらの技術は,いずれも Web ブラウザがサポートしている必要があります.また,そ
の実装は Web ブラウザによって異なるため,挙動や動作スピードが Web ブラウザや,そのバージョンによって異な
ることに注意が必要です.また,携帯端末などの Web ブラウザではこれらをサポートしていないケースもあることを
留意する必要があります.
3.3.3 動的なページの改変
Ajax では,ユーザの操作中にデータの送受信を行っています.そのため,Web ページを遷移することなく,コンテ
ンツを新しい情報に書き換えることが可能になります.これによって,スムーズな画像表示や,入力内容に適した情報
の更新などが実現されます.
3.4 通信の制約
JavaScript では,XMLHttpRequest メソッドを用いることでファイルを取得することができます.しかし,このと
き異なるドメインに存在するファイルにアクセスすることは,セキュリティの問題から禁止されています.
第3章
392
図 3.1 Ajax による非同期通信の特徴
Ajax
第4章
XML データの操作
XML 文書のデータの取得や追加,変更などの操作は SAX (Simple API for XML) や DOM (Document Object
Model) といった仕組みを用いて行うことができます.ここでは,JavaScript を用いた DOM による XML 文書の操作
について解説します.
4.1 DOM
DOM (Document Object Model) とは,XML 文書や HTML 文書を扱うための API (Application Programing
Interface) の 1 つです.DOM は,2009 年 7 月現在,W3C により DOM Level 1∼3 までが勧告されています.
4.1.1 DOM ツリー
XML 文書や HTML 文書はその文書構造として木構造をとります.この木構造のことを DOM ツリーと呼びます.
例として,具体的な HTML 文書の DOM ツリー例を図 4.1 に示します.ここで,要素の内容は省略していますが,内
容も木構造のノード(テキストノード)として扱われます.木構造でのノードとは,XML における要素 (element) や
内容 (content) のことを指します.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp">
<head>
<title>xhtml sample</title>
</head>
<body>
<h1>XHTML SAMPLE</h1>
<p>これは,<em>XHTML</em>による XML 文書の例です.</p>
<hr />
<h2>XML Structure</h2>
<p><img src="./xmlstructure.png" alt="XML の文書構造" /></p>
</body>
第4章
394
XML データの操作
</html>
図 4.1 DOM ツリー
4.2 DOM ツリーの操作
DOM ツリーの操作のために,XML 文書の要素などの取得や追加,変更を行うためのメソッドが用意されています.
4.2.1 document のメソッド
document に対するノードを生成したり,取得したりするためのメソッドが用意されています.document に対する
メソッドの一覧を表 4.1 に示します.
表 4.1 document のメソッド
メソッド
意味
createElement()
ノードを生成する
getElementsByTagName()
タグの名前からノードを指定する
getElementById()
タグの id 属性からノードを指定する
getElementsByName()
タグの name 属性からノードを指定する
ここで,TagName,Name は複数あるため Elements となっていますが,id 属性は文書中に 1 つしか存在しないため,
element となっている点に注意します.
以下に,getElementsByTagName() メソッドを用いて,p 要素を取得する例を示します.
document.getElementsByTagName("p");
4.2 DOM ツリーの操作
395
4.2.2 ノードプロパティ
DOM ツリーのノードには,JavaScript からアクセスできるプロパティ(ノードプロパティ)が用意されています.
ノードプロパティを利用することで,ノードの様々な情報を取得できます.ノードプロパティの種類を表 4.2 に示し
ます.
表 4.2 ノードプロパティ
ノードプロパティ
意味
childNodes
子ノード(配列)
parentNode
親ノード
firstChild
子ノードの先頭のノード
lastChild
子ノードの末尾のノード
nodeName
ノード名
nodeValue
ノードの値
nodeType
ノードの型
attributes
属性(配列)
ノードプロパティによる XML の操作の例を示します.
var para = document.getElementsByTagName("p");
var text = para[0].firstChild.nodeValue;
document.getElementById("result1").textContent = text;
1 行目の var para = document.getElementsByTagName(”p”); で para 変数に p ノードの配列を格納していま
す.2 行目 var text = para[0].firstChildNodeValue; では,p 要素の最初のノードの値を取得しています.3 行目の
document.getElementById(”copy”).textContent = text; では,id の属性値が copy であるノードの内容に text を格
納しています.
4.2.3 要素の追加・削除
ノードの追加や削除を行うためのメソッドを表 4.3 に示します.
表 4.3
ノードの追加,削除
メソッド
意味
createElement()
ノードを作成する
createTextNode()
テキストノードを作成する
appendChild()
ノードを子要素として追加する
removeChild()
子ノードを削除する
第4章
396
XML データの操作
var newele = document.createElement("div");
var text = document.createTextNode("Hello, DOM!!");
newele.appendChild(text);
document.body.appendChild(newele);
この例では,まず 1 行目の var newele = document.createElement(”div”); で div 要素を作製しています.その後,2
行目の var text = document.createTextNode(”Hello, DOM!!”); でノードテキストを作製しています.作製したノー
ドテキストは 3 行目の newele.appendChild(text); として newele で表される div 要素に付加しています.さらに,4
行目の document.body.appendChild(newele); とすることで,HTML 文書に反映させています.
属性の追加・取得
ノードの属性値の追加や削除を行うためのメソッドを表 4.4 に示します.
表 4.4 属性の取得,追加
メソッド
意味
setAttribute(属性名, 属性値)
属性値を与える
getAttribute()
属性値を取得する
var para = document.getElementsByTagName("p");
para[2].setAttribute("id", "result");
この例では,まず 1 行目の var para = document.getElementsByTagName(”p”); で p 要素を全て取得しています.
次に,2 行目の para[2].setAttribute(”id”, ”result”); では,para[2] とすることで,p 要素の 3 番目の要素に,id 属性
として result という値を設定しています.
第 14 回 演習課題
目標
JavaScript を用いて,HTML 文書や XML 文書を操作します.
まず,簡単な HTML 文書を表示する JavaScript を作成します.次に,XML 文書から要素を抽出する JavaScript
を作成します.
課題 1 JavaScript による DOM 操作
1–1
以下の HTML 文書を作成し,サーバに設置して下さい.ファイル名は任意とします.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp">
<head>
<title>DOM の練習</title>
<script type="text/javascript" src="pracdom.js"></script>
</head>
<body>
<h1>実行例</h1>
<form>
<p><input type="button" value="load" onclick="javascript:getResult();" /></p>
</form>
<div id="result1"></div>
</body>
</html>
1–2
id 属性の属性値が result の div 要素に Hello, JavaScript!と表示する JavaScript のスクリプトを作成して下さい.た
だし,処理は getResult 関数に記述し,ファイル名は pracdom.js として下さい.また,HTML 文書は変更しないで下
さい.
※ Web ページに埋め込まれたボタンをクリックすると,pracdom.js の getResult 関数が実行されるよう HTML 文
書を記述しています.
第4章
398
第 14 回 演習課題
1–3
以下の XML(第 13 回の発展課題で作製した XML 文書でもよい)から,この XML 文書に登録されている name 要
素とその population 要素を JavaScript を用いて抽出しその一覧表を作成して下さい.
必要であれば,以下の HTML,JavaScript コードのひな形を利用して下さい.
XML 文書
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<cities>
<city code="sapporo" prefecture="hokkaido">
<name>札幌</name>
<population>1889352</population>
<symbol>
<tree>ライラック</tree>
<flower>スズラン</flower>
<bird>カッコウ</bird>
<other />
</symbol>
</city>
<city code="hakodate" prefecture="hokkaido">
<name>函館</name>
<population>284967</population>
<symbol>
<tree>イチイ</tree>
<flower>ツツジ</flower>
<bird>ヤマガラ</bird>
<other type="fish">イカ</other>
</symbol>
</city>
</cities>
HTML 文書
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp">
<head>
<title>北海道の都市</title>
<script type="text/javascript" src="hokkaido.js"></script>
</head>
<body>
399
<h1>一覧</h1>
<form>
<p><input type="button" value="リストの取得" onclick="getResult();" /></p>
</form>
<div id="result"></div>
</body>
</html>
hokkaido.js
var request;
function getResult() {
loadXML();
}
function loadXML() {
request = new XMLHttpRequest();
request.open(’GET’, ’./hokkaido.xml’, true);
request.onreadystatechange = parseXML;
request.send(null);
}
function parseXML() {
if(request.readyState == 4 && request.status == 200) {
var xml = request.responseXML;
//
}
}
ここに処理を追加する
参考文献
[1] Jesse James Grrett, adaptive path >> ajax: a new approach to web applications, http://www.adaptivepath.
com/ideas/essays/archives/000385.php
第 15 回
マッシュアップ入門(2)
Web API に多く利用されている通信方式とデータ形式について解説します.また,プロトコル
形式として XML-RPC,REST,データ形式として RSS/ATOM,JSON などについて具体的に
説明します.演習では,REST と JSONP によりデータを取得する Web アプリケーションの
JavaScript プログラミングを行うことにより,Web API の利用方法について学びます.
本資料は Ubuntu 9.04 の使用を前提に構成されています.また,掲載されているソースコードなどは UTF–8 で記述し,Web ブ
ラウザは Mozilla Firefox 3 を使用することを前提として作成されています.使用している API の仕様変更などにより,記述通り
に動作しないことがあります.
第1章
プロトコル
Web ページのコンテンツ取得やメールの受信など,サーバからのデータを受信する際にはそれに応じて,決めら
れたプロトコルを使用することになっていました.これまで見てきたように,メールサーバからのメールの受信には
SMTP や POP3 など,Web ページの取得には HTTP や ftp などを使用します.
ここでは,マッシュアップサイトを構築する際に必要となる通信方式の特徴について,他の通信方式と比較しつつ解
説します.
1.1 RPC
RPC (Remote Procedure Call: 遠隔手続き呼び出し) とは,ネットワーク上で稼働する他の端末のサービスを呼び出
すためのプロトコルです.
図 1.1 に RPC サーバ上で稼働するサービスの手続き (procedure) を呼び出した場合の概念図を示します.RPC ク
ライアントは,RPC サーバに対して手続きを呼び出すリクエストを送信します.リクエストを受けた RPC サーバは
該当する手続きを実行した後,実行結果を RPC サーバへ返します.このようにして,RPC クライアントは自身が所
有しないデータを取得できたり,稼働していないサービスの処理結果を取得することができます.
図 1.1
RPC による手続きの呼び出し
1.2 XML–RPC
XML–RPC [6] は RPC を元にし,XML を用いて HTTP によって通信を行う RPC プロトコルのひとつです.
XML–RPC は第 13 回 4 章で触れた SOAP の元となった技術です.
XML–RPC では,HTTP ヘッダと XML によって記述された通信内容をひとつのデータとしてやり取りを行いま
す.このとき,HTTP ヘッダと XML をまとめたデータのことを envelope(エンベロープ)と呼びます.このように,
1.2 XML–RPC
403
通信の際のプロトコルと実際のデータをまとめて取り扱う方式で,特に,図 1.2 のように,XML を用いてデータを符
号化したものを XML–RPC と呼びます.
図 1.2
XML–RPC による手続きの呼び出し
以下に,リクエストの例を示します.
POST /RPC2 HTTP/1.0
User-Agent: Frontier/5.1.2 (WinNT)
Host: betty.userland.com
Content-Type: text/xml
Content-length: 181
<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>41</i4></value>
</param>
</params>
</methodCall>
まず,先頭部分には,HTTP ヘッダが記述されます.POST メソッドを用いており,文書型は text/xml,文書の長
さは 181 であることなどが記述されています.XML–RPC では,文書のデータ形式に XML を用いますので,文書型
は必ず text/xml となります.
XML ヘッダの後には実際のデータが XML によって記述されます.methodName 要素によって,呼び出すための手
続きを指定します.これは,スクリプトのファイルであったり,データベースのセル名であったり,ファイルのパスで
あったりします.
リクエストに対するレスポンスの例を以下に示します.
HTTP/1.1 200 OK
第 1 章 プロトコル
404
Connection: close
Content-Length: 158
Content-Type: text/xml
Date: Fri, 17 Jul 1998 19:55:08 GMT
Server: UserLand Frontier/5.1.2-WinNT
<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value><string>South Dakota</string></value>
</param>
</params>
</methodResponse>
この場合も,HTTP ヘッダが先頭部分に記述されます.エラーが発生しなければ,200 OK が返されます.
XML データでは,South Dakota という sting の値が返送されていることが分かります.
このように,XML–RPC では,遠隔端末で稼働しているサービスの特定の手続きにリクエストを送り,データを受
け取ることができます.また,その際のデータは,HTTP ヘッダ部と XML によって記述されます.
1.3 SOAP
SOAP (Simple Object Access Protocol) は,通信に用いるプロトコルと,通信を行うデータ形式を同時に規定したプ
ロトコルです.主に通信プロトコルに HTTP,送受信するデータに XML を用います.WSDL や UDDI などととも
に,Web サービスのプロトコルとして用いられます.詳細は第 13 回 4 章を参照して下さい.
1.4 REST
REST (Representational State Transfer) は R. Fielding が 2000 年に発表した論文で初めて使われた単語です.
URI によって指定したリソースを HTTP を用いて利用する方式を REST と呼びます.しかし,厳密に Fielding の定
義に従っていない Web サービスも多く存在しており,ここでは XML のやり取りに SOAP を用いずに,HTTP を用
いた通信方式のことを REST と呼ぶこととします.
例えば,REST (Representational State Transfer) は,SOAP や WSDL,UDDI を使用することなく Web サービス
を提供できます.REST はリソースに着目することでシンプルな通信方式を実現しています.必要な情報(リソース)
がどこにあるのか,ということに着目した方式で,通信に必要となるのはリソースの URI です.従って,URI で問い
合わせるだけですから,この方式のプロトコルには一般的に用いられている HTTP を用いることにより実現可能で,
WSDL のようにプロトコルなどを規定したインタフェイス情報も必要としません.このような REST の思想に則った
Web サービスを,RESTful Web サービスと呼ぶこともあります.
REST では,リソースを URI を用いて表現します.以下に例を示します.
http://www.example.com/japan/hokkaido/cities/
(1)
http://www.example.com/japan/okinawa/village/
(2)
1.4 REST
405
http://www.example.com/cities?country=jp&prefecture=hokkaido
(3)
http://www.example.com/cities?country=jp&prefecture=okinawa
(4)
例えば,(1) の例は,日本国の北海道にある市の情報を示す URL です.(2) は,日本国の沖縄県の村の情報を示す
URL です.
また,URI は固有の URI であればよいので,(3) や (4) のように実装されることも多くあります.(3) では,
http://www.example.com/cities に country=jp と prefecture=hokkaido というパラメータを付加してリクエストを
行うことで,日本国の北海道の市の情報を表しています.(4) も同様に,沖縄県の情報を示しています.実際の Web
API では,このように URI にパラメータを付加して HTTP GET リクエストを送ることで,情報を取得できる実装例
が多数あります.
このように,REST によるデータのやり取りは,RPC を用いた XML–RPC や SOAP などに比べ,URI の HTTP
リクエストを送信するだけで済むため,手軽に利用することができます.
第2章
データ形式
この章ではマッシュアップサイト構築の際に,やり取りされるデータ形式について解説します.
これまで見てきたように,Web API に用いられる通信方式には,SOAP を利用した XML–RPC や REST がありま
す.これらの通信方式では,XML が広く使用されています.しかし,XML の他にもリソースの配信方法を考慮し考
え出された RSS/Atom や,スクリプト言語から簡易に扱えるような JSON などのフォーマットも利用されています.
ここでは,Web API に広く採用されているフォーマットについて解説します.
2.1 XML
XML は第 13 回の 2 章で詳しく扱いました.また,それ以降も,多くの場面で XML が利用されていることが理解
できたと思います.Web 技術において XML は幅広い部分の根底を支える技術のひとつです.
Web API において送受信されるデータも,その多くが XML や XML を元にした拡張言語であることが多いです.
SOAP による通信や REST の考え方に則った通信方式,また,この後解説する RSS や Atom フィードも XML を利
用しています.
2.2 RSS/Atom
この数年で Weblog とよばれる個人の日記形式の Web サイトが急速に広まり,手軽に個人が情報発信を行うことが
できるようになりました.一方で,新聞社では自社の記事を積極的に Web に掲載するようになってきており,Web 独
自の記事を掲載している場合も少なくありません.また,一般企業においても企業としての公式情報を Web 上で配信
するといったサービスが広まりを見せています.こういった,記事を配信する(フィード: feed)際には,そのほとん
どが RSS や Atom といったフォーマットが用いられています.これは,RSS や Atom といった形式が記事の配信に適
したフォーマットだからです.
RSS や Atom は,Web 上でのコンテンツを配信するためのフォーマットを規定しており,急速に広まっている技
術ではありますが,RSS の仕様はその歴史的な経緯から若干の混乱を生じる事態となっています.まずは,混在する
RSS のバージョンの整理と RSS と Atom との関連性について解説します.
2.2.1 RSS と Atom の歴史的経緯
RSS はその歴史的経緯からいくつかのバージョンが存在し,それらの略称も異なります.RSS の各バージョンを公
開された順番に簡単に紹介します.
2.2 RSS/Atom
407
RSS 0.9
RSS と呼ばれる仕様の最初のものは RSS 0.9 です.RDF 構文(2.4 節参照)を用いた仕様です.この RSS は RDF
Site Summary の略語です.
RSS 0.91
RDF を用いずに,XML を用いた仕様が RSS 0.91 です.RSS 0.9 に比べ拡張性の高い仕様です.この RSS は,そ
ういった経緯から,Rich Site Summary と略語とされています.
RSS 1.0
RSS 0.91 では,拡張性の高さによって利用者が独自に要素を追加するなど,混乱の元となりました.これに対応す
るために,RSS 0.9 を見直し,再び RDF を採用したものが,RSS 1.0 です.RSS 1.0 は RSS 0.9 を元にしたものであ
るため,RSS 0.9 と同様に RDF Site Summary の略称とされています.
RSS 1.0 は,2010 年現在,Weblog やニュース配信などで広く利用されているフォーマットです.この詳細は 2.4 節
で解説します.
RSS 0.92
RSS 1.0 の仕様が公開された 2 週間後には,RDF を用いない複雑な仕様となった RSS 1.0 に反対する立場の陣営か
ら,RSS 0.91 の上位互換となる RSS 0.92 の仕様が公開されました.XML による複雑さを持った仕様に反発し,シン
プルな RDF による RSS を求めた結果,RSS 1.0 と RSS 0.92 という 2 つの標準仕様が混在することになりました.
しかし,この RSS 0.92 は RSS 1.0 とは互換性があるため,RSS を利用しているユーザにとってはそれほど問題で
はありませんでした.
RSS 2.0
このような状態から,RSS 1.0 と RSS 0.92 を統合された仕様を策定しようとする動きが生じます.しかし,RDF を
使用する立場と使用しない立場との双方を取り入れた仕様はまとまりませんでした.RDF の採用を訴える RSS 0.92
側の陣営は,新しい仕様として(RSS 1.0 と互換性のない)RSS 2.0 の仕様を公開します.
こうして,双方に互換性のない RSS 1.0 と RSS 2.0 という仕様が誕生し,現在それらが混在しています.RSS 2.0
の詳細は 2.3 節で解説します.
Atom
Atom は,以上のような RSS の複雑な仕様の変遷を解決することを目的にし,標準化が進められている仕様です.
現在,RSS は RDF による RSS 1.0 と RDF を用いない RSS 2.0 の 2 種類存在し,番号が振られているにも関わら
ず,それぞれには互換性がなく,これらは異なる技術であると考えてよいほどです.このような現状を解決するため
に,RSS 3.0 を作成するのではなく,仕様を一から定めようという動きが出てきました.この仕様は,現在 Atom と呼
ばれており,IETF (The Internet Engineering Task Force)
*1 によって標準化作業が進められています.2010
年現在,
Atom 1.0 の仕様が公開されています.この詳細は 2.5 節で解説します.
*1
インターネット技術タスクフォース.インターネットに関わる技術の標準化を行う組織のひとつ.ワーキンググループのメーリングリストに
参加することで誰でも議論への参加が可能.標準化された仕様は RFC (Request For Comments) 文書として公開される.
第 2 章 データ形式
408
2.3 RSS 2.0
RSS 2.0 は XML によって表現されます.ルート要素は,rss で version 属性として 2.0 を付加します.また,ルート
要素には,子要素として channel と item 要素が含まれます.channel 要素にはフィードを配信する組織や人物,Web
サイトなどを記述し,item 要素にはフィードで配信する実際の内容を記述します.channel 要素は rss 要素に 1 つ出現
しますが,item 要素はいくつ出現しても構いません.
2.3.1 channel 要素の子要素
channel 要素は子要素として title, link, description の 3 種類の必須要素と,16 種類のオプションの要素を持ちます.
表 2.1 に channel 要素の子要素の一覧と指定する属性,要素の意味を示します.
2.3.2 item 要素の子要素
item 要素は RSS フィードの内容を記述する部分です.item 要素には,子要素として指定できる 10 種類の要素が定
義されています.表 2.2 に item 要素の子要素の一覧と指定する属性,要素の意味を示します.これらの子要素には必
須の要素はありませんが,少なくとも title 要素,もしくは description 要素のいずれかを記述する必要があります.
2.3.3 RSS 2.0 形式のフィードの例
図 2.1 に RSS 2.0 の木構造を示します.RSS 2.0 による XML 文書はこのような構造となります.
実際の RSS 2.0 による XML 文書の例を以下に示します.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<rss version="2.0" >
<channel>
<title>RSS 2.0 Feed Test</title>
<link>http://example.com</link>
<description>RSS 2.0 のテスト用フィード</description>
<language>ja</language>
<pubDate>Tue, 10 Jun 2003 04:00:00 GMT</pubDate>
<item>
<description>RSS 2.0 のテスト</description>
</item>
</channel>
</rss>
*2
*3
Platform for Internet Content Selection.Web 上のフィルタリングを扱う.
ポッドキャスティングなどで利用されている.
2.4 RSS 1.0
409
表 2.1 channel 要素の子要素
channel 要素の子要素
属性
意味
title(必須要素)
フィード配信者の名称
link(必須要素)
フィードの URI
description(必須要素)
フィードの配信者の説明
languatge
フィードの記述言語
copyright
フィードの著作権表示
managingEditor
編集者の連絡先(電子メールアドレス)
webMaster
Web マスターの連絡先(電子メールアドレス)
pubDate
フィード内の記事の発行日時
lastBuildDate
フィードの最終更新日時
category
カテゴリー
generator
RSS ファイルの作成に用いたアプリケーション
docs
フィードの説明の URL
cloud
更新通知に用いるための情報を指定する
ttl
time–to–Live.フィードの更新頻度の最小単位
image
url
画像
title
link
width
height
description
rating
rating
textInput
PICS
title
*2 の格付け
フォーム
description
name
link
skipHours
ユーザのフィード読み取りのタイミングを制御
skipDays
ユーザのフィード読み取りのタイミングを制御
2.4 RSS 1.0
RSS 1.0 では RDF を用いた記述方法を採用しています.このため,RSS 2.0 よりも高い拡張能力を持ちますが,そ
の反面複雑に見えることがあります.2010 年現在,Weblog やニュースフィードなどで広く用いられています.
2.4.1 RDF
RDF (Resource Description Framework) はリソースを表現するための仕組みです.RDF は主語 (subject),述
語 (predicate),目的語 (object) の 3 つの構成要素からなり,これらをまとめてトリプルと呼びます.
第 2 章 データ形式
410
表 2.2 item 要素の子要素
item 要素の子要素
属性
意味
title
記事のタイトル
link
記事の URL
description
記事の概要
author
作者の情報(電子メールアドレス)
category
記事のカテゴリ
comment
コメントページの URL
enclosure
url
エンクロージャの情報
*3
type
length
guid
Globally Unique Identifire.グローバルで一意の値.URL でもよい
pubDate
発行日時
source
url
サイトのフィード名
図 2.1 RSS 2.0 の木構造の例
2.4 RSS 1.0
411
ここでいうリソースとは,URI によってアドレス指定可能なものを指します.例えば,リソースの表現として以下
のような文を考えます.
「”The origin of species” の著者は Darwin である.」
ここで,主語は The origin of species,述語は著者である,目的語は Darwin となります.これを,RDF での知識
表現に当てはめた例を以下に示します.
<description about="The origin of species">
<author>Darwin</author>
</descritption>
2.4.2 RSS 1.0 文書の記述
RSS 1.0 による文書は RDF によって記述されます.また,RDF は XML によって定義されていますから,RSS 1.0
文書は XML の仕様に基づいて記述されます.
RSS 1.0 文書は,RDF によって記述されるので RDF をルート要素とします.また,xmlns 属性によって名前空間
(第 13 回 2.6 節参照)を指定し,接頭辞 rdf を用いることで表現します.さらに,RSS の名前空間をデフォルト名前
空間として指定します.RDF の名前空間は http://w3.org/1999/02/22-rdf-syntax-ns#,RSS 1.0 の名前空間は
http://purl.org/rss/1.0/ です.従って,RSS 1.0 による XML 文書のルート要素は以下のように記述されます.
<rdf:RDF xmlns="http://purl.org/rss/1.0/"
xmlns:rdf="http://w3.org/1999/02/22-rdf-syntax-ns#">
</rdf:RDF>
2.4.3 RSS 1.0 の文書構造
RSS 1.0 文書はルート要素 rdf の子要素である channel や image,textinput 要素,そして複数の item 要素から構成
されます.図 2.2 に RSS 1.0 の木構造の例を示します.
channel 要素
channel 要素は記述が必須となる要素です.channel 要素では,rdf:about 属性によって,配信フィード自身,もしく
はフィードを配信するサイトの URL が指定されます.
また,channel 要素は title, description, link 要素の 3 種類の記述が必須の子要素と,約 30 種類のオプションの子要
素を持ちます.
記述が必須の子要素である title 要素はフィードのタイトルを記述し,description 要素にはフィードの要約,link 要
素にはフィードが示すサイトの URL を記述します.
image 要素
image 要素は画像のリソースを指定するための要素です.image 要素では rdf:resource 属性によって画像ファイルの
URL を指定します.この要素はオプションの要素です.なお,使用する画像サイズは幅が 144 pixel,高さが 400 pixel
までのものを指定できますが,現実的な運用を考慮し 88 × 31 pixel が推奨されています.
この image 要素は,title, url, link の記述が必須となる 3 種類の子要素をとります.title 要素は HTML における
第 2 章 データ形式
412
図 2.2 RSS 1.0 の木構造の例
2.4 RSS 1.0
413
画像タグの代替テキスト(alt 属性)に相当します.url 要素は画像ファイルの URL を指定します.image 要素の
rdf:resource 属性と同様です.link 要素は画像ファイルへ関連付けるハイパーリンクの URL を指定します.通常,
channel 要素の子要素である link 要素と同様の URL を設定することになります.
textinput 要素
textinput 要素はフォームを生成します.これは,フィードの検索などの目的のために CGI スクリプトが設置される
ことを想定し設けられた要素です.
この textinput 要素は,子要素に title, description, name, link 要素を持ちます.title 要素はボタンのラベルを指定
し,description 要素にはフォームの動作の説明,name 要素には実際に CGI に渡されるオブジェクト名,link 要素に
は CGI スクリプトの URL を記述します.
2.4.4 RSS 1.0 文書の例
以下に,簡単な RSS 1.0 フィードの例を示します.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<rdf:RDF xmlns="http://purl.org/rss/1.0/"
xmlns:rdf="http://w3.org/1999/02/22-rdf-syntax-ns#">
<channel rdf:about="http://example.com/rss10/">
<title>RSS 1.0 の例</title>
<link>http://example.com/rss10/</link>
<description>RSS 1.0 の例を示した文書</description>
<items>
<rdf:Seq>
<rdf:li rdf:resource="http://example.com/entry1" />
<rdf:li rdf:resource="http://example.com/entry2" />
</rdf:Seeq>
</items>
</channel>
<item rdf:about="http://example.com/entry1/">
<title>最初の記事</title>
<link>http://example.com/entry/</link>
</item>
<item rdf:about="http://example.com/entry2/">
<title>2 つ目の記事</title>
<link>http://example.com/entry2/</link>
</item>
</rdf:RDF>
第 2 章 データ形式
414
2.5 Atom
Atom の主な仕様は,Web へコンテンツを配信するための Atom 配信プロトコル (The Atom Syndication Format)
と Web 上のリソースの出版までを考慮する一連のプロセスを定義した Atom 出版プロトコル (The Atom Publishing
Protocol) の 2 つです.ここでは,Web 上での記事の配信に用いられる Atom 配信プロトコルを取り上げます.
2.5.1 Atom 配信プロトコル
Atom 配信プロトコルのルート要素は feed です.feed 要素には Atom の名前空間 http://www.w3.org/2005/Atom
を指定します.
feed 要素は複数の entry 要素を持ちます.entry 要素にはフィードの内容が記述されます.entry 要素は title, link,
id, updated, summary などの子要素を持ちます.
Atom によるフィードの例を以下に示します.
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>フィードの名前</title>
<link href="http://www.example.com/"/>
<updated>2009-11-25T09:00:00Z</updated>
<author>
<name>著者の名前</name>
</author>
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
<entry>
<title>記事のタイトル</title>
<link href="http://www.example.com/2009/11/25/atom03"/>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<updated>2009-11-25T09:00:00Z</updated>
<summary>ここには,記事の要約が記述されます.</summary>
</entry>
</feed>
XML 宣言の後,feed 要素で全体を括っています.名前空間は http://www.w3.org/2005/Atom を指定します.
title や link などのフィードを説明する要素を記述した後,実際の記事は entry 要素を列挙して記述します.
2.6 JSON
JSON (JavaScript Object Notation) は構造化データの記述形式の 1 つで,XML などのようにテキストデータで記
2.6 JSON
415
述されるデータベースです.JSON はその名前の由来の通り,JavaScript のオブジェクトの表現形式を採用していま
す.2006 年に IETF によって標準化されています [5].
JSON によるデータベースは,JavaScript のオブジェクトや配列の表現形式を用いて表現されます.
配列
JavaScript では,データの全体を [...] で括り,データを「,」で区切ることで配列を表現できます.以下に配列の例
を示します.
["札幌", "旭川", "函館", "釧路", "苫小牧", "帯広"]
オブジェクト
JavaScript において,オブジェクトはプロパティ値を持つことができます.例えば,円を表すオブジェクトを生成
した場合,このオブジェクトに中心の座標や半径といった付随情報を持たせることができます.例えば,この場合は
JavaScript では以下のようにすることで circle オブジェクトを生成できます.
var circle = { x: 100, y: 50, radius: 10 }
オブジェクトのプロパティは,{ プロパティ 1 の名前:プロパティ 1 の値, プロパティ 2 の名前:プロパティ 2 の値,
...} といったように,「:」で区切ることで記述します.また,「,」で区切ることで複数のプロパティを表現できます.
JSON においても同様に記述することができます.JSON における例を以下に示します.
{ "名前":"札幌", "人口":1889352 }
なお,文字列は”...”で括ることで表現できます.
データ型
JSON で扱うことのできるデータには,オブジェクトや配列など以下のようなものがあります.
• オブジェクト
• 配列
• 数値
• 文字列
• false
• true
• null
オブジェクトと配列のネスト
JSON では配列やオブジェクトをネストすることで同時に扱うことができます.また,これによってデータベースの
構造を表現できます.
ネストによって構造化された例を以下に示します.
第 2 章 データ形式
416
{ "シンボル":["木", "花", "鳥"] }
この例では,オブジェクトに与えられたシンボルプロパティのプロパティ値として,木,花,鳥からなる配列を指定
しています.
これらを踏まえた,JSON による単純なデータベースの例を以下に示します.
{"名前":"札幌","人口":1889352,"シンボル":{"木":"ライラック","花":"スズラン","鳥":"カッコウ"}}
この例では,オブジェクトのプロパティとして名前,人口,シンボルを付加しており,それぞれのプロパティ値が指
定されています.名前に対するプロパティ値札幌と人口に対するプロパティ値 1889352 は,それぞれ文字列と数値で
すが,シンボルのプロパティ値にはオブジェクトが指定されていることがわかります.
この表現は,インデントを行った上で XML 文書の例と見比べると,同様の構造を表現できていることが分かります.
JSON での表現
{
"名前": "札幌",
"人口": 1889352,
"シンボル": {
"木": "ライラック",
"花": "スズラン",
"鳥": "カッコウ"
}
}
XML での表現
<市>
<名前>札幌</名前>
<人口>1889352</人口>
<シンボル>
<木>ライラック</木>
<花>スズラン</花>
<鳥>カッコウ</鳥>
</シンボル>
</市>
また,全体を市を表すひとつのオブジェクトとしてまとめ,各市を配列を用いて表現すると,以下のような JSON に
よる表現が得られます.
{ "市":
2.6 JSON
417
[
{"名前":"札幌","人口":1889352,"シンボル":{
"木":"ライラック","花":"スズラン","鳥":"カッコウ"}},
{"名前":"旭川","人口":354572,"シンボル":{
"木":"ナナカマド","花":"ツツジ","鳥":"キレンジャク","虫":"カンタン"}},
{"名前":"函館","人口":284967,"シンボル":{
"木":"イチイ","花":"ツツジ","鳥":"ヤマガラ","魚":"イカ"}}
]
}
2.6.1 JavaScript による JSON の利用例
具体的に JavaScript を用いた JSON を利用する例を見てみます.
以下に同一サーバに設置した JSON ファイルを読み込む場合の例を示します.この場合も,第 14 回で用いた XML
を読み込むための XMLHttpRequest メソッドを利用することができます.
jsonTest.html
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp">
<head>
<title>JSON の練習</title>
<script type="text/javascript" src="jsonTest.js"></script>
</head>
<body>
<h1>実行例</h1>
<form>
<form action="">
<p><input type="button" value="load" onclick="javascirpt:getResult();" /></p>
</form>
</form>
<div id="result"></div>
</body>
</html>
jsonTest.js
function getResult() {
request = new XMLHttpRequest();
request.open(’GET’, ’./jsonTest.txt’, true);
request.onreadystatechange = parseJSON;
第 2 章 データ形式
418
request.send(null);
}
function parseJSON() {
if(request.readyState == 4 && request.status == 200) {
var data = request.responseText;
// (1)
var obj = eval("("+ data + ")");
// (2)
var table = "<table>";
table += "<tr><th>都市名</th><th>人口</th>
<th>シンボル(木)</th><th>シンボル(花)</th><th>シンボル(鳥)</th></tr>";
for(var i = 0; i < obj.city.length; i++) {
// (3)
table += "<tr>";
table += "<td>" + obj.city[i].name + "</td>";
// (4)
table += "<td>" + obj.city[i].population + "</td>";
table += "<td>" + obj.city[i].symbol.tree + "</td>";
table += "<td>" + obj.city[i].symbol.flower + "</td>";
table += "<td>" + obj.city[i].symbol.bird + "</td>";
table += "</td>";
}
document.getElementById(’result’).innerHTML = table;
// (5)
}
}
jsonTest.txt
{ "city":
[
{"name":"札幌", "population":1889352, "symbol":{
"tree":"ライラック", "flower":"スズラン", "bird":"カッコウ"}},
{"name":"旭川", "population":354572, "symbol":{
"tree":"ナナカマド", "flower":"ツツジ", "bird":"キレンジャク", "incect":"カンタン"}},
{"name":"函館", "population":284967, "symbol":{
"tree":"イチイ", "flower":"ツツジ", "bird":"ヤマガラ", "fish":"イカ"}}
]
}
jsonTest.js の (1) では,取得した JSON 形式のデータを格納するオブジェクト data を生成しています.ここでは,
通信によって受け取ったデータは文字列ですので,data に格納されているデータの型は文字列型として扱われてい
ます.
(2) では,data に格納されている文字列を eval メソッドを用いて式として評価することによって,オブジェクトと
して obj に格納しています.この作業によって,obj.city や obj.city[1].name などのようにしてプロパティ値を参照す
2.7 JSONP
419
ることができるようになります.
(3) では,city のプロパティ値の配列の長さを取得し,その回数分ループを実行します.
(4) 以降では,実際のプロパティ値を読み出し,テーブルのセルとして HTML 形式で記述しています.
(5) では,HTML 形式で記述した table の内容を,id 属性が result の要素に埋め込んで(置き換えて)います.
図 2.3 にこの実行結果を示します.
図 2.3
実行結果
2.7 JSONP
JSONP (JSON with padding) は,JSON で返すデータを関数呼び出しの形で記述しておき,JSONP 形式のファイ
ルを読み込むことで,JavsScript の関数を呼び出すことができるようにした仕組みです.
JSONP の利点は XMLHttpRequest のクロスドメイン制約に対応できる点が上げられます.通常,XMLHttpRequest
による通信は,同一のドメインに限られます.これは,文書の改ざんなどのセキュリティ上の問題への対策として設け
られたポリシーです.このようなことから,一般に公開された Web API を使用したデータのやり取りは異なる Web
サーバ間でのやり取りとなるため,通常は Web API によるデータを受信することはできません.
この点を解決したのが,関数呼び出しの形でデータを送信する JSONP の形式です.script 要素の src 属性にファイ
ルを指定することで,HTML 文書の一部として扱われます.従って,script 要素に読み込まれた JSONP のデータは
関数呼び出しの形になっており,さらに,引数に受信したデータが指定されているため,JavaScript に書かれた関数に
データを渡すことができるようになります.
以下に,callback 関数を用いた JSONP による関数呼び出しの例を示します.
callback( {"shape": "box", "color": "green", "size": "large"} )
function callback(data) {
alert(data.shape);
}
JSONP のデータでは,全体を callback 関数で括ることで,callback 関数の引数にオブジェクトを指定したことにな
第 2 章 データ形式
420
ります.これによって,JavaScript に記述された callback へ JSONP で指定されたオブジェクトが渡されます.
このようにデータを関数呼び出しとして渡すことで,XMLHttpRequest() メソッドを用いることなく,またクロス
ドメインにとらわれることなく非同期通信が実現できます.ただし,渡されるデータの安全性を考慮する必要がありま
す.これは,渡されるデータの引数に悪意をもったコードが含まれている危険性があるためです.JSONP のような形
式を使用する場合には,安全性を確保できる,信頼できる提供者からのみのデータを扱うといった注意が必要です.
jsonpTest.html
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp">
<head>
<title>JSONP の練習</title>
<script type="text/javascript" src="jsonpTest.js"></script>
</head>
<body>
<h1>実行例</h1>
<div id="result"></div>
<script src="./jsonpTest.txt" type="text/javascript"></script>
</body>
</html>
jsonpTest.js
function parseJSON(obj) {
var table = "<table>";
table += "<tr><th>都市名</th><th>人口</th><th>シンボル(木)</th><th>シンボル(花)</th><th>
シンボル(鳥)</th></tr>";
for(var i = 0; i < obj.city.length; i++) {
table += "<tr>";
table += "<td>" + obj.city[i].name + "</td>";
table += "<td>" + obj.city[i].population + "</td>";
table += "<td>" + obj.city[i].symbol.tree + "</td>";
table += "<td>" + obj.city[i].symbol.flower + "</td>";
table += "<td>" + obj.city[i].symbol.bird + "</td>";
table += "</td></tr>";
}
table += "</table>";
document.getElementById(’result’).innerHTML = table;
}
jsonpTest.txt
2.7 JSONP
421
parseJSON({ "city":
[
{"name":"札幌", "population":1889352, "symbol":
{"tree":"ライラック", "flower":"スズラン", "bird":"カッコウ"}},
{"name":"旭川", "population":354572, "symbol":
{"tree":"ナナカマド", "flower":"ツツジ", "bird":"キレンジャク", "incect":"カンタン"}},
{"name":"函館", "population":284967, "symbol":
{"tree":"イチイ", "flower":"ツツジ", "bird":"ヤマガラ", "fish":"イカ"}}
]
})
この例では,script 要素の src 属性でコールバック関数を記述した JSONP 形式のテキストファイルを読み込んでい
ます.これによって,jsonpTest.html の script 要素が読み込まれた段階で,parseJSON 関数が呼び出され処理が開始
されます
*4 .実行例は図
2.3 と同様になります.また,実際には,その利用の目的などに従い,JavaScript などから
JSONP ファイルを読み込むタイミングを指定することが考えられます.
Web API を利用する際には,script 要素の src 属性にはコールバック関数を記述した JSON 形式のファイル
(JSONP の形式で記述されたファイル)を返す動作をする API の URL を記述します.例えば,以下のように URI の
パラメータに callback オプションが付加された URI です.具体的な指定の仕方は,提供する Web API の仕様に従っ
て下さい.
<script type="text/javascript" src="http://www.example.com?q=query&callback=getJSON">
*4
従って,parseJSON 関数の中で id 属性が result の要素を検索していますが,この要素が script 要素よりも下に記述されている場合には処
理が行われていないため見つかりません.よって,この JavaScript は動作しません.
第 15 回 演習課題
目標
Web API を利用した Web サイトの構築法の一部を習得します.
特に,REST 方式によるデータ取得の方法と JSONP によるコールバック関数の使用を理解します.また,実装
には JavaScript や XML 言語を使用しますので,過去の講義資料を参照しながら課題に取り組んで下さい.
※ 発展は任意課題とします.余裕のある方は挑戦してみて下さい.
課題 1 Web API の利用: REST, JSONP によるデータ取得
1–1
都市の名前から,画像を検索する Web アプリケーションを作成します.必要なものは,HTML ファイル,JavaScript
のスクリプト,JSON によるデータベースです.以下にひな形を示しますので,それぞれのファイルを作成して下さい.
作成したファイルのうち,mashup.js を一部変更し,都市名をクリックすると写真の一覧が表示されるように変更し
て下さい.
cities.txt
loadCities({ "city":
[
{"name":"札幌","population":1889352,"symbol":
{"tree":"ライラック","flower":"スズラン","bird":"カッコウ"}},
{"name":"旭川","population":354572,"symbol":
{"tree":"ナナカマド","flower":"ツツジ","bird":"キレンジャク","incect":"カンタン"}},
{"name":"函館","population":284967,"symbol":
{"tree":"イチイ","flower":"ツツジ","bird":"ヤマガラ","fish":"イカ"}},
{"name":"釧路","population":186962,"symbol":
{"tree":"ハシドイ","flower":"キンレンカ","bird":""}},
{"name":"帯広","population":168608,"symbol":
{"tree":"シラカバ","flower":"クロユリ","bird":"ヒバリ"}},
{"name":"苫小牧","population":173775,"symbol":
{"tree":"ナナカマド","flower":"ハスカップ, ハナショウブ","bird":"ハクチョウ"}},
]
})
15practice.html
<?Xml Version="1.0" encoding="UTF-8" standalone="no"?>
423
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp">
<head>
<title>マッシュアップサイトの構築</title>
<script type="text/javascript" src="mashup.js"></script>
<style type="text/css">
#container{ width: 99%; }
#pictures{ width: 58%;}
#hotels{ width: 38%; float: right; }
</style>
</head>
<body>
<h1>実行例</h1>
<h2>XML の読み込み</h2>
<div id="cities"></div>
<script src="./cities.txt" type="text/javascript"></script>
<div id="hotels">
<h2>ホテル情報の読み込み</h2>
</div>
<div id="pictures">
<h2>画像の読み込み</h2>
</div>
</body>
</html>
15practice.html
function getResult(query) {
req_flickr(query);
req_rakuten(query);
}
function loadCities(obj) {
var table = "<table>";
table += "<tr><th>都市名</th><th>人口</th><th>シンボル(木)</th><th>シンボル(花)</th><th>シ
ンボル(鳥)</th></tr>";
第2章
424
第 15 回 演習課題
for(var i = 0; i < obj.city.length; i++) {
table += "<tr>";
table += "<td><a href=’#’ onclick=’javascript:getResult(this.firstChild.nodeValue);’>"
+ obj.city[i].name + "</a></td>";
table += "<td>" + obj.city[i].population + "</td>";
table += "<td>" + obj.city[i].symbol.tree + "</td>";
table += "<td>" + obj.city[i].symbol.flower + "</td>";
table += "<td>" + obj.city[i].symbol.bird + "</td>";
table += "</td></tr>";
}
table += "</table>";
document.getElementById(’cities’).innerHTML = table;
}
function req_flickr(query) {
var rest = ’http://www.flickr.com/services/rest/?’;
var apikey = ’api_key=’ + ’15597be1e90b63a4f71e1961cfecc90b’;
var method = ’method=’ + ’flickr.photos.search’;
var num = ’per_page=’ + ’10’;
var format = ’format=’ + ’json’;
var query = ’text=’ + ’ 旅 ’ + query;
var callback = ’jasoncallback=’ + ’jasonFlickrApi’;
query = rest + apikey + ’&’ + method + ’&’ + format + ’&’ + query + ’&’ + callback;
// ここに,script 要素とその type 属性,src 属性を生成するコードを記述する.
}
function jsonFlickrApi(data) {
var list = data.photos.photo;
var flickr = document.getElementById(’pictures’);
for(var i = 0; i < list.length; i++) {
var photo = list[i];
var anchar = document.createElement(’a’);
var image = document.createElement(’img’);
anchar.href = ’http://www.flickr.com/photos/’ + photo.owner + ’/’ + photo.id + ’/’;
image.src = ’http://static.flickr.com/’ + photo.server + ’/’ +
photo.id + ’_’ + photo.secret + ’_s.jpg’;
image.style.border = ’solid 1px gray’;
image.style.margin = ’1px’;
425
image.style.padding = ’1px’;
anchar.appendChild(image);
flickr.appendChild(anchar);
}
}
function req_rakuten(query) {
return 0;
}
発展
宿 泊 施 設 の 情 報 を 右 側 の カ ラ ム に 表 示 さ せ て み ま し ょ う .http://webservice.rakuten.co.jp/api/
simplehotelsearch/ の API の仕様を参考にして下さい.JSONP によるコールバック関数が使用できます.
mashup.js の req rakuten 関数に REST 形式の URI を作成し,script 要素に JSON のデータを読み込む処理を,ま
た,コールバック関数を新たに作成し HTML を書き出す処理を行う関数を記述して下さい.
参考文献
[1] RSS Advisory Board, RSS 2.0 Specification (varsion 2.0.11), http://www.rssboard.org/rss-specification
[2] W3C Recommendation 10 February 2004, RDF/XML Syntax Specification (Revised), http://www.w3.org/
TR/REC-rdf-syntax/
[3] Network Working Group, RFC 4287 – The Atom Syndication Format, http://www.ietf.org/rfc/rfc4287.
txt
[4] Network Working Group, RFC 5023 – The Atom Publishing Protocol, http://www.ietf.org/rfc/rfc5023.
txt
[5] Network Working Group, The application/json Media Type for JavaScript Object Notation (JSON), http:
//www.ietf.org/rfc/rfc4627.txt,
[6] Dave Winer, XML–RPC Specification, http://www.xmlrpc.com/spec
この著作物は,「クリエイティブ・コモンズ・ライセンス 表示 2.1 日本」により,公立はこだて未来大学から利用許
諾されています.
詳しい利用許諾条項は,http://creativecommons.org/licenses/by/2.1/jp/legalcode をご覧下さい.