ホーム » スタッフ » 斉藤徹 (ページ 103)

斉藤徹」カテゴリーアーカイブ

2025年6月
1234567
891011121314
15161718192021
22232425262728
2930  

検索・リンク

Debianのapache2の設定方法

学生が、Raspberry-PiでCGIを使いたいらしいけど、設定の方法がDebianは一癖あるので、 説明資料を記述。

Debianの原則

Debianでは、基本的な設定ファイルは極力自分で触らない主義。

apache2 も同様で、便利なモジュールも設定ファイルは、必要なものは モジュール毎にインストール時に読み込ませて、触らない主義。

このための設定があって、 CGIとかPHPといったものは、モジュールで管理。

DebianのApache2設定ファイルの考え方

一般的なApacheでは、設定は、/etc/apache2/apache2.conf とか、 /etc/apache2/httpd.conf に記述する。 しかし、いくつものモジュールを使うと、これらの設定ファイルが、 巨大で理解困難になってしまう。

このためDebianのapache2 では、/etc/apache2/*-enabled で対応する。 /etc/apache2/apache2.conf には、以下のような行が書いてあり、 *-enabled配下の設定ファイルをすべて読み込んで起動する。

(( /etc/apache2/apache2.confの一部 ))
 IncludeOptional mods-enabled/*.load
 IncludeOptional mods-enabled/*.conf
 IncludeOptional conf-enabled/*.conf
 IncludeOptional site-enabled/*.conf

/etc/apache2/mods-enabled (mods-available)

  1. 必要なモジュールをインストールすると、 設定ファイルは /etc/apache2/mods-available に書き込まれる。
    (モジュール名.load モジュール名.conf)
      使えるモジュールは、以下のコマンドを使えば、一覧が見れる。
      $ aptitude search libapache2-mod
      インストールしたいモジュールが見つかったら
      $ sudo aptitude install libapache2-mod-モジュール
    
  2. 本当に使いたいモジュールは、以下のコマンドを実行。
      $ sudo /usr/sbin/a2enmod モジュール名
      /etc/apache2/mods-enabled に、mods-available への
      シンボリックリンクを作ってくれる。
    

    使いたくなくなったら、

      $ sudo /usr/sbin/a2dismod モジュール名
    
  3. a2enmodなどを実行したら、以下のコマンドで apache2を再起動
      $ sudo /etc/init.d/apache2 restart
    

    基本原則 /etc/apache2/mods-enabled の配下の設定ファイルは触らない。 どうしても設定ファイルを変更したい場合は、conf-enabled , site-enabled で設定。

/etc/apache2/sites-enabled (sites-available)

  1. apache2では、1台のコンピュータで複数のwebサイトを構築できる。 バーチャルホストの設定は1つのホスト毎に、sites-available の *.conf に記述。 ホスト毎の細かい設定は、この中に記述する。
  2. そのホストを使えるようにしたかったら、以下のコマンド。
      $ sudo /usr/sbin/a2ensite ホスト
      /etc/apache2/site-enabled に、site-available への
      シンボリックリンクを作ってくれる。
    

    ホストを使えないようにする。

      $sudo /usr/sbin/a2dissite ホスト
    
  3. a2ensite を実行したら、"/etc/init.d/apache2 restart"

/etc/apache2/conf-enabled (cont-available)

  1. site-* では、各ホスト毎の設定を書くけど、すべての仮想ホストに共通な 設定は、conf-enabled / conf-available を使う。
  2. 設定を /etc/apache2/conf-available の中に、設定名.conf で記述し、 以下のコマンドで有効にする。
      $ sudo /usr/sbin/a2enconf 設定名
      $ sudo /usr/sbin/a2disconf 設定名
    

(例)

CGIを使いたい (CGIは基本モジュールなのでlibapache2-mod-cgi などはしなくていい)

 $ sudo /usr/sbin/a2enmod cgi  # cgiモジュールの有効化
 $ sudo /etc/init.d/apache2 restart

PHP5を使いたい

 $ sudo aptitude install php5   # PHP5をインストール
 $ sudo aptitude install libapache2-mods-php5
                           # apache2のphp5モジュールをインストール
 $ sudo /usr/sbin/a2enmod php5  # php5モジュールの有効化
 $ sudo /etc/init.d/apache2 restart  # apache2 の再起動

ページは各ユーザの /home/user/public_html/ 配下に作らせたい。

 $ sudo /usr/sbin/a2enmod userdir

SSLのhttps://を使いたい

 $ sudo vi /etc/apache2/site-available/default-ssl.conf
 $ sudo /usr/sbin/a2ensite default-ssl
 $ sudo /etc/init.d/apache2 restart

SQLの最初

関係データベースの導入説明が終わったので、実際のSQLの説明。

create user

データベースを扱う際の create user 文は、DDL(Data Definition Language)で行う。

CREATE USER ユーザ名
IDENTIFIED BY "パスワード"

grant

テーブルに対する権限を与える命令。

GRANT システム権限 TO ユーザ名
   データベースシステム全体に関わる権限をユーザに与える。
   (例) GRANT execute ON admin.my_package TO saitoh
GRANT オブジェクト権限 ON オブジェクト名 TO ユーザ名
   作られたテーブルなどのオブジェクトに関する権限を与える。
   (例) GRANT select,update,delete,insert ON admin.my_table TO saitoh
REVOKE オブジェクト権限 ON オブジェクト名 TO ユーザ名
   オブジェクトへの権限を剥奪する。

create table

実際にテーブルを宣言する命令。構造体の宣言みたいなものと捉えると分かりやすい。

CREATE TABLE テーブル名
   ( 要素名1  型 , 要素名2 型 ... ) ;
   PRIMARY KEY 制約
   型の後ろに"PRIMARY KEY"をつける、
   もしくは、要素列の最後に、PRIMARY KEY(要素名,...)をつける。
   これによりKEYに指定した物は、重複した値を格納できない。

型には、以下の様なものがある。(Oracle)
   CHAR( size)  : 固定長文字列 / NCHAR国際文字
   VARCHAR2( size ) : 可変長文字列 / NVARCHAR2...
   NUMBER(桁) :指定 桁数を扱える数
   BINARY_FLOAT / BINARY_DOUBLE : 浮動小数点(float / double)
   DATE : 日付(年月日時分秒)
   SQLiteでの型
   INTEGER : int型
   REAL : float/double型
   TEXT : 可変長文字列型
   BLOB : 大きいバイナリデータ

DROP TABLE テーブル名
   テーブルを削除する命令

insert,update,delete

指定したテーブルに新しいデータを登録,更新,削除する命令

INSERT INTO テーブル名 ( 要素名,... ) VALUES ( 値,... ) ;
   要素に対応する値をそれぞれ代入する。
UPDATE テーブル名 SET 要素名=値 WHERE 条件
   指定した条件の列の値を更新する。
DELETE FROM テーブル名 WHERE 条件
   指定した条件の列を削除する。

select

データ問い合わせは、select文を用いる、 select文は、(1)必要なカラムを指定する射影、(2)指定条件にあうレコードを指定する選択、 (3)複数のテーブルの直積を処理する結合から構成される。

SELECT 射影 FROM 結合 WHERE 選択
   (例) SELECT S.業者番号 FROM S WHERE S.優良度 > 30 ;

2分木の生成

先週に2分木に対する再帰などを交えたプログラムの説明をしたので、 今週は木の生成について、AVL木などを交えて説明。 後半は、情報処理センターで演習。

#include <stdio.h>
#include <stdlib.h>
// 2分木の宣言
struct Tree {
   int data ;
   struct Tree* left ;
   struct Tree* right ;
} ;
// 木の根
struct Tree* top = NULL ;
// 木のノードを構築する補助関数
struct Tree* tcons( int x , struct Tree* l , struct Tree* r ) {
   struct Tree* n ;
   n = (struct Tree*)malloc( sizeof( struct Tree ) ) ;
   if ( n != NULL ) {
      n->data = x ;
      n->left = l ;
      n->right = r ;
   }
   return n ;
}
// 木を表示する補助関数。枝の左右がわかる様に...
void print( struct Tree* p ) {
   if ( p == NULL ) {
      printf( "x" ) ;
   } else {
      printf( "(" ) ;
      print( p->left ) ;
      printf( " %d " , p->data ) ;
      print( p->right ) ;
   printf( ")" ) ;
   }
}
// 木に1件のデータを追加する補助関数
void entry( int x ) {
   struct Tree** ppt = &top ;

   while( (*ppt) != NULL ) {
      if ( (*ppt)->data == x )
         break ;
      else if ( (*ppt)->data > x )
         ppt = &( (*ppt)->left ) ;
      else
         ppt = &( (*ppt)->right ) ;
   }
   if ( *ppt == NULL )
      (*ppt) = tcons( x , NULL , NULL ) ;
   }
int main() {
   entry( 51 ) ;
   entry( 26 ) ;
   entry( 76 ) ;
   entry( 60 ) ;
   print( top ) ;
   // ((x 26 x) 51 ((x 60 x) 76 x))

   top = NULL ;
   entry( 26 ) ;
   entry( 51 ) ;
   entry( 60 ) ;
   entry( 76 ) ;
   print( top ) ;
   // (x 26 (x 51 (x 60 (x 76 x))))
}

歯みがきロボコン2015

例年、ロボコン車体の写真ばかりですが、知り合いの方が私の解説風景を撮ってくれました。(^_^)

福井テレビの看板アナの坂本さんは、何度か歯みがきロボコンでお隣でしたが、私の素人解説の中途半端な話しを盛り上げる話でつないでいて、頭の回転が速くないとできない仕事で、流石……です。

1510041857_530x530.jpg

歯みがきロボコンの車体

明日の歯みがきロボコンに参加予定の車体、最終調整かな。

1510031933_640x640.JPG

2EI実験ガイダンスでコンピュータ将棋など…

電子情報工学科の2年の後期実験では、 私の担当はゲームのプログラミング。 といっても、シューティングなどではなく、オセロ・五目並べ・ポーカーの 勝敗判定や役判定などを行うプログラムを通して、 プログラミングの大変さを味わってもらう。

プログラミングは、論理的思考能力のたわものではあるが、 ある程度は「プログラムを自分で作って間違った経験の差」が、 プログラム能力になると思う。そこで、タイミングやアニメ表示の プログラミングではなく、ゲーム盤の勝敗判定のプログラミングを通して 経験を深めてもらうのが目的。

簡単なゲームプログラムの作成

実験の配布資料を上記に示す。 実験では、2人が交互にオセロの手を打ち、ルール判定や勝敗を行うプログラムを作成するのが目標。

プログラミング技量に応じたプログラム作成をしてもらうために、 2週の最初にどの機能までを実装するのか、実装する機能目標の表をチェックし、 1週目さいご、2週目さいごに進捗を自分で確認する。 2週の最後には、隣の人と本当に動くのかチェックをしてもらう。

コンピュータ.vs.人間による対戦

実験ガイダンスは簡単にしておいて、プログラミングの興味を持ってもらうために、 チェスなどのコンピュータ対戦の雑談。

コンピュータは論理的思考の処理(左脳)が得意で、現状ではコンピュータの速度にはかなわない。 しかし、人間のイメージで捉える能力(右脳)ではまだまだ劣っている。 こういった領域でもコンピュータが活躍するための研究なども進められている。

プログラマーに見て欲しい映画

構造体の参照渡しとオブジェクト指向

一緒に、来週のプログラミング応用の資料書いちゃえ。

構造体の参照渡し

構造体のデータを関数の呼び出しで記述する場合には、参照渡しを利用する。

struct Person {
   char name[ 20 ] ;
   int  age ;
} ;
void print( struct Person* p ) {
   printf( "%s %d¥n" , p->name , p->age ) ;
}
void main() {
   struct Person saitoh ;
   strcpy( saitoh.name , "t-saitoh" ) ;
   saitoh.age = 50 ;
   print( &saitoh ) ;
}

このようなプログラムの書き方をすると、「データ saitoh に、print() せよ…」 といった処理を記述したようになる。 これを発展して、データ saitoh に、print という命令をするイメージにも見える。

この考え方を、そのままプログラムに反映させ、Personというデータは、 名前と年齢、データを表示するprintは…といったように、 データ構造と、そのデータ構造への処理をペアで記述すると分かりやすい。

オブジェクト指向の導入

オブジェクト指向では、データ構造とその命令を合わせたものをクラス(class)と呼ぶ。 また、データ(class)への命令は、メソッド(method)と呼ぶ。

class Person {
private:
   char name[ 20 ] ;
   int  age ;
public:
   Person( char s[] , int a ) {
      strcpy( name , s ) ;
      age = a ;
   }
   int scan() {
      return scan( "%s %d" , name , &age ) ;
   }
   void print() {
      printf( "%s %d¥n" , name , age ) ;
   }
} ;
void main() {
   Person saitoh( "t-saitoh" , 50 ) ;
   saitoh.print() ;
   Person table[ 50 ] ;
   for( int i = 0 ; i < 50 ; i++ ) {
      if ( table[ i ].scan() != 2 )
         break ;
      table[ i ].print() ;
   }
}

構造体とオブジェクト指向

プログラミング応用の後期では、構造体とコンピュータグラフィックスの基礎を扱う予定。 CGの基礎でも、X座標,Y座標…をひと塊の構造体で表現という意味では、構造体の延長として授業を進める予定。

構造体

上記資料を元に説明。 最初に構造体が無かったら、名前・国語・算数・理科の1クラス分のデータをどう表現しますか?

// まずは基本の宣言
char name[ 50 ][ 20 ] ;
int  kokugo[ 50 ] ;
int  sansu[ 50 ] ;
int  rika[ 50 ] ;
// もしクラスが最初20人だったら、20→50に変更する際に、
// 文字列長の20も書きなおしちゃうかも。
// 50とか20とかマジックナンバーは使わないほうがいい。
#define SIZE 50
#define LEN 20
char name[ SIZE ][ LEN ] ;
int  kokugo[ SIZE ] ;
:
// 2クラス分のデータ(例えばEI科とE科)を保存したかったら?
// case-1(配列2倍にしちゃえ)
char name[ 100 ][ 20 ] ;  // どこからがEI科?
int  kokugo[ 100 ] ;
:
// case-2(2次元配列にしちゃえ)
char name[ 2 ][ 50 ][ 20 ] ; // 0,1どっちがEI科?
int  kokugo[ 2 ][ 50 ] ;
:
// case-3(目的に応じた名前の変数を作っちゃえ)
char ei_name[ 50 ][ 20 ] ; // EI科は一目瞭然
int  ei_kokugo[ 50 ] ;     // だけど変数名が違うから
:                      // 処理を2度書き
char ee_name[ 50 ][ 20 ] ;
int  ee_kokugo[ 50 ] ;
:

このような問題に対応するために構造体を用いる。

struct Person {  // Personが構造体名(タグ名)
   char name[ 20 ] ;
   int  kokugo ;
   int  sansu ;
   int  rika ;
} ;
struct Person saitoh ;
struct Person ei[ 50 ] , ee[ 40 ] ;
strcpy( saitoh.name , "t-saitoh" ) ;
saitoh.kokugo = 100 ;
ei[ 0 ].sansu = 80 ;
ee[ 1 ].rika = 75 ;

授業では、構造体の初期化、入れ子の話をする。詳細は配布資料参照。

途中で、C言語の歴史として、unix開発時に、BCPL→B言語→C言語(K&R)→ANSI-C→…C++→D言語 といった雑談も説明。

入れ子の話では、 for(…) { for(…) { } } のような、処理の入れ子(処理の構造化)と、 構造体の入れ子(データの構造化)の話から、構造化プログラミング(structured programming)といった話も紹介する。

データベース・ガイダンス

今日が後期の選択科目「データベース」の第一回目ということで、 シラバス配布&ガイダンスをしてからぁ〜のぉ〜、概要説明。

インターネットの情報量

インターネット上の情報量の話として、2010年度に281EB(エクサバイト) 参考:kMGTPEZYで、今日改めて探したら、2013年度で、1.2 ZB(ゼタバイト) という情報があった。ムーアの法則2年で2倍の概算にも、それなりに近い。 今年2015年であれば、約2年で、2 ZBにはなっているかな。

そして、これらの情報をGoogleなどで探す場合、すぐにそれなりに情報を みつけてくれる。これらは、どの様に実装されているのか?

Webシステムとデータベース

まず、指定したキーワードの情報を見つけてくれるものとして、 検索システムがあるが、このデータベースはどのようにできているのか?

Web創成期の頃であれば、Yahooがディレクトリ型の検索システムを構築 してくれている。(ページ作者がキーワードとURLを登録する方式) しかし、ディレクトリ型では、自分が考えたキーワードではページが 見つからないことが多い。

そこで、GoogleはWebロボット(クローラー)による検索システムを構築した。 Webロボットは、定期的に登録されているURLをアクセスし、 そのページ内の単語を分割しURLと共にデータベースに追加する。 さらに、ページ内にURLが含まれていると、そのURLの先で、 同様の処理を再帰的に繰り返す。

これにより、巨大なデータベースが構築されているが、これを少ない コンピュータで実現すると、処理速度が足りず、3秒ルール/5秒ルール (Web利用者は次のページ表示が3秒を越えると、次に閲覧してくれない) これを処理するには負荷分散が重要となる。

一般的に、Webシステムを構築する場合には、 1段:Webサーバ、2段:動的ページ言語、3段:データベースとなる場合も 多い。この場合、OS=Linux,Web=Apache,DB=MySQL,言語=PHPの組合せで、 LAMP構成とする場合も多い。

一方で、大量のデータを処理するDBでは、 フロントエンドDB,スレーブDB,マスタDBの3段スキーマ構成となることも多い。

データベースシステム

データベースには、ファイル内のデータを扱うためのライブラリの、 BerkleyDBといった場合もあるが、複雑なデータの問い合わせを実現する 場合には、リレーショナル・データベース(RDB)を用いる。 RDBでは、データをすべて表形式であらわし、SQLというデータベース 問い合わせ言語でデータを扱う。 また、問い合わせは、ネットワーク越しに実現可能であり、こういった RDBで有名なものとして、Oracle , MySQL , PostgreSQL などがある。 単一コンピュータ内でのデータベースには、SQLite などがある。

しかし、RDBでは複雑なデータの問い合わせはできるが、 大量のデータ処理のシステムでは、フロントエンドDB,スレーブDB,マスタDB の同期が問題となる。この複雑さへの対応として、最近は NoSQL が 注目されている。

データベースが無かったら

これらのデータベースが無かったら、どのようなプログラムを作る 必要があるのか?

情報構造論ではC言語でデータベースっぽいことをしていたが、 大量のデータを永続的に扱うのであれば、ファイルへのデータの読み書き 修正ができるプログラムが必要となる。

こういったデータをファイルで扱う場合には、1件のデータ長が途中で 変化すると、N番目のデータは何処?といった現象が発生する。 このため、簡単なデータベースを自力で書くには、1件あたりのデータ量を 固定し、lseek() , fwrite() , fread() などの 関数でランダムアクセスのプログラムを書く必要がある。

また、データの読み書きが複数同時発生する場合には、排他処理も 重要となる。例えば、銀行での預け金10万の時、3万入金と、2万引落としが 同時に発生したらどうなるか? 最悪なケースでは、 (1)入金処理で、残金10万を読み出し、 (2)引落し処理で、残金10万を読み出し、 (3)入金処理で10万に+3万で、13万円を書き込み、 (4)引落し処理で、残金10万-2万で、8万円を書き込み。 で、本来なら11万になるべき結果が、8万になるかもしれない。

さらに、コンピュータといってもハードディスクの故障などは発生する。 障害が発生してもデータの一貫性を保つためには、バックアップや 障害対応が重要となる。

Raspberry-Piのカメラをサーボで制御したい

I2Cを認識させる

(( i2cを認識させる設定 ))
$ sudo raspi-config
## 8 Advenced Options" -> "A7 I2C" よりI2Cを標準で認識するように設定
## /etc/modprobe.d/raspi-blacklist.confのblacklistがコメントアウト
# blacklist i2c-bcm2708
## /etc/modules に以下の行が追加される
i2c-dev
i2c-bcm2708
$ sudo reboot
(( i2cが認識されたか確認 ))
$ sudo aptitude install i2c-tools
$ ls /dev/i2c-*
/dev/i2c-1
## Raspberry-Pi によっては、/dev/i2c-0 となるかも。
$ sudo i2cdetect -y 1
0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
## まだi2c機器を何も繋げていない...
(( i2cをユーザで使えるように ))
$ ls /dev/i2c-1
crw-rw---T 1 root i2c 89, 1  9月 10 09:02 /dev/i2c-1
## i2cを使うためのグループにユーザpiを加える。
$ sudo adduser pi i2c

カメラ制御で使うもの

システム

最新の投稿(電子情報)

最近の投稿(斉藤 徹)

アーカイブ

カテゴリー