Perl スクリプトを Solaris から Linux にポーティングする

直接マッピングすることができない場合にコードを再調整するためのガイド

Comments

仮想化技術の進歩に伴い、企業は物理サーバーを仮想環境に統合しつつあり、それによって資産管理を容易にする一方、電力消費と物理的なスペースを削減しています。この統合作業には、古いオペレーティング・システムから、システムの保守が容易なオペレーティング・システムや、TCO (Total Cost of Ownership: 総所有コスト) のメリットがある、その他のオペレーティング・システムへのマイグレーションが含まれる場合もあります。

Solaris から Linux へのマイグレーションを計画している場合、カスタム・コード (C、シェル・スクリプト、Perl、等々) のほとんどすべてに対し、プラットフォームの違いに対応した、何らかの再調整 (つまり属性のマッピングの「再編成」) を行う必要があります。

また、Perl は他の言語と変わりません。つまりプログラム自体はプラットフォーム間でポーティング可能であり、ターゲット・システムでコードを実行するためのインタープリターがインストールされてさえいればよいのですが、通常は、何らかの再調整を必要とする問題が発生します。Solaris 特有のリソース、なかでもオペレーティング・システムのパス名、システム・コマンド、Perl モジュールが、コードの中で使用されていることが多いものです。そのため、マイグレーション後も Perl スクリプトが本来の動作をするように、何らかの形でコードを再調整する必要があります。

では、Perl の構文のどの構成体、またどの演算子に対して最も注意する必要があるのでしょう。この記事では、ポーティングの際に非常によくある落とし穴について説明するとともに、Perl スクリプトを Solaris から Linux にマイグレーションするための手順について説明します。

この記事で説明する手順は、AIX や HP/UX など、ほとんどのUNIX オペレーティング・システムから Linux へのマイグレーション手順として使用できるはずです。ただし取り上げる例やサンプル・コード、参考資料はすべて、Solaris から Linux へのマイグレーションに焦点を絞っています。

Perl をポーティングする場合の問題点

Linux システム上で実行する場合に Solaris 特有のコードによって問題が発生しないように、Perl スクリプトで参照されるリソースを検証する必要があります。例えば、Solaris でしか使用しないファイルから情報を抽出するスクリプトを考えてみてください。あるいは、Linux にはないフラグを使用するシステム・コマンドを実行した場合を想像してみてください。

ポーティングに関する問題の大部分は、アクセスまたは参照されるシステム・リソースを基に 5 つの問題に分類することができます。これを一覧にしたものが表 1 です。

表 1. Perl スクリプトをポーティングする際の問題の分類
分類ポーティングする際の問題
01プラットフォーム特有の Perl モジュールに依存している
02オペレーティング・システムのコマンドと IPC (プロセス間通信)
03オペレーティング・システムのパス名の使い方
04プラットフォーム特有の情報を保持する特殊変数の使い方
05プラットフォームごとに実装が異なる関数、またはプラットフォームによっては実装されない関数

表 1 に挙げた分類は、ポーティングの問題をすべて網羅した最終的なリストではなく、単に最も一般的な問題を分類して挙げてあるにすぎません。ポーティングの問題に関する詳細は「Perl Programming Documentation」を参照してください (「参考文献」にリンクがあります)。

Perl スクリプトの完璧なポーティングのための 5 つのステップ

Perl スクリプトを Solaris から Linux にポーティングするための手順を調べてみましょう。この手順は表 1 に挙げたポーティングの問題の分類を基にしています。この手順には 5 つのステップが含まれ、それぞれのステップは表 1 の分類の 1 つに焦点を当てたものです。各ステップでは、何らかの形でコードの再調整が必要な、Perl の構文の構成体や演算子の問題に注目しています。

ステップ 1. Solaris 特有のモジュールに対する依存関係を検証する

最初のステップでは、インポートされた Perl モジュールを検証します。Perl モジュールには Solaris 専用に作成されているものがあり、それらのモジュールを使用すると、スクリプトは Solaris プラットフォームに関連付けられることになってしまいます。そこでスクリプト・コードごとに、Solaris 専用に作成されたモジュールを特定し、そのなかで使用されている関数や変数を明らかにする必要があります。そして適切な変更を加え、その Perl スクリプトを現在実行しているのではないプラットフォームに関連付けられることがないようにします。

CPAN のリポジトリーには、Solaris 特有のモジュールをすべて掲載したリストが用意されています。そうしたモジュールは通常、名前の最初が Solaris:: または Sun::Solaris:: になっています。

リスト 1 のシェル・スクリプトを使用すると、「Solaris」または「Sun」で始まる import 文を持つ Perl スクリプト・ファイルを特定することができます。

