Perlの多重起動を禁止したい

このQ&Aのポイント
  • main_01.plというプログラムがすでに起動していた場合、main_01.plはすぐに終了するように組みたい
  • テキストファイルにロックをかけ、ロック中であるならばプログラムは処理を行わずすぐに終了することで多重起動を禁止したい
  • タイムアウト処理と排他処理を使用して、main_01.plの多重起動を制限する方法を考えています
回答を見る
  • ベストアンサー

Perlの多重起動を禁止したい

main_01.plというプログラムがあります。 これは10分毎にバッチファイルから起動の命令が下ります。ただしプログラムの処理によっては10分以上かかることがあります。 この時、main_01.pl がすでに起動していた場合、main_01.pl はすぐに exit; になるように組みたいのです。僕が考えた方法は、あるテキストファイルにロックをかけ、そのファイルがロック中であるならばプログラムは処理を行わずすぐに終了する、といった感じです。 =============================== # タイムアウト処理 my $timeout = 5; # 排他処理 my $lockfile="lock.txt"; # 多重起動停止 (ここに $lockfile が書き込めなかったらmain_01.plは別に起動していることになるので起動しない。) # 排他処理開始 open(LOCK,"$lockfile"); flock(LOCK,2); # 処理開始 eval { # タイムアウト local $SIG{ALRM} = sub { die "alarm\n" }; alarm( $timeout ); # プログラムスタート print "\n◆スタート\n\n"; sleep(4); # プログラム終了 print "\n◆終わりました。\n\n"; }; # タイムアウト処理 if ( $@ ) { # タイムアウト print "\nタイムアウトしました。TIMEOUT= $timeout \n"; } else { # タイムアウトせずに正常終了 print "\n正常終了しました。\n"; } # 排他処理終了 close(LOCK); exit;

  • Perl
  • 回答数2
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • mtaka2
  • ベストアンサー率73% (867/1179)
回答No.2

> # 排他処理開始 > open(LOCK,"$lockfile"); > flock(LOCK,2); このやりかただと、たぶん質問者さんの意図通りにはなりません。 プログラムの動作に10分以上かかって次のプログラムが起動した場合、 後から起動したプログラムは ・flock の呼び出しで、先に起動したプログラムが終了する(ロックが解除される)まで待つ ・その後で、処理を実行する ということになります。 重複実行はしませんが、起動した回数だけ必ず処理を実行しますので、 処理に毎回10分以上かかるような状況になった場合、どんどん未処理(終了待ち)のプロセスが増えていくことになります。 flock の処理は、 flock(LOCK,6) or die("実行中です"); とした方がいいでしょう。 flock は、第2引数が2(LOCK_EX)の場合は、あとから実行した方はロックが解除されるまで動作が停止しますが、 第2引数が6(LOCK_EX|LOCK_NB)の場合は、あとから実行した方がロック中だった場合は、0(エラー)を返します。 そのため、こうすることで、 「そのファイルがロック中であるならばプログラムは処理を行わずすぐに終了する」 という処理になります。

nakisan2011_12
質問者

お礼

ありがとうございます、とてもうまく行きました。flock第2引数、勉強になりました! 実際に試してみたところ、うまく多重起動を禁止することができました。

その他の回答 (1)

  • chie65535
  • ベストアンサー率43% (8526/19383)
回答No.1

open(LOCK,"$lockfile"); ↓ open(LOCK,"$lockfile") or die("多重実行禁止\n"); 「オープンに失敗する理由は、もう誰かがオープンしているからだ」と言うのが前提。 「もう誰かがオープンしている」ってのは「もう誰かが起動してる」ってのと一緒。

nakisan2011_12
質問者

お礼

返信ありがとうございます、参考にさせて頂きます!

関連するQ&A

  • perlプログラム内で中間ファイルを利用するには

    perlプログラムについて 処理1 の アウトプットデータを用いて、処理2を行うというのを1つのperlのプログラム内で実装したいと考えています。 処理1のアウトプットファイルの書き出しに時間がかかり 処理2が先に動き、ファイル読み込みできずに終わってしまいます。 処理1のアウトプットファイル書き出しが終了を待ってから、処理2を実施したいのですが、 どのように記載すればよいのでしょうか? 例) perl program.pl AAA > BBB program.pl 内 open(OUT1,"> program1_work"); open(ARG,$ARGV[0]); while(<ARG>){ 処理1 print OUT1 "XXXXXX"; } close(ARG); open(ARG1,OUT1); while(<ARG1>){ 処理2 print "XXXXXX"; } close(ARG1);

  • Perl 一定時間後にプログラムを実行

    恐れ入ります。 一定時間後にプログラムを実行したいのですが、sleepですと、すべてのプログラムが停止してしまいます。 プログラムの一部を、一定時間後に実行するにはどうしたらよいのか苦戦しています。 $SIG{ALRM} = \&timeout; eval { alarm 5; print qq! 再生中!; alarm 0; }; alarm 0; sub timeout{ print qq!5秒経ちました!; } としてみましたが、うまくいきません。再生中を表示しながら、5秒後に5秒経ちましたと、 再生中を表示しながら表示したいのですが、どのようにしたら良いでしょうか。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • flockの挙動がおかしい。。。

    おそれいります。 親プロセスから子プロセスを複数呼び 子プロセスが全て終わった後に次の手順に移行する。。。という処理をflockを使って作っているのですが、 うまくいきません。 下の「main.pl」を実行すると、「lock.pl」を10回呼び出して、 すべて終了したら「OK」と表示したいです。 lockというファイルを全部のプロセスで共有して、 子の全部の処理が終わった時点で、mailにロックが移る。。。という動きを想定したのですが、 なぜか、数回実行しているとMAIN LOCK(1) が最後に発動しているにもかかわらず、 子プロセスが終了していないのに「OK」の表示を出してしまいます。 flockは順番を守らないのでしょうか・・・・????? どのようにしたらうまく動くでしょうか。。。。 ==> main.pl <== #!/usr/bin/perl use Fcntl ':flock'; for (1..10){ system("./lock.pl $_ &"); } sleep 5; # 子プロセスが開始するまで待つ print qq("MAIN LOCK\n"); # ... (1) open LC,"+<lock" or die; flock LC,LOCK_EX; sleep 1; print qq("OK\n"); ==> lock.pl <== #!/usr/bin/perl use Fcntl ':flock'; print qq(lock $ARGV[0]\n!); # ... (2) open LC,"+<lock" or die; flock LC,LOCK_EX; sleep $ARGV[0]; print qq(release $ARGV[0]!\n);

    • ベストアンサー
    • Perl
  • Perlで use strict して our変数

    Perl 初心者です。初めて質問します。 test_sub.pl で宣言した変数を test_main.pl から参照したくて悩んでいます。 環境 : WindowsXP / ActivePerl 5.14.2 -------------------- * test_sub.pl -------------------- #!/usr/bin/perl use strict; our $hoge = 'HOGE'; 1; -------------------- * test_main.pl -------------------- #!/usr/bin/perl use strict; require 'test_sub.pl'; print "Content-type: text/html\n\n"; print $hoge; -------------------- これを実行すると、 Global symbol "$hoge" requires explicit package name at C:/public_html/cgi-bin/test_main.pl line 7.\r というエラーが出ます。 require する前に、test_main.pl のほうで our($hoge); と宣言したり 参照する際に print $main::hoge; とパッケージを指定したりすればいけるのですが、 これらをしないとできないものなのでしょうか。 use strict; を書かなければ最初のソースでも動くのですが use strict は書きたい… 継承のようなことをしたいのです。 ちなみに以下試してみたソースです。 -------------------- * test_main.pl -------------------- #!/usr/bin/perl ######################################## # NG use strict; require 'test_sub.pl'; print "Content-type: text/html\n\n"; print $hoge; ######################################## # OK our変数を宣言しておくといける =pod use strict; our ($hoge); require 'test_sub.pl'; print "Content-type: text/html\n\n"; print $hoge; =cut ######################################## # OK 参照する際にパッケージ名を指定すればいける =pod use strict; require 'test_sub.pl'; print "Content-type: text/html\n\n"; print $main::hoge; =cut ######################################## ######################################## # NG =pod use strict; use base qw(test_sub); print "Content-type: text/html\n\n"; print $hoge; =cut ######################################## -------------------- * test_sub.pm -------------------- #!/usr/bin/perl package test_sub; use strict; our $hoge = 'HOGE'; 1; -------------------- NG パタンはどちらも Global symbol "$hoge" requires explicit package name のエラーとなります。 もしご存じの方がいらっしゃいましたら教えてください。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • 排他的ロック

    もともとMicrosoft SQLで使用していたアプリケーションを多少改造し、MySQLにしようと思っています。 データ型もコマンドもすべて一致しているし、と思って構築をしていたら一つ見落としていたことがありました。 排他的ロックです。 MySQLで排他的ロックってどうやってやればいいのでしょう? ちなみに今はこのコマンドをどうすればMySQLで動くのか迷い中です。 SET LOCK_TIMEOUT 1000//ロックのタイムアウトを設定 SELECT * FROM # WITH(XLOCK) WHERE $//排他的ロック

    • ベストアンサー
    • MySQL
  • Perlからメール送信で文字化け

    Perl5.8からsendmailを使ってメール送信しています。 髙や﨑が入ると文字化けします。文字化けしないようにする方法を教えてください。 #!/usr/bin/perl require 'jcode.pl'; require 'mimew.pl'; $sendmail = '/usr/lib/sendmail'; print"Content-type: text/html\n\n test\n"; if (!(open(OUT,"| $sendmail -t -i -f xxxx\@hogehoge.co.jp"))) { ; } print OUT "To: xxxx\@hogehoge.co.jp\n"; print OUT "From: xxxx\@hogehoge.co.jp\n"; print OUT "Reply-To: xxxx\@hogehoge.co.jp\n"; $subject = "サブジェクト 髙﨑"; $subject = &mimeencode($mail_subject); print OUT "Subject: $mail_subject\n"; print OUT "Mime-version: 1.0\n"; print OUT "Content-Type: text/plain\; charset=\"ISO-2022-JP\"\n"; print OUT "Content-Transfer-Encoding: 7bit\n\n"; $honbun = "メール本文 髙﨑"; &jcode'convert(*honbun, 'jis'); print OUT "$honbun\n"; close(OUT);

    • ベストアンサー
    • Perl
  • 極めて初歩的な質問ですみません

    PERLの勉強をつい最近はじめました。 参考にしている本のどこを探してもみつからなかったので、質問させていただきます。 sub lock{ $c = 0; while (-f $lockfile) { $c++; if( $c >= 5 ){ print 'BUSY 少し時間を置いてもう一度登録してください。',"\n"; exit; } sleep(1); } open(LOCK,">$lockfile"); close(LOCK); というサブルーチンがありまして、分からないのはwhile構文の条件の記述です。 (-f $lockfile) とは、-fとは、どういう意味なのでしょうか。 if(! -f $mail01 ){ open(OUT,">$mail01"); close(OUT); というところにもありました。 どうぞ教えてやってください。超初心者なので、どうぞよろしくお願いします。

    • ベストアンサー
    • Perl
  • Perl のプログラム二重起動について

    Perlでの二重起動?についての疑問があるので質問いたします。 ============================ (状況) 1)Aというプログラムが存在し、そのAというプログラムはタスクスケジューラーによって10分毎に起動しています。 2)Aプログラムは全体の処理が終わるまでに通常5分の時間がかかります。処理が終わればexitで終わります。 (ちなみにAプログラムはファイル書き込みなどの排他処理が必要なフローはありません) ============================ というのをふまえ、疑問点が出てきたので質問します。 例えば、あるイレギュラーな出来事が起こり、Aプログラムの処理時間が15分に伸びてしまいました。 しかし、タスクスケジューラーは10分間隔でAプログラムを起動させます。 このとき、オーバーした5分間だけAプログラムは二重に起動することになります。           0   5    10 15 20 最初のAプログラム ===============  次のAプログラム           ========== この場合、windows7上のActivePerlは、どんな動きをするのでしょうか? 予約みたいな形になり、最初のAプログラムが終わってから次のAプログラムが動くのでしょうか? それとも二重起動するのでしょうか?

    • ベストアンサー
    • Perl
  • wshで起動したコマンドををタイムアウト終了させる

    たとえば以下のようなバッチファイルとvbsファイルを用意して test.batを実行した場合 ftpのダウンロード処理が完了した後 ダウンロードしたファイルを処理したいのです 以下のようにすれば処理待ちになるのでそこは 実現できるのですが ftp.exeがなんらかの原因で稀に終了しない事があるので そうなるといつまでも処理待ちになってしまうので タイムアウトさせたいのです ftpコマンドをあえてquitしないで(終了しない状態を再現させる) WScript.timeout=10 をいれてみて試してみたのですが タイムアウトが有効になりません ftpのプロセスは最悪残ってしまってもかまわないのですが 起動をかけたバッチファイルのほうは永遠待ち状態ではなく 一定時間応答がなければ次の処理に移したいのです 何かいいタイムアウトの実装方法はないでしょうか? アドバイスお願い致します test.bat cscript test.vbs ←ここでftp.exeが終了しないと永遠待ち状態になってしまう rem ftpが完了後に行いたい処理 exit test.vbs WScript.timeout=10 CreateObject("WScript.Shell").Run "CMD.exe /C ftp -s:c:\cmd.txt", 1, True

  • バッチファイルで多重起動を防ぐ

    とあるプログラムを定期的に バッチファイルで起動させています。 プログラムは処理が完了すると自動で終了させています。 ただ、時間の間隔はさほど大きくないため、 先だっての起動プログラムが動いているときに 次のタスクにて2重でプログラムが動き出す可能性が出てきました。 バッチファイル上で、その名称のプログラムが動いていないか確認し、 動いていた場合は起動しないようにできないでしょうか?