system() は、指定したコマンドを実行します。下記の例では netstat というネットワーク関連の情報を表示するコマンドを実行しています。
system("netstat -a");
関数の戻り値として 実行ステータス を返します。実行ステータスは実行結果を示す整数値で、通常、成功すれば 0、失敗すれば 0 以外の値になります。
$retcode = system("netstat -a");
system() では、コマンドが終了するまで処理を Perl に戻しません。
コマンドの実行結果を変数に読み取るには、`...` を用います。` はクォーテーションではなく、バッククォーテーションなので注意してください。下記のようにしてコマンドの実行結果をプログラムで読み込むことができます。
@list = `netstat -a`; print @list;
qx/.../ は `...` と同じ意味を持ちます。qx(...) のように、任意の記号や括弧文字を用いることができます。
@list = qx/netstat -a/; print @list;
open() の第2引数を "コマンド名 |" とすることで、コマンドを実行し、その結果をファイルハンドルから読み込むことができます。コマンドとコマンドの間の入出力をつないでデータを送り込むことから、| のことを パイプ と呼んでいます。下記の例では、netstat -a コマンドを実行し、LISTEN という文字を含む行だけを表示しています。
open(CMD, "netstat -a |"); while (<CMD>) { if (/LISTEN/) { print; } } close(CMD);
open() の第2引数を "| コマンド名" とすることで、コマンドを実行し、そのコマンドにデータを渡してやることができます。下記の例では myadd という名前のコマンドを起動し、その標準入力に数値データを渡しています。
open(CMD, "| myadd"); print CMD "12345\n"; print CMD "67890\n"; close(CMD);
コマンドにデータを渡してその結果を読み取るには、コマンドの標準入力、標準出力両方を参照する必要があります。例えば、nkf -s という漢字コード変換コマンドを起動して、その標準入力にデータを渡して、コマンドの標準出力を読み出す場合、下記のようにできればいいのですが、Perl はこれをサポートしていません。
open(CMD, "| nkf -s |"); # Perlではこの書き方は未サポート
これを実現するには、少し面倒ですが、Open2 というモジュールの機能を用いて次のようにします。
use IPC::Open2; # コマンドを入出力モードで起動する $pid = open2(*READ, *WRITE, "nkf -s"); # コマンドの標準入力にデータを送る print WRITE "あいうえお"; close(WRITE); # コマンドの標準出力からデータを読み出す $line = <READ>; print "$line\n";
適切な時点で close(WRITE) を呼び出してやらないと、コマンドが永遠に入力待ちの状態になってしまうので注意してください。close() を呼び出した場合でも、Windows 98 では動作を確認しましたが、Windows XP ではうまく実行できないようです。
コマンドの実行結果を ヌルデバイス に リダイレクト(転送)してやることで、コマンドは実行するけれども、その表示データを捨ててしまうことができます。ヌルデバイスは、Windows の場合は NUL: がヌルデバイスになります。
$status = system("netstat -a > NUL:"); print "status = $status\n";
UNIX 系の場合は /dev/null がヌルデバイスになります。
$status = system("netstat -a > /dev/null"); print "status = $status\n";
パイプ(|)はコマンドの標準出力(STDOUT)しか読み取りませんが、2>&1 を付加することにより、コマンドの標準エラー出力(STDERR)も読み取ることができるようになります。もともとは UNIX 固有の機能ですが、Windows XP でも使用できるようです。
open(CMD, "/bin/ls nofile 2>&1 |"); while (<CMD>) { print "=== $_"; } close(CMD);