人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

[Perl]プロセス間での通信

Perl1:$SIG{'USR1'} = sub {動かしたいスクリプト};sleep(待つ時間);
Perl2:kill 'USR1',プロセス番号

今はこのようにして、Perl2がPerl1に「動作していいよ!」というように連絡しているのですが・・・、Speedyperlなどの下では、プロセスを1つ1つ作らないため、この方法は上手く動きません。

なんとかして上記のような通信を動かす方法を教えてください。

ただし、$SIGは使用しない方法でお願いします。
また、Speedyperl以外を使用したり、Speedyperlの起動プロセス数MAXを1にしたりする方法は除きます。

具体的な方法でよろしくお願いします。

●質問者: highschool
●カテゴリ:コンピュータ インターネット
✍キーワード:Max Perl SIG sub スクリプト
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● b-wind
●14ポイント

Speedyperl というのは SpeedyCGI のことでしょうか?

SIGNAL ではダメな理由がよく分からなかったのですが。


TCP/IP や Unix-Domain ソケット、SysV IPC を使ってみてはいかがでしょうか?

http://www.kt.rim.or.jp/~kbk/perl5.005/perlipc.html

◎質問者からの返答

あ、SpeedyCGIですね。うーん、表現力がないので上手く説明できないのですが(苦笑)

私の使用目的上、1つのプロセスで複数のスクリプトを動作させるとダメなんです・・・。抽象的ですみません。

説明が足りなかったので追記します。

PerlスクリプトA・・・sleep(60);等で待機

PerlスクリプトB・・・PerlスクリプトAに連絡

PerlスクリプトA・・・連絡を受けたので、すぐにsleepをやめてスクリプトを全て実行する

このようなことをしたいのです。

どうやってその連絡をするか・・・・・。

ファイルを用意して、そのファイルが(Bによって)書き換えられたら(Aの待機しているスクリプトを)実行のような形でもいいのですが、そのためにはsleep(1);を繰り返したりでファイルを監視する必要があります。

この場合ですと、最大1秒のタイムラグができます。

なるべく(CPU負荷の低い方法で)リアルタイムを実現したいのです。


2 ● furutanian
●40ポイント ベストアンサー

横から失礼。既存のスクリプトをちょっとイジって実現してみました。

UDPを使ってみましたが、SpeedyCGIで動作確認してないですけど、動きますかね?

・スクリプトA

 1 #!/usr/bin/perl
 2
 3 use IO::Socket;
 4 use IO::Select;
 5
 6 $udpSock = IO::Socket::INET->new(
 7 Proto => "udp",
 8 LocalPort => 32999,
 9 );
 10
 11 $udpSel = IO::Select->new;
 12 $udpSel->add($udpSock);
 13
 14 if(IO::Select->select($udpSel, undef, undef, 60)) { # sleep 60
 15 print "get " . <$udpSock>;
 16 } else {
 17 print "timeout...\n";
 18 }

・スクリプトB

 1 #!/usr/bin/perl
 2
 3 use IO::Socket;
 4
 5 my $udpSock = IO::Socket::INET->new(
 6 Proto => "udp",
 7 PeerAddr => "localhost",
 8 PeerPort => 32999,
 9 );
 10
 11 print $udpSock "Trigger\n"; # 連絡

http://x68000.q-e-d.net/~68user/net/udp-1.html

◎質問者からの返答

おおおおおおおおおおおおお

わざわざスクリプトまで書いていただいてすみません><

素晴らしい!一度動かしてみたいとおもいます。


3 ● tombe
●26ポイント

1)共有メモリ、セマフォを使う

http://www.nkozawa.com/html/TipsProgPerl.html


2)スレッドを使う


3)TCP/IPで通信する

(例)

------------------------------

【Perl1(サーバー)側】

use IO::Socket::INET;

my $PORT = 10000; # 任意の空いているポート番号

my $server = IO::Socket::INET->new(LocalPort => $PORT,

Type => SOCK_STREAM,Reuse -> 1,

Listen => 1); # 接続最大数=1

$server->accept();

close($server);

### '動作していいよ!'サインを受け取った後のPerl1の処理

------------------------------

【Perl2(クライアント)側】

use IO::Socket::INET;

#### '動作していいよ!'サインを出すまでのPerl2の処理

my $PORT = 10000; # Perl1に合わせる

my $socket = IO::Socket::INET->new(@localhost:$PORT");

print $socket '動作していいよ!';

close($socket);

------------------------------

ただしこの方法は、Perl1:Perl2のペアが複数発生する場合、衝突しない複数ポート番号の管理が必要となります。


3)親子プロセスを使う

(例)

if (fork())

{

wait;

#### '動作していいよ!'サインを受け取った後のPerl1の処理

} else {

#### '動作していいよ!'サインを出すまでのPerl2の処理

}

exit;

◎質問者からの返答

はてなの人が優しすぎて感動しています。

本当にありがとうございます。

いったん既存のスクリプトに導入してみて、動かしてみますね。

(追記)

みなさんありがとうございました!

2番さんの回答を既存のスクリプトに導入しました。

快調に動作しています。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