2012年2月7日火曜日

perl DBD::Oracle モジュールの rpm 化

perl DBD::Oracle モジュールの rpm 化 (改訂版)
(http://dba-ha.blogspot.jp/2014/11/perl-dbdoracle-rpm.html)
をご参照ください。
cpan2rpm のサイトがなくなったようで、spec ファイルを書き起こしています。
RHEL5、RHEL6、RHEL7 に対応しています。



長期間放置してしまいました。
この投稿を公開したのが2012/02/07なので丸一年です。
このページのビューが多いようなのでメンテナンスします。

DBD-Oracle-1.57_00.tar.gz 用の rpm を作る機会があり、修正したい箇所がありました。
赤字で訂正部分を入れました(2013/02/19)。


perl の DBD::Oracle モジュールを rpm 化します。

まず Oracle instant client をインストールし、cpan2rpm を使って DBD::Oracle モジュール用の spec ファイルを作成し、rpm パッケージを作成します。

インターネットに直接つながるホストで作業します。RHEL5, RHEL6 の x86_64, i686 版用のものを作成します。RHEL5 x86_64 用のものを例示していきます。異なる部分は読み替えてください。単純に読み替えできない部分は注釈します。

Oracle Database Instant Client (http://www.oracle.com/technetwork/database/features/instant-client/index.html) のページにアクセスし以下のようにリンクをたどります。
[See Instant Client downloads for all platforms]
[Instant Client for Linux x86-64]

[Accept License Agreement] をチェックし、以下のファイルをダウンロードします。
ダウンロードに際し、サインインするように促されます。

oracle-instantclient11.2-basic-11.2.0.3.0-1.x86_64.rpm
oracle-instantclient11.2-sqlplus-11.2.0.3.0-1.x86_64.rpm
oracle-instantclient11.2-devel-11.2.0.3.0-1.x86_64.rpm

必要であれば、以下のファイルもダウンロードします。

oracle-instantclient11.2-jdbc-11.2.0.3.0-1.x86_64.rpm
oracle-instantclient11.2-odbc-11.2.0.3.0-1.x86_64.rpm
oracle-instantclient11.2-tools-11.2.0.3.0-1.x86_64.rpm

Precompiler パッケージも必要であれば、以下のリンクからダウンロードします。
[Instant Client Package - Precompiler:]

oracle-instantclient11.2-precomp-11.2.0.3.0-1.x86_64.rpm

必要なパッケージがそろったらインストールします。

$ sudo rpm -ivh oracle-instantclient11.2-*.rpm

Oracle Database や Oracle Client、別バージョンの Oracle instant client 等をインストールしないのであれば、以下のように登録しておくと便利です。

$ cat << 'EOF' | sudo tee /etc/profile.d/oic.sh
> export ORACLE_HOME='/usr/lib/oracle/11.2/client64'
> #export C_INCLUDE_PATH='/usr/include/oracle/11.2/client64'
> #export LD_LIBRARY_PATH='/usr/lib/oracle/11.2/client64/lib'
> EOF
export ORACLE_HOME='/usr/lib/oracle/11.2/client64'
#export C_INCLUDE_PATH='/usr/include/oracle/11.2/client64'
#export LD_LIBRARY_PATH='/usr/lib/oracle/11.2/client64/lib'

$ cat << 'EOF' | sudo tee /etc/ld.so.conf.d/oic.conf
> /usr/lib/oracle/11.2/client64/lib
> EOF

$ sudo /sbin/ldconfig

新たにログインするか、

$ export ORACLE_HOME='/usr/lib/oracle/11.2/client64'
$ export LD_LIBRARY_PATH='/usr/lib/oracle/11.2/client64/lib'

を実行します。
後述の cpan2rpm コマンドによる作業では、「LD_LIBRARY_PATH」環境変数の定義が必須ですが、上記の手順にて、Oracle instant client ライブラリのパスを「ldconfig」コマンドにてシステム登録しているので、通常のクライアント操作では不要のはずです。「ldconfig」コマンドを実行しない場合は「LD_LIBRARY_PATH」環境変数の定義が必須です。
ORACLE_HOME」環境変数は常に必須です。
ここでは、 cpan2rpm コマンドを利用するので、新たにログインしなおした場合も「LD_LIBRARY_PATH」環境変数を定義します。

※ RHEL i686 版では「client64」を「client」に置き換えます。

以下のようなコマンドでデータベースにアクセスできるようになります。

$ sqlplus64 system/password@hostname:1521/sid

※ RHEL i686 版では「sqlplus64」を「sqlplus」に置き換えます。

無事 Oracle instant client がインストールできたことを確認したところで、次に cpan2rpm をインストールします。
最新版を以下のサイトで確認しダウンロードします。

$ sudo wget http://ftp.arix.com/cpan2rpm-2.028-1.noarch.rpm \
> -O /var/tmp/cpan2rpm-2.028-1.noarch.rpm

このパッケージを利用するには、「perl-libwww-perl」パッケージが必要となります。
RHEL6 では「perl-ExtUtils-MakeMaker」も必要となります。RHEL5 の場合は「perl」パッケージに含まれています。
DBD::Oracle モジュールは DBI モジュールに依存するので「perl-DBI」パッケージもインストールします。

$ sudo yum install \
>   perl-DBI \
>   perl-libwww-perl \
>   perl-ExtUtils-MakeMaker
$ sudo rpm -ivh /var/tmp/cpan2rpm-2.028-1.noarch.rpm

RHEL6 では以下のコマンドでスクリプトを一部修正する必要があります。

$ grep Pod /usr/bin/cpan2rpm
use Pod::Text;
    my $pod = Pod::Text->new();
$ grep '6\.' /etc/redhat-release && \
> sudo sed -i -e 's!Pod::Text!Pod::Parser!' /usr/bin/cpan2rpm
$ grep Pod /usr/bin/cpan2rpm
use Pod::Parser;
    my $pod = Pod::Parser->new();

DBD::Oracle モジュール用の spec ファイルを作成するに当たり、私の環境(「keepalived の rpm を作る」を参照)では「~/.rpmmacro」ファイルに「%_sourcedir %{_topdir}/SOURCES/%{name}」を定義しているので、以下のコマンドでディレクトリを作成する必要がありました。通常は不要だと思います。

$ mkdir ~/rpmbuild/SOURCES/%{name}
$ mkdir ~/rpmbuild/SOURCES/perl-DBD-Oracle

http://cpan.perl.org/modules/by-module/DBD/ あたりで DBD::Oracle モジュールの最新バージョンを確認します。
spec ファイルを作成します。

$ OIC_VER=11.2.0.3.0
$ PERL_DBD_ORACLE_VER=1.38
$ cpan2rpm --no-sign DBD::Oracle \
>   --version ${PERL_DBD_ORACLE_VER} --release=${OIC_VER}%{dist} \
>   --make-no-test --no-clean --spec-only \
>   --requires=oracle-instantclient11.2-basic \
>   --buildrequires=oracle-instantclient11.2-devel,
oracle-instantclient11.2-sqlplus \
>   --no-requires=libclntsh.so.11.1,libocci.so.11.1

-- cpan2rpm - Ver: 2.028 --
Upgrade check
Fetch: HTTP

-- module: DBD::Oracle --
Found: DBD-Oracle-1.38.tar.gz
At: http://search.cpan.org//CPAN/authors/id/P/PY/PYTHIAN
Retrieving URL
Metadata retrieval
Tarball extraction: [/home/mockbuild/rpmbuild/SOURCES/%{name}/DBD-Oracle-1.38.tar.gz]
Generating spec file
SPEC: /home/mockbuild/rpmbuild/SPECS/DBD-Oracle.spec
-- Done --

オプションの詳細は「man cpan2rpm」で調べていただくこととして、「--no-requires」について一言。これがないとインストールに失敗する rpm ができてしまいました。「--requires」オプションを指定しているので良しとします。試していませんが、Oracle instant client を zip ファイル解凍にてインストールする場合には、「--requires」オプションを除外してパッケージを作成しておく必要があるものと思われます。DBD::Oracle モジュールは、環境によって動かないこともあるようなので、環境ごとに rpm を毎回作る方がよいのだと思います。

DBD-Oracle-1.57_00.tar.gz だと、--no-requires」は不要でした。少し前のバージョンで oraperl 等のレガシーなものが別のパッケージに分離されたおかげと思われます。すっきりしました。

※ RHEL6 では「Generating spec file」の前行に「tar: write error」と表示されますが、spec ファイルを作成する場合には無視してよさそうです。

DBD-Oracle-1.57_00.tar.gz だと、このエラーも出なくなりました。すっきりです。

私の環境では、cpan2rpm コマンドがダウンロードしてくれたソースファイルを移動する必要があります。

$ mv ~/rpmbuild/SOURCES/%\{name\}/DBD-Oracle-1.38.tar.gz \
> ~/rpmbuild/SOURCES/perl-DBD-Oracle/

作成された spec ファイルは以下のようになっていました(140行目を除き、全環境で同一)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#
#   - DBD::Oracle -
#   This spec file was automatically generated by cpan2rpm [ver: 2.028]
#   The following arguments were used:
#       --no-sign DBD::Oracle --version 1.38 --release=11.2.0.3.0%{dist} --make-no-test --no-clean --spec-only --requires=oracle-instantclient11.2-basic --buildrequires=oracle-instantclient11.2-devel,oracle-instantclient11.2-sqlplus --no-requires=libclntsh.so.11.1,libocci.so.11.1
#   For more information on cpan2rpm please visit: http://perl.arix.com/
#

%define pkgname DBD-Oracle
%define filelist %{pkgname}-%{version}-filelist
%define NVR %{pkgname}-%{version}-%{release}
%define maketest 0
%define custom_find_req %{_tmppath}/%{NVR}-find-requires
%define _use_internal_dependency_generator 0
%define __find_requires %{custom_find_req}
%define __perl_requires %{custom_find_req}

name:      perl-DBD-Oracle
summary:   DBD-Oracle - Oracle database driver for the DBI module
version:   1.38
release:   11.2.0.3.0%{dist}
vendor:    Tim Bunce (dbi-users@perl.org)
packager:  Arix International <cpan2rpm@arix.com>
license:   Artistic
group:     Applications/CPAN
url:       http://www.cpan.org
buildroot: %{_tmppath}/%{name}-%{version}-%(id -u -n)
prefix:    %(echo %{_prefix})
requires:  oracle-instantclient11.2-basic
buildrequires: oracle-instantclient11.2-devel
buildrequires: oracle-instantclient11.2-sqlplus
source:    http://search.cpan.org//CPAN/authors/id/P/PY/PYTHIAN/DBD-Oracle-1.38.tar.gz

%description
DBD::Oracle is a Perl module which works with the DBI module to provide
access to Oracle databases.

This documentation describes driver specific behaviour and restrictions. It is
not supposed to be used as the only reference for the user. In any case
consult the DBI documentation first!

#
# This package was generated automatically with the cpan2rpm
# utility.  To get this software or for more information
# please visit: http://perl.arix.com/
#

%prep
%setup -q -n %{pkgname}-%{version}
chmod -R u+w %{_builddir}/%{pkgname}-%{version}

%build
grep -rsl '^#!.*perl' . |
grep -v '.bak$' |xargs --no-run-if-empty \
%__perl -MExtUtils::MakeMaker -e 'MY->fixin(@ARGV)'
CFLAGS="$RPM_OPT_FLAGS"
%{__perl} Makefile.PL `%{__perl} -MExtUtils::MakeMaker -e ' print qq|PREFIX=%{buildroot}%{_prefix}| if \$ExtUtils::MakeMaker::VERSION =~ /5\.9[1-6]|6\.0[0-5]/ '`
%{__make}
%if %maketest
%{__make} test
%endif

%install
[ "%{buildroot}" != "/" ] && rm -rf %{buildroot}
cat <<EOF > %{custom_find_req}
#!/bin/sh
/usr/lib/rpm/find-requires |grep -v -e 'libclntsh.so.11.1' -e 'libocci.so.11.1'
EOF
chmod 755 %{custom_find_req}

%{makeinstall} `%{__perl} -MExtUtils::MakeMaker -e ' print \$ExtUtils::MakeMaker::VERSION <= 6.05 ? qq|PREFIX=%{buildroot}%{_prefix}| : qq|DESTDIR=%{buildroot}| '`

cmd=/usr/share/spec-helper/compress_files
[ -x $cmd ] || cmd=/usr/lib/rpm/brp-compress
[ -x $cmd ] && $cmd

# SuSE Linux
if [ -e /etc/SuSE-release -o -e /etc/UnitedLinux-release ]
then
    %{__mkdir_p} %{buildroot}/var/adm/perl-modules
    %{__cat} `find %{buildroot} -name "perllocal.pod"`  \
        | %{__sed} -e s+%{buildroot}++g                 \
        > %{buildroot}/var/adm/perl-modules/%{name}
fi

# remove special files
find %{buildroot} -name "perllocal.pod" \
    -o -name ".packlist"                \
    -o -name "*.bs"                     \
    |xargs -i rm -f {}

# no empty directories
find %{buildroot}%{_prefix}             \
    -type d -depth                      \
    -exec rmdir {} \; 2>/dev/null

%{__perl} -MFile::Find -le '
    find({ wanted => \&wanted, no_chdir => 1}, "%{buildroot}");
    print "%doc  README.java.txt README.win32.txt Changes README.macosx.txt README.clients.txt examples README.win64.txt README.hpux.txt README.sec.txt hints Todo README.aix.txt README-files README.help.txt README.mkdn INSTALL README.64bit.txt README LICENSE";
    for my $x (sort @dirs, @files) {
        push @ret, $x unless indirs($x);
        }
    print join "\n", sort @ret;

    sub wanted {
        return if /auto$/;

        local $_ = $File::Find::name;
        my $f = $_; s|^\Q%{buildroot}\E||;
        return unless length;
        return $files[@files] = $_ if -f $f;

        $d = $_;
        /\Q$d\E/ && return for reverse sort @INC;
        $d =~ /\Q$_\E/ && return
            for qw|/etc %_prefix/man %_prefix/bin %_prefix/share|;

        $dirs[@dirs] = $_;
        }

    sub indirs {
        my $x = shift;
        $x =~ /^\Q$_\E\// && $x ne $_ && return 1 for @dirs;
        }
    ' > %filelist

[ -z %filelist ] && {
    echo "ERROR: empty %files listing"
    exit -1
    }

%clean
[ "%{buildroot}" != "/" ] && rm -rf %{buildroot}
rm -f %{custom_find_req}

%files -f %filelist
%defattr(-,root,root)

%changelog
* Tue Feb 7 2012 mockbuild@work01.example.com
- Initial build.

※ 31行目が追加となります。

DBD-Oracle-1.57_00.tar.gz のビルドに利用する場合は、
・5行目の「--no-requires=libclntsh.so.11.1,libocci.so.11.1削除
・13-16、65-69、134行目削除
・20行目の「1.38」を「1.57_00」に変更
・99行目を「print "%doc  hints Todo Changes README.help.txt README.mkdn INSTALL LICENSE README examples";」に変更
・140行目を適宜変更
・32行目を「source:    %{source}/DBD-Oracle-%{version}.tar.gz」に変更
  

ビルドする準備が整ったので、ビルドします。
上記の spec ファイルと DBD::Oracle モジュールのソースファイルがあれば、cpan2rpm コマンドがなくても、インターネットにつながっていなくても、ビルドできます。その場合は、32行目を以下のように修正してください。

source:    %{source}/DBD-Oracle-%{version}.tar.gz

$ rpmbuild -ba ~/rpmbuild/SPECS/DBD-Oracle.spec
(中略)
Wrote: /home/mockbuild/rpmbuild/SRPMS/perl-DBD-Oracle-1.38-11.2.0.3.0.el5pcs.src.rpm
Wrote: /home/mockbuild/rpmbuild/RPMS/x86_64/perl-DBD-Oracle-1.38-11.2.0.3.0.el5pcs.x86_64.rpm
Wrote: /home/mockbuild/rpmbuild/RPMS/x86_64/perl-DBD-Oracle-debuginfo-1.38-11.2.0.3.0.el5pcs.x86_64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.51955
+ umask 022
+ cd /home/mockbuild/rpmbuild/BUILD
+ cd DBD-Oracle-1.38
+ '[' /var/tmp/perl-DBD-Oracle-1.38-mockbuild '!=' / ']'
+ rm -rf /var/tmp/perl-DBD-Oracle-1.38-mockbuild
+ rm -f /var/tmp/DBD-Oracle-1.38-11.2.0.3.0.el5pcs-find-requires
+ exit 0

出来上がったパッケージを必要なところにコピーしておきます。

インストールして、動作確認します。

$ sudo rpm -ivh ~/rpmbuild/RPMS/*86*/perl-DBD-Oracle-1*.rpm

$ cat << 'EOF' | tee test.pl
> #!/usr/bin/perl
> use strict;
> use DBI;
> my $hDb = DBI->connect('dbi:Oracle:host=hostname;sid=sid;port=1521', "system/password") or die "CONNECT ERROR $DBI::errstr";
> my $hSt = $hDb->prepare('select * from v$instance');
> my $nRes = $hSt->execute;
> while(my $raRes = $hSt->fetchrow_arrayref) {
>     print join("\t", @$raRes), "\n";
> }
> $hSt->finish;
> $hDb->disconnect;
> EOF
$ chmod 755 test.pl
$ ./test.pl




0 件のコメント:

コメントを投稿