リスト 1. Solaris モジュールのインポートを見つける方法
#!/bin/bash
find . -name "*.pl" -exec grep -ilP "^\s*use (Solaris|Sun)" {} \;

リスト 1 のコードは、Perl スクリプトの中にある Solaris 特有のモジュールを検出する精度が高くなるように変更することができます。例えば、リスト 1 のシェル・スクリプトを Perl に変換し、PPI モジュールを利用して構文解析を行うことができます。この記事では PPI モジュールの使い方については説明しませんが、Perl コードを構文解析する際の精度を高めるために、是非とも PPI モジュールを使用するようお薦めします。

Solaris 特有のコードが含まれるスクリプトを特定することができたら、次に、Linux でも動作する等価なモジュールを検索する必要があります。機能面で等価なそうしたモジュールを特定することは必ずしも容易ではありません。元のモジュールが Solaris プラットフォーム専用の技術を使用している場合があるからです。そうした場合には、さらに深い分析を行う必要があります。

Linux ベースの等価なモジュールを使用するためには、すべての import 文、呼び出されるすべての関数変数を、新しいモジュールで等価な import 文関数変数と置き換える必要があります。

ステップ 2. Solaris 特有のシステム・コマンドの呼び出しを検証する

Perl スクリプトの中からの中からオペレーティング・システムのコマンドを呼び出している場合、そうした呼び出しは Solaris から Linux にマイグレーションする際に最もよく問題になります。その理由は以下のとおりです。

  • ターゲット・システムにコマンドがない
  • コマンドのフラグが異なる
  • プラットフォームによってコマンドの動作が異なる

従って、ポーティングの問題に関する分類番号 02 の問題、つまりシステム・コールを処理する際には、特に注意する必要があります。

この場合の目標は、スクリプト上で呼び出されるシステム・コマンドが、構文的にもその意味においても必ず Linux で適切に動作するようにすることです。簡単に言えば、Solaris 特有のシステム・コマンドを含むスクリプトの中で、利用されている Perl のコア関数と演算子をいかに特定するか、ということです。

1 つの例から始めましょう。リスト 2 は Solaris システムのメモリー容量を表示するための単純な Perl スクリプトです。

リスト 2. システムのメモリー容量を表示する Perl スクリプト
#!/usr/bin/perl 
my $mem_info = `prtconf | grep Memory`; 
my (undef, $mem_size) = split(':', $mem_info); 
($mem_size, undef) = split(' ', $mem_size); 
print "Memory size is: ".$mem_size."\n";

ここで、同じスクリプトを Linux で実行するとしましょう。リスト 2 のスクリプトは、バックティック (`) 演算子で囲まれたシステム・コマンドのパイプ (prtconf | grep Memory) を呼び出しており、prtconf コマンドは Solaris 特有のものであることはわかります。そこで最初のステップとして、このコマンドに代わるコマンドを見つけます。

cat /proc/meminfo | grep MemTotal を使うことはできますが、出力のフォーマットが異なります。/proc/meminfo ではメモリー容量の情報を KB で保持しますが、prtconf は MB で保持するからです。

このスクリプトを再調整するために ptrconfcat /proc/meminfo で置き換えることができますが、出力情報を MB のままにするためには (このスクリプトの出力が他のスクリプトの入力に使われているかどうかがわからないため、MB のまま変更しないことが重要です)、単純な変換を使うことができます。リスト 3 は、このスクリプトを再調整する方法の一例を示しています。

リスト 3. リスト 2 のスクリプトを再調整する
#!/usr/bin/perl 
my $mem_info = `cat /proc/meminfo | grep MemTotal`; 
my (undef, $mem_size) = split(':', $mem_info); 
($mem_size, undef) = split(' ', $mem_size); 
$mem_size = int($mem_size / 1000); 
print "Memory size is: ".$mem_size."\n";

Perl には、オペレーティング・システムのコマンドをさまざまな方法で実行するだけの柔軟性があるため、そのために使用できるコアとなる関数や演算子が数多くあります。表 2 は、Perl スクリプトの中からシステム・コマンドを呼び出すために使用可能なコア関数と演算子の一覧です。

表 2. システム・コマンドを呼び出すために使用可能なコア関数と演算子
関数/演算子Solaris での例Linux での例
backtick (``)`prstat``ps -e`
systemsystem("psrinfo")system("cat","/proc/cpuinfo")
execexec("/usr/sbin/df -kZ")exec("/bin/df -kZ")
qxqx/"metastat"/qx/"lvdisplay"/
openopen DATA, "cat /var/cron/log |"Open DATA, "cat /var/log/cron"
readpipereadpipe( "cat /etc/default/login " )Readpipe( "cat /etc/default/login" )

これらの関数と演算子、その他 Perl 言語のコアの一部としては含まれていない各関数や演算子についての詳細は、Perl のドキュメントを調べてください。システム管理コマンドの違いについては、IBM Redbooks 「Solaris から Linux への移行: システム管理者ガイド」を参照してください。

ステップ 3. オペレーティング・システムのパス名の使い方を検証する

今度は、Perl スクリプトに使用されているパス名のマイグレーションについて説明しましょう。このステップはステップ 2 と似ています。このステップでは、ファイルのオープンまたは操作に使用されている構文要素と演算子に注意する必要があります。Perl には、ファイルのオープンや操作のための専用の演算子はありますが、パス名が参照されていることによって問題が発生する場合があります。(この問題は、ステップ 2 で説明したシステム・コマンドを呼び出す場合にも発生します。)

リスト 4 は、Solaris による NFS サーバーの構成ファイルを読み取って標準出力に出力する簡単なスクリプトを示しています。

リスト 4. システム・ファイルの内容を標準出力に出力する Perl スクリプト
#!/usr/bin/perl 
open(NFSCONF, '/etc/default/nfs'); 
print <NFSCONF>; 
close(NFSCONF);

Solaris から Linux にマイグレーションする場合、システム・パスに注意する必要があります。システム・パスが異なることはよくあります。この例の場合、この Solaris スクリプトで参照されている /etc/default/nfs ファイルは Linux/Red Hat ディストリビューションには存在しませんが、/etc/default/nfs と置き換えることができます。リスト 5 は、リスト 4 を再調整した後のスクリプトを示しています。

リスト 5. リスト 4 を再調整した結果
#!/usr/bin/perl 
open(NFSCONF, '/etc/sysconfig/nfs'); 
print <NFSCONF>; 
close(NFSCONF);

ファイルを操作する Perl コマンドのすべてに対して注意する必要があります。表 3 は、Perl でよく使われるパス処理コマンドの一部を示しています。これらのコマンドのどれかがスクリプトの中で使用されている場合には、マイグレーションの際にパス名を再調整する必要があります。

表 3. Perl でよく使用されるパス処理コマンド
コマンド説明
chdir作業ディレクトリーを変更します
chmod一連のファイルのパーミッションを変更します
globワイルドカードを展開し、ファイル名の一覧 (空の場合もあります) を返します。
link古いファイル名にリンクされた新しいファイル名を作成します
mkdir新しいディレクトリーを作成します
openファイルを開きます
opendirディレクトリーを開きます
renameファイルの名前を変更します
rmdir指定されたディレクトリーを削除します
sysopen指定されたファイルを開き、指定されたファイル・ハンドルに関連付けます

ステップ 4. Solaris 特有の情報を保持する特殊変数の使い方を検証する

一部の特殊変数は Solaris 特有の環境情報を保持しています。これらの変数を特定し、適切に変換する必要があります。表 4 は、Solaris 特有の情報や参照を保持する可能性があるコア変数をいくつか示しています。

表 4. Perl のコア変数の一部 (変数の一覧は「Perl Programming Documentation」を参照)
変数説明
ENV現在の環境変数を含んでいます。これらの変数のなかには、Solaris と Linux との間で直接マッピングすることができないものがあるかもしれません。変数の例として、NETPATH、MSGVERB、SEV_LEVEL などがあります。
SIGシグナルに対するシグナル・ハンドラーを含んでいます。両方のプラットフォームでのシグナルの違いについては「参考文献」セクションを参照してください。

ステップ 5. プラットフォームによって実装が異なる関数の使い方を明らかにする

Perl のコア関数の一部は、プラットフォームによっては実装されない場合や、プラットフォームによって実装が異なる場合があります。こうした関数の動作が Solaris と Linux とで異なる場合には、Linux プラットフォームでも同様の動作をするようにこれらの関数を変更するか、あるいは Linux プラットフォームに対応する補完バージョンを探してそのバージョンに速やかに移行する必要があります。この点についても、「Perl Programming Documentation」を参照してください (「参考文献」にリンクがあります)。

まとめ

Solaris から Linux (または HP/UX や AIX から Linux) へマイグレーションする際、Perl スクリプトのコンポーネントの中で最も問題を起こしがちな 5 つのコンポーネントを特定する作業は、それほど困難ではありません。しかしコードに対して必要な再調整と置き換えを行い、Perl スクリプトを Linux でも適切に動作させるには、非常に時間がかかります。これは、マイグレーション対象となるスクリプトが多い場合にはなおさらのことです。この記事ではその出発点として、コードを再調整するための助言と例を紹介しました。皆さんの幸運をお祈りします。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux, Open source
ArticleID=587503
ArticleTitle=Perl スクリプトを Solaris から Linux にポーティングする
publish-date=10202010