Cookbook

16.22 シグナルを致命的エラーに変換する

捕捉するように設定していないシグナルが原因となってプログラムが強制終了させられる場合、通常はENDブロックが実行されない。 sigtrapプラグマを使用する use sigtrap qw(die untrapped normal-signals);

16.21 動作のタイムアウト

動作が一定の長さの時間を超えて実行され続けることのないようにしたい。 SIGALARMハンドラを設定して、dieを呼び出す。 eval { local $SIG{ALARM} = sub { die "alarm clock restart" }; alarm 10; # アラームを10秒に設定する eval { # 実行するのに時間の…

16.20 シグナルをブロックする

シグナルの受け取りを遅らせたい。その目的は、任意の時点でプログラムに割り込む可能性のあるシグナルによって、予想外の動作が引き起こされるのを防止するためである。 sigprocmaskシステムコールに対するPOSIXモジュールのインターフェースを使用する。 u…

16.19 ゾンビプロセスの蓄積を防ぐ

終了した子プロセスの状態を確認する必要がない場合 $SIG{CHLD} = 'IGNORE'; 終了したプロセスの状態を意図的に確認する必要がある場合 use POSIX ":sys_wait_h"; $SIG{CHLD} = \&REAPER; sub REAPER { my $stiff; while (($stiff = waitpid(-1, WNOHANG)) >…

16.17 シグナルハンドラを書く

16.18 Ctrl+Cを捕捉する

SIGINTに対応するハンドラを設定する。 $SIG{INT} = 'IGNORE'; 何らかの処理を行う場合 $SIG{INT} = \&tsktsk; sub tsktsk { $SIG{INT} = \&tsktsk; warn "\aThe long habit of living indisposeth us for dying.\n"; }

16.16 シグナルハンドラを一時的に上書きする

localを使用して、シグナルの動作を一時的にオーバーライドする # シグナルハンドラ sub ding { $SIG{INT} = \&ding; warn "\aEnter your name!\n"; } # 名前の要求をするために、SIGINTをオーバーライドする。 sub get_name { local $SIG{INT} = \&ding; my…

16.15 シグナルハンドラを設定する

%SIGハッシュを使用して、独自のハンドラをインストールする。 $SIG{QUIT} = \&got_sig_quit; # SIGQUITを受け取るたびに&got_sig_quitを呼び出す $SIG{PIPE} = 'got_sig_pipe'; # SIGPIPEを受け取るたびにmain::got_sig_pipeを呼び出す $SIG{INT} = sub {$o…

16.14 シグナルを送信する

killコマンドを使用する kill 9 => $pid; # $pidにシグナル9を送信する kill -1 => $pgrp; # ジョブ全体にシグナル1を送信する kill USR1 => $$; # 現在のプロセスにSIGUSR1を送信する kill HUP => @pids; # @pidsに含まれるプロセスにSIGHUPを送信する

16.13 利用可能なシグナルの一覧を表示する

% kill -l % perl -e 'print join(" ", keys %SIG), "\n";

16.12 異なるプロセス間で変数を共有する

forkによって分離したプロセスの間や関連性のないプロセスの間で変数を共有したい。 使用しているOSにおいて、SysV IPCがサポートされている場合には、それを使用する。

16.11 名前付きパイプを使用して、プロセスをファイルのように見せる

ファイルに対するアクセスを全てプログラムによって捕捉したい。例えば、自分の~/.planファイルをランダムな引用を返すプログラムにする。 名前付きパイプを使用する。 シェルで名前付きパイプを作成する。 % mkfifo /path/to/named.pipe 読み取り側のコード…

16.10 関連プロセスの間で通信する

関連性のある2つのプロセスがあり、これらの間で通信を行う必要がある。ただし、open, system, およびバッククォートによって行える以上に厳密な制御を行いたい。 pipeを使用してから、forkを使用する my ($reader, $writer); pipe $reader, $writer; if (fo…

16.9 別のプログラムの入力、出力、およびエラーを制御する

コマンドの入力、出力、およびエラーの各ストリームを完全に制御したい。 細心の注意を払いながら、標準モジュールのOPC::Open3を使用する。

16.8 別のプログラムの入力と出力を制御する

別のプログラムに対して、書き込みと読み取りを同時に行いたい。 標準モジュールのIPC::Open2を使用する use IPC::Open2; $pid = open2(*README, *WRITEME, $program); print WRITEME "here's your input\n; close(WRITEME); $output = <README>; close(README); wai</readme>…

16.7 プログラムのSTDERRを読み取る

コマンドのSTDOUTとSTDERRをまとめて変数に代入する。 $output = `cmd 2>&1`; # バッククォートの場合 # または、 $pid = open(PH, "cmd 2>&1 |"); # パイプ付きのopenの場合 while (<PH>) { } # さらに読み取りを行う コマンドのSTDOUTを変数に代入し、STDERRを</ph>…

16.6 入力を前処理する

gzipやcompressによって圧縮されたファイルをgzipによって圧縮解除して、自動的に処理する。 @ARGV = map { /\.(gz|Z)$/ ? "gzip -dc $_ |" : $_ } @ARGV; while (<>) { # ... } ファイルを処理する前にURLを取得する @ARGV = map { m#^\w+://# ? "GET $_|" …

16.5 出力をフィルタ処理する

自分のプログラムの出力を後処理する必要があるが、そのための独立したプログラムを作成したくない。 暗黙的にforkが行われる形式でopenを使用して、自分のプログラムにフィルタを接続する。 head(100); while (<>) { print; } sub head { my $lines = shift…

16.4 別のプログラムと読み書きする

別のプログラムを実行し、そのプログラムの出力の読み取りや、そのプログラムへの入力の書き込みを行いたい。 プログラムから出力を読み取る場合 $pid = open $readme, "-|", "program", "arguments" or die; while(<$readme>) { # ... } close $readme; プ…

16.3 現在のプログラムを別のプログラムに置き換える

実行中のプログラムを別のプログラムに置き換えたい。その際、別のプログラムを実行する前にパラメータを検査し、初期環境を設定する。 組み込みのexec関数を使用する。execを呼び出すときにメタキャラクタが含まれている引数を1個だけ渡すと、シェルが使用…

16.2 別のプログラムを実行する

1つのプログラムから別のプログラムを実行し、それが終了した後で、元のプログラムの実行を継続したい。その際、別のプログラムでも元のプログラムと同じSTDIN, STDOUTを使用する。 引数として1個の文字列を渡してsystemを呼び出し、その文字列がシェルによ…

16.1 プログラムから出力を収集する

プログラムを実行したときに、その出力を収集して、変数に保存したい。 バッククォートを使用する $output = `program args`; # 1個の複数行文字列に出力を収集する @output = `program args`; # 各要素に1行ずつ割り当てた配列に出力を収集する パイプを使…

15.20 イメージにテキストを追加する

CPANのGDモジュールを使用する use GD; $image = GD::Image->new($FILENAME); $blue = $image->colorAllocate(0,0,255); $image->string(gdTinyFont, 10, 10, "Copyright Me, 2037", $blue); # $image->png()でファイルに書き込む

15.19 イメージの縮小版を作る

CPANのImage::Magickモジュールを使用する use Image::Matick; $image = Image::Magick->new(); $image->Read($ORIGINAL_FILENAME); $image->Resize(geometry => '120x90'); $image->Write($THUNBNAIL_FILENAME);

15.18 データをグラフ化する

数値データがあるので、それを棒グラフ、円グラフ、折れ線グラフなどで表したい。 CPANのGD::Graph::*モジュールを使用する use GD::Graph::lines; # bars, lines, points, pie $chart = GD::Graph::lines->new(480, 320); $chart->set( x_label => $X_AXIS_…

15.17 Windows Perl/TkでDOSシェルウィンドウを消去する

プログラムの最初の部分に、次のコードを追加する BEGIN { if ($^O eq 'MSWin32') { require Win32:Console; Win32::Console::Free(); } }

15.16 Tkのサイズ変更イベントに応答する

Confiureイベントを捕捉することによって、ユーザがウィンドウのサイズを変更するのを防ぐ use Tk; $main = MainWindow->new(); $main->bind('<Configure>' => Sub { $xe = $main->XEvent; $main->maxsize($xe->w, $xe->h); $main->minsize($xe->w, $xe->h); });</configure>

15.15 Tkでダイアログボックスを作成する

Tk::DialogBoxウィジェットを使用する use Tk::DialogBox; $dialog = $main->DialogBox ( -title => "Register This Program", -buttons => [ "Register" , "Cancel" ] ); # $dialog->Add()を使用して、ダイアログボックスにウィジェットを追加する # 後でダ…

15.14 Tkでメニューを表示する

TkのMenubuttonおよびFrameウィジェットを使用する。 use Tk; $main = MainWindow->new(); # メニューを表示するための水平方向の領域をウィンドウの最上部に作成する $menubar = $main ->Frame(-relief => "raised", -borderwidth => 2) ->pack(-anchor => …

15.13 Expectで他のプログラムを制御する

STDINとSTDOUTに端末を通じてアクセスすることが前提になっているフルスクリーンプログラムの対話型操作を自動化したい。 CPANのExpectモジュールを使用する。 use Expect; $command = Expect->spawn("program to run") or die; # プログラムの出力がSTDOUT…