blog20100901

2013/08/20 - プログラミング言語 Perl にまつわる etc. - Perl monger
参考 : perldoc, perldoc.jp, search.cpan.org, perldoc.perl.org ...
「 初めての Perl 第 6 版 」(オライリー・ジャパン発行 ISBN978-4-87311-567-2) 」
「 続・初めての Perl 改訂版 」(オライリー・ジャパン発行 ISBN4-87311-305-9) 」
「 Effective Perl 第 2 版 」(翔泳社発行 ISBN978-4-7981-3981-4) 」 ... etc,.

Perl Perl_5

Perl システムコマンドを exec で利用する exec, system (0x257)

Perl システムコマンドを exec で利用する exec, system (0x257)

目次 - Perl Index



Theme



Perl について、復習を兼ねて断片的な情報を掲載して行く連載その 0x257 回。


Perl で、シェルのシステムコマンドを利用する関数「 system 」を確認するために関数「 exec 」を確認しておく。


関数「 exec 」



システムコマンドを実行可能な Perl の関数「 system 」を system - perldoc.jp で確認しようとしたところ、冒頭で同じくシステムコマンドを実行可能な関数「 exec 」とほとんど同じと説明されていたため、はじめに exec - perldoc.jp を確認しておきます。


exec 書式



Perl の関数「 exec 」は、通常はシェルで利用するシステムコマンドを実行することが出来ます。「 exec 」の書式は次のものです。


exec LIST
exec PROGRAM LIST




exec の実行



引数「 LIST 」には、例えば次のように記述します。ここでは、システムコマンドに「 echo 」、その引数に文字列「 Hello 」を指定しています。


exec 'echo Hello';



この Perl プログラムの実行結果は次の通りです。


Hello



次のように、引数を複数に分割しても同じ結果 ( 文字列 Hello ) を得られます。


exec 'echo', 'Hello';




ひとつの引数と複数の引数の異なる処理



前項で確認したように、関数「 exec 」は引数がひとつでも複数でも同じ結果を返しますが、内部で行われる処理は異なります。

まず、「 引数が 1 つの場合、かつ、引数の中にシェルが解釈可能なメタキャラクタが含まれている 」場合には、Perl はシェル ( 通常は /bin/sh -c ) を起動して引数全体を渡します。

ですから、この場合は Perl が子プロセスとして起動したシェルが引数の処理を実行します。


# リダイレクションのメタキャラクタ > が含まれる
exec 'echo Hello > file';



「 引数が 1 で、かつ、引数の中にシェルのメタキャラクタが含まれない 」場合と、「 引数が複数 」の場合は Perl 自身が「 execvp(3) 」をシステムから呼び出して引数の処理を実行します。


# 引数が 1 つでメタキャラクタを含まない
exec 'echo Hello';

# 引数が複数
exec 'echo', 'Hello';



ですからこの場合、シェルは起動されません。


別名で起動する「 間接オブジェクト 」



書式「 exec PROGRAM LIST 」では、「 間接オブジェクト 」( indirect object ) というものを利用して、指定したコマンドを別の名前で実行出来ます。

例えば、次のようにすればコマンド「 echo 」を別名「 Hello 」として実行できます。「 { } 」ブロックと最初の引数の間にカンマがないことに注意します。


my $echo = '/bin/echo';
exec { $echo } 'Hello', 'hello';



「 echo 」の処理は一瞬で終わってしまうので代わりにコマンド「 sleep 」を使うと別名を利用していることが良く分かります。


my $sleeping = '/bin/sleep';
exec { $sleeping } 'sleeping', 100;



上記を実行した後で、別の仮想端末 (terminal emulator) 等でコマンド「 ps 」をオプション「 a 」を付けて実行するとコマンド sleep が sleeping として表示されることが分かります ( pstree では sleep となっていましたが )。


$ ps a
PID TTY STAT TIME COMMAND
:
3355 pts/0 S+ 0:00 sleeping 1000
3359 pts/2 Ss 0:00 bash
3379 pts/2 R+ 0:00 ps a
:
.



この Tip は Using the Perl system() function - GSSG で確認しました。

通常この形式はあまり使わないそうですが、関数「 exec 」( および「 system 」) での配列変数のチェック ? に利用出来るようです。

例えば、次のコードの場合、引数は単一 ( スカラ ) の引数として処理されるので、スカラ変数にシェルのメタキャラクタ等が含まれる場合は、処理がシェルに渡されるかもしれません。


my @args = ("/bin/echo $message");
system @args;



しかし、次の場合は、引数がリストとして処理されるので ( おそらく ) 直接 execvp が呼び出されることになります。


my @args = ("/bin/echo", $message);
system @args;



このように配列変数の中身によって execvp を利用したりシェルを呼び出したりされることはプログラム上想定外の危険を生むことがあります ( execvp を利用する方が安全と理解しています)。

そこで、次のように間接オブジェクト記法を利用します。


system { $args[0] } @args;



この様に配列を使えば、必ず引数をリストモードとして処理する ( excvp を呼び出す ) ように強制することが出来るといいます。

この時「 $args[0] 」は、コマンドの名前として解釈されます。また、「 $args[0] 」が 2 回利用されるように見えますが、それは気にしなくてよい (?) そうです。

もし、「 $args[0] 」の中身が「 "/bin/echo 'Hello'" 」 のようになっていれば、関数「 exec 」( および「 system 」) は、値全体をひとつのコマンド名「 /bin/echo 'Hello' 」として解釈するのでエラーになります。

これがどういうことかというと、この間接オブジェクト記法をつかえば、最初の引数全体を必ず単独コマンド名として処理しようとするので、その文字列の中にシェルのメタキャラクタが入っていたとしても、シェルは起動されることがなくなる ( エラーになる ) ということです。

つまりこの記法を使えば、意図しないシェルのメタキャラクタの実行を防止し、悪意を持った外部からの入力を無効とすることが出来ます。これについては関数「 system 」とあわせて確認します。


「 exec 」は Perl に戻ってこない



関数「 exec 」には重要な特徴があります。

それは、「 exec 」によってコマンドが実行された後は処理が Perl に戻ってこないということです。

つまり、次のようなコードを記述した場合、「 exec 」の処理は実行されますが、次の処理 ( ここでは print ) は実行されません。


exec 'echo', 'Hello';
print "return?\n";



もし、このコードを実行すると次のようなメッセージが出力されます。


Statement unlikely to be reached at file.pl line N.
(Maybe you meant system() when you said exec()?)
Hello



メッセージの内容は「 ステートメントは 到達しそうにありません file.pl の N 行目に. 」です。

それから「 あなたは system の意味で 利用していませんか "exec" を ? 」と続きます。

ですから、システムコマンドを実行した後も、Perl プログラムで処理を継続したい場合は、関数「 system 」を利用します。


0x257 -> 0x258 へ



次回は、関数「 system 」を確認します。


参考情報は書籍「 初めての Perl 第 6 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。

目次 - Perl Index





















同じカテゴリー(Perl)の記事
 Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228) (2023-10-11 23:49)
 Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227) (2023-05-26 15:41)
 Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226) (2023-05-19 17:05)
 Perl mp2 翻訳 テンプレートシステムの選択 (d225) (2022-08-15 22:23)
 Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224) (2022-06-15 20:43)
 Perl mp2 翻訳 チュートリアル (d223) (2022-06-15 20:42)
上の画像に書かれている文字を入力して下さい
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。

Llama
リャマ
TI-DA
てぃーだブログ
プロフィール
セラ (perlackline)
セラ (perlackline)
QRコード
QRCODE
オーナーへメッセージ

PAGE TOP ▲