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


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

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

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

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

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

回答の条件
  • URL必須
  • 1人1回まで
  • 登録:
  • 終了:2006/10/22 16:07:49
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:furutanian No.2

回答回数112ベストアンサー獲得回数14

ポイント40pt

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

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

id:highschool

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

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

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

2006/10/17 17:48:59

その他の回答2件)

id:b-wind No.1

回答回数3344ベストアンサー獲得回数440

ポイント14pt

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

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


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

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

id:highschool

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

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

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

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

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

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

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

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

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

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

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

2006/10/16 19:37:19
id:furutanian No.2

回答回数112ベストアンサー獲得回数14ここでベストアンサー

ポイント40pt

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

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

id:highschool

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

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

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

2006/10/17 17:48:59
id:tombe No.3

回答回数38ベストアンサー獲得回数7

ポイント26pt

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;

id:highschool

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

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

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

(追記)

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

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

快調に動作しています。

2006/10/22 16:06:16

コメントはまだありません

この質問への反応(ブックマークコメント)

トラックバック

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません