Archive for 1月, 2009
□IDEとSCSIを混在させてSCSIブートするとき
by admin on 1月.08, 2009, under MEMO
IDE-HDD と SCSI-HDD を混在させていて、かつ SCSI-HDD からブート
しようとすると /sbin/lilo したときに
> Warning: /dev/sda is not on the first disk
> Added Linux *
というようになって、リブートしてもうまくブートしてくれないこと
がありますが、こんなときには /etc/lilo.conf を下記のように書き
直すとばっちりいけます。
> # LILO configuration file
> # generated by ‘liloconfig’
> #
> # Start LILO global section
> disk = /dev/sda ★
> bios = 0×80 ★
> #
> boot = /dev/sda
> #boot = /dev/hda
> compact # faster, but won’t work on all systems.
:
:
この「disk = デバイス名」でデバイスを特定したあとで「bios =」
という部分、システムとして何番目のディスクかを指定しています。
ちなみに 0×80 はシステムの第1ディスクになります。
これで SCSI-HDD で起動させて IDE-HDD をデータ領域とする、とか
が簡単に出来ます。
□C言語ソースをPerlモジュールにする
by admin on 1月.08, 2009, under MEMO
参考URL:
http://www.rainylain.jp/vc/perl_module.htm
Perlは文字列操作にはとてもすばらしい機能を発揮しますが、どうしても
C言語で出来た外部関数とリンクしたい、という時になったときにCとPerl
とのやり取りをしてくれるPerlモジュールを作成すると結構楽です。
今回はdracdが動いているホストに指定したIPアドレスを登録する、という
モジュールをつくる。名づけて「drac4perl」かな?
もともとdracのソースには「testing.c」という、dracのデータベースに
指定したIPアドレスを入れてくれる簡単なクライアントソースがついている
ので、これをPerlモジュール化してしまうと楽ですね。(あー手抜きだ!)
testing.c をみてみると、ポイントとなるところは
>???????? host = argv[1];
>???????? ip = inet_addr(argv[2]);
>???????? rc = dracauth(host, ip, &err);
ここだけ。dracauthで、引数で渡されたdracdが動いているhostに対してip
を登録しているだけ。これを導入したPerlモジュールを作ればよい。
まずはモジュール名を決めましょう。参考URLのとおりに h2xs で骨組みを
つくります。
> # h2xs -A -n Drac4Perl
> Defaulting to backwards compatibility with perl 5.8.4
> If you intend this module to be compatible with earlier perl versions, please
> specify a minimum perl version with the -b option.
>
> Writing Drac4Perl/ppport.h
> Writing Drac4Perl/lib/Drac4Perl.pm
> Writing Drac4Perl/Drac4Perl.xs
> Writing Drac4Perl/Makefile.PL
> Writing Drac4Perl/README
> Writing Drac4Perl/t/Drac4Perl.t
> Writing Drac4Perl/Changes
> Writing Drac4Perl/MANIFEST
で、できた Drac4Perl.xsを下記のようにする。
> #include “EXTERN.h”
> #include “perl.h”
> #include “XSUB.h”
>
> #include “ppport.h”
>
> // ——————————–
> // C言語ソースコード(Perlに影響しない部分)
> #include <stdio.h>
> #include <sys/types.h>
> #include <netinet/in.h>
> #include <arpa/inet.h>
>
> drac_in(host, ipaddr)
>???????? char *host;???? // dracd が動いているホストのIPアドレス
>???????? char *ipaddr;?? // dracd に登録したいユーザーのIPアドレス
> {
>???????? int result;???????????? // 処理結果
>???????? unsigned long ip;?????? // IPアドレス(long int)
>???????? char *err;????????????? // エラー理由(今回は無視)
>
>???????? // IPアドレスを変換
>???????? ip = inet_addr(ipaddr);
>???????? // dracd に登録&結果を返す
>???????? return dracauth(host, ip, &err);
> }
>
>
> // ——————————–
> // Perlモジュール宣言
> MODULE = Drac4Perl????????????? PACKAGE = Drac4Perl
>
> int
> auth(server, client)
>???? char *server;
>???? char *client;
>
>???? CODE:
>???????? RETVAL = drac_in(server, client);
>
>???? OUTPUT:
>???????? RETVAL
で、Makefile.PL のライブラリを指定する部分に「-ldrac」を追加して
> use 5.008004;
> use ExtUtils::MakeMaker;
> # See lib/ExtUtils/MakeMaker.pm for details of how to influence
> # the contents of the Makefile that is written.
> WriteMakefile(
>???? NAME????????????? => ‘Drac4Perl’,
>???? VERSION_FROM????? => ‘lib/Drac4Perl.pm’, # finds $VERSION
>???? PREREQ_PM???????? => {}, # e.g., Module::Name => 1.1
>???? ($] >= 5.005 ????? ## Add these new keywords supported since 5.005
>?????? (ABSTRACT_FROM? => ‘lib/Drac4Perl.pm’, # retrieve abstract from module
>??????? AUTHOR???????? => ‘A. U. Thor <root@linet.gr.jp>’) : ()),
>???? LIBS????????????? => ['-ldrac'], # e.g., ‘-lm’
>???? DEFINE??????????? => ”, # e.g., ‘-DHAVE_SOMETHING’
>???? INC?????????????? => ‘-I.’, # e.g., ‘-I. -I/usr/include/other’
>???????? # Un-comment this if you add C files to link with later:
>???? # OBJECT??????????? => ‘$(O_FILES)’, # link all the C files too
> );
perl Makefile.PL
make
make install
すればOK。
あとは下記のようなテストプログラム(dractest.pl)で試してみればよい。
> #!/usr/bin/perl
> #
> # Drac4Perlモジュールのテスト
> #
> use Drac4Perl;
>
> $RESULT =? Drac4Perl::auth(“localhost”, “192.168.100.3″);
>
> system(“/usr/bin/db_dump -p /etc/postfix/dracd.db”);
>
> exit 0;
として、これを実行すれば、drac がちゃんとインストールされていれば
> # ./dractest.pl
> VERSION=3
> format=print
> type=hash
> h_nelem=3
> db_pagesize=512
> HEADER=END
>? 192.168.100.3
>? 1143172343
> DATA=END
と、こんな風に登録されればOK!
□溜め込みメールの掃除ツール(IMAP版)
by admin on 1月.08, 2009, under MEMO
IMAP版の場合には、Maildir の中を全てスキャンすればいいので、POP3
の時よりも少しは簡単かも!?
最初は Email::Folder や Email::Delete::Maildir モジュールを使おう
かと思ったけど、今ひとつ使い勝手が悪いので、これらのモジュールを
参考にしつつ
・指定したフォルダからファイル一覧を取得
・メールファイルとして解析して、メール送信日時を取得
・送信日が古く、かつメールファイル生成日も古いなら削除
という処理にする。
> #!/usr/bin/perl -w
>
> use File::Find::Rule;
> use Email::Simple;
> use HTTP::Date;
>
> # 検査対象日時を算出(90日以上前)
> $old_day = 90;
> $oldlimit = time – ($old_day * 24 * 60 * 60); # day * hour * min * sec
>
> print “———-\n”;
>
> # メールファイルの一覧を取得($oldlimit より前に生成されたメールファイルが対象)
> my @mail_files = File::Find::Rule->file()
> ->mtime(“< $oldlimit")
> ->in(“/home/hogehoge/Maildir”);
>
> # 対象メールを検査
> foreach $file (@mail_files)
> {
> # メールファイルを開く
> open(FILE, $file);
>
> # メールファイルを構造体に変換
> my $mail = Email::Simple->new(do { local $/; $_ =
>
> # メールの送信日時を取得&変換
> $timestamp = str2time($message->header(“Date”));
>
> # メールの送信日時が削除対象日時より前なら
> if ($timestamp < $oldlimit)
> {
> # 削除する
> unlink $file;
> }
>
> }
>
> exit 0;
たぶんIMAP版の方がPOP3版よりも断然処理速度が速いと思われる。
□溜め込みメールの掃除ツール(POP3版)
by admin on 1月.08, 2009, under MEMO
よくメールボックスにメールを溜め込んでいる人がいます。
初心者でメールの定期的な掃除の仕方(設定)を知らない人や、確信犯
的に掃除をしない人、はたまたいなくなったユーザーのメールボックス
だったりすることもあります。
こういう人たちのメールボックスは往々にして制限サイズ一杯まで溜め
込み、結局メールがあふれて受信できなかったりエラーメールが送信者
に戻ったりします。
管理者としてはこういうメールボックスをいちいち個別に掃除するのは
面倒なので、自動的に一定期間経過したメールを削除するツールを用意
してみました。
とりあえずPerlにメール関連のモジュールが色々あるので、Perlで自動
掃除スクリプトを作ります。とりあえず Mail::Box モジュールをイン
ストールします。
perl -MCPAN -e shell
としてCPANを起動して
install Mail::Box
としてメールボックスモジュールをインストールします。すると色々な
モジュールが必要だよ、という事でひたすらインストールがまってます。
インストールしながら作るスクリプトの動作を考えましょう。
1つ1つメールを見ていってもいいのですが、溜めている人はたいてい
すごいメール数を溜めていますので、できるならとりあえず一覧を取得
した上で、指定した日付以前のメールを、既読/未読などを考慮しなが
ら削除するようにするほうがいいでしょう。
基本的な処理としては
> # モジュールの宣言
> use Mail::Box::Manager;
> #
> # 指定のメールボックスを開く
> my $mgr = Mail::Box::Manager->new;
> my $folder = $mgr->open(folder => “/var/spool/mail/$userid”, access => ‘rw’);
> #
> # 全メールをスキャン
> foreach my $id ($folder->messageIds)
> {
> # ここのメールごとに発信元と送信日時を得る
> $from = $folder->messageId($id)->sender->format;
> $timestamp = $folder->messageId($id)->guessTimestamp;
>
> # 送信日時が指定日時よりも前なら
> if ($timestamp < (time - $oldlimit))
> {
> # 該当メールは削除
> $folder->messageId($id)->delete;
> }
> }
>
> # メールボックスを閉じる(=削除メールを消す)
> $folder->close;
>
> exit;
となります。モジュール様様ですね。
注意しなければならない点は、ユーザーの shell が /dev/null だと
掃除諸々が出来ません。
□PostgreSQL をサーバー/クライアントとして使う(いざ自宅DB)
by admin on 1月.08, 2009, under MEMO
ダイナミックDNSサービス:MyDNS.JP(http://www.MyDNS.JP/)を使用して、
自宅に PostgreSQL のデータベースサーバー(自宅DB)を設置してみます。
目的としては、データは自宅でしっかり管理して、PHP が入っている外部の
WEBサーバー(例えば BiG-NET の)からアクセスができるようにします。
自宅サーバーについては、このメモでガリガリインストしている方には説明
は不要でしょうからはしょって、具体的な PostgreSQL の設定などに限定を
します。
まずは外部からアクセスするユーザーを PostgreSQL に設定します。この時
一緒にパスワードも設定しましょう。DBユーザーを作れるユーザー(笑)に
なって、「test1」というユーザーを追加します。
samba:~$ /usr/local/pgsql/bin/createuser -A -D -P -E test1
Enter password for new user:
Enter it again:
CREATE USER
パスワードを求められるので適当に入れます。createuser のオプションは
–help でみてください。ここではDBの新規作成不可、ユーザー追加不可で
パスワードを暗号化した「test1」というユーザーを追加しました。
つづいて、/usr/local/pgsql/data/pg_hba.conf を編集して、外部の特定の
IPアドレス(普通はPHPがOKなWEBサーバー?)からの接続のみできるように
許可します。ここで特定のデータベースに対して接続できるユーザーを制限
できます。
> # TYPE? DATABASE??? USER??????? IP-ADDRESS??????? IP-MASK?????????? METHOD
>
> local?? all???????? all???????????????????????????????????????????? trust
> # IPv4-style local connections:
> host??? all???????? all???????? 127.0.0.1???????? 255.255.255.255?? trust
> host??? test1?????? test1?????? 192.168.192.0???? 255.255.255.0???? md5
ここでは、「192.168.0.0/24」からなら「db_test1」というデータベース
に対して「test1」というユーザーだけが「md5」による認証で接続が可能
という設定にしました。「md5」ではなくて「crypt」に、という本がほと
んどかと思いますが、それは PostgreSQL の 7.1 までの古いバージョン
向けです。何はともあれ、これで外からアクセスできる準備ができました。
PostgreSQL を普通に起動している場合には、5432 番ポートで受け付ける
筈ですが、最近のバージョンでは普通にインストールしたままだと、外部
からの接続は受け付けないかもしれません。
そんなときには /usr/local/pgsql/data/postgresql.conf を確認して、
ポートの指定などがコメントアウトしていないかどうかを見ます。(★)
:
:
> listen_addresses = ‘*’ (古いVerなら tcpip_socket = on)
> port = 5432
> max_connections = 1000
> superuser_reserved_connections = 20
:
:
また自宅サーバーを iptables 等でフィルタリングしている場合は、外部
からこのポートにアクセスができるようにしないといけません。
/etc/services に 5432番を postgres と書き足してもいいですし、直接
指定でもいいでしょう。
で、実際にアクセスをしてみると…
> hogehoge:~# /usr/local/pgsql/bin/psql -d db_test1 -h 192.168.192.30 -U test1
> Password:
> Welcome to psql 7.3.2, the PostgreSQL interactive terminal.
>
> Type:? \copyright for distribution terms
>??????? \h for help with SQL commands
>??????? \? for help on internal slash commands
>??????? \g or terminate with semicolon to execute query
>??????? \q to quit
>
> db_test1=>
と入れました。んー、何かネットワークしていますねー。
では、PHPがOKなWEBから自宅DBを実際に操作してみましょう。
基本的な操作として、下記の4つの処理を簡単にやってみます。
1.自宅DBに接続
2.テーブル作成
3.データの書き込み
4.データの読み込み
基本的にはデータベースに接続ができればなんでも処理できるはずですので
とにかく1をクリアしましょう。(^^;
1.自宅DBに接続
test_db1.php
−−−−−−−−−−
<HTML>
<BODY>
<?
// データベースへの接続
$DB = pg_connect(“host=192.168.192.30 port=5432 dbname=db_test1 user=test1 password=testtest”);
if (!$DB)
{
??? print “自宅DBへの接続が失敗しました!?<BR>\n”;
??? print “</BODT></HTML>\n”;
??? exit;
}
$dbname = pg_dbname($DB);
print “自宅DB:$dbname へ接続成功です!!<BR>\n”;
?>
</BODY>
</HTML>
−−−−−−−−−−
こんなHTML(PHPスクリプト)を用意しました。
これは「database.mydns.jp」の「5432」番ポートに「test1」で「pass1」
というユーザー名&パスワードで接続し、「db_test1」というデータベース
にアクセスするものです。
このHTMLにWEBからアクセスをしてうまくいけば
> 自宅DB:db_test1 へ接続成功です!!
となるはずです。
2.テーブル作成
続いてテーブルを作成するSQL文を追加してみます。
test_db2.php
−−−−−−−−−−
:
:
print “自宅DB:$dbname へ接続中です!!<BR>\n”;
// テーブルの生成
$SQL = “SELECT relname from pg_class where relname = ‘test1_tbl’;”;
$RESULT = pg_query($DB, $SQL);
$ROW = pg_num_rows($RESULT);
if ($ROW)
{
??? print “test1_tbl は既に存在しています!?<BR>\n”;
}
else
{
??? $SQL = “CREATE TABLE test1_tbl (
??? name TEXT,
??? age INTEGER);
??? “;
??? $RESULT = pg_query($DB, $SQL);
??? print “test1_tbl はありませんので作りました!!<BR>\n”;
}
?>
</BODY>
</HTML>
−−−−−−−−−−
こんなふうに追加しました。
これは「test1_tbl」というテーブルを追加しろという命令ですね。
別途コンソールから psql でログインしておいてテーブルの有無を
確認すると
> db_test1=> \d
> No relations found.
というようにない状態で、このPHPスクリプトにアクセスをして
うまくいくと
> 自宅DB:db_test1 へ接続中です!!
> test1_tbl はありませんので作りました!!
という表示になります。psql で確認しても
> db_test1=> \d
>????????? List of relations
>? Schema |?? Name??? | Type? | Owner
> ——–+———–+——-+——-
>? public | test1_tbl | table | test1
> (1 row)
>
> db_test1=>
とできていました。
ちなみに、もし同名のテーブルが存在していると
> 自宅DB:db_test1 へ接続中です!!
> test1_tbl は既に存在しています!?
というようにエラー表示が出てしまいます。
3.データの書き込み
4.データの読み込み
書き込みと読み込みは一度にやってしまいましょう。
test_db3.php
−−−−−−−−−−
:
:
print “test1_tbl はありませんので作りました!!<BR>\n”;
}
// データの書き込み
$SQL = “INSERT INTO test1_tbl VALUES (
???????? ‘日本太郎’, 25);\n
?????? “;
$SQL .= “INSERT INTO test1_tbl VALUES (
???????? ‘日本花子’, 22);
?????? “;
$RESULT = pg_query($DB, $SQL);
// データの読み出し
$SQL = “SELECT * FROM test1_tbl;
?????? “;
$RESULT = pg_query($DB, $SQL);
$ROW = pg_num_rows($RESULT);
if ($ROW)
{
??? print “$ROW 件のデータがありました!!<BR>\n”;
??? for ($r = 0; $r < $ROW; $r ++)
??? {
??????? $ARRAY = pg_fetch_array($RESULT,$r);
??????? print “\t$ARRAY[name]\t$ARRAY[age]<BR>\n”;
??? }
}
else
{
??? print “データがありませんでした!?<BR>\n”;
}
?>
</BODY>
</HTML>
−−−−−−−−−−
こんなふうに追加しました。
うまくいくと
> 自宅DB:db_test1 へ接続中です!!
> test1_tbl は既に存在しています!?
> 2 件のデータがありました!!
> 日本太郎 25
> 日本花子 22
というようになります。
リロードするとどんどん追加していくので件数も増えていきます。(^^;
自宅サーバーの方のDBで一応、直接確認しておくと
> db_test1=> select * from test1_tbl;
>????? name | age
> ———-+—–
> 日本太郎? | 25
> 日本花子? | 22
> (2 rows)
>
> db_test1=>
というわけで、自宅DBがしっかり動いていることが確認できました。
pg_hba.conf でアクセス元を制限しているのでこれだけでも自宅DBなら
問題ないと思いますが、さらにセキュリティを気にする場合は、テーブル
へのアクセス権などを設定してください。
5.おまけ
さて、外部からのアクセスをパスワード付きとしただけならまだしも自鯖
ないからのアクセスもパスワードを必須とした場合、pg_dump でのバック
アップの仕方に困ってしまうかと思います。(なぜなら pg_dump は通常の
psql でDBにアクセスするのと同じ事になるので、当然パスワードを求め
られる)
そんな時は、ちと危なっかしいですがIDとパスワードを書いたファイル
(仮にIDを hogehoge、パスワードを areare とする)を次のようにどこか
において
> hogehoge:~# cat ~/postgresql.auth
> hogehoge
> areare
/usr/local/pgsql/bin/pg_dump -u db_test1 < /root/postgresql.auth > db_test1.back
のようにすることで、パスワード入力を省くことができる。