CGI-BBS > CGI > Perl > プロセス番号の意味


カレッヂ
カレッヂ


質問者 ひろ  投稿日 2/15(木) 19:27:38
初めて質問させていただきます。
perlを始めて一ヶ月経っていない素人ですので宜しくお願い致します。

ユニークなファイルを作成したいので
プロセス番号($$)を利用したファイル名をつけたいと考えています。

Aというスクリプトでファイルを作成し、
BというスクリプトでAで作成したファイルを読み込みたいのですが、
Bにて、Aで作成したファイルを特定して読み込むのは
可能なのでしょうか?

また、そもそもプロセス番号はAとBで違うものなのですか?
Aのスクリプトの途中でCへ処理が移動したあと、またAへ処理が戻った時、
Aの最初で作成したプロセス番号と、処理が戻ったあとのプロセス番号は
同じなのでしょうか?

上手く書けなくて申し訳ありませんが、お願い致します。

回答者 しあわせのツボ  [削除]  投稿日 2/15(木) 20:22:13
プロセス番号はスクリプトが起動するたびごとにuniqueな値が付番され、動作している間(途中でidleやsleepしてもよい)同じ値を維持し、終了時に開放されます。
AとBを別々に起動するのなら番号は異なりますが、AにBをrequireしてしまえば同じ番号になります。Cの終了をAが待つようにすればAの番号は前後で同一です。同じAでも次回は別の番号になります。

もしAが作成したファイルをBで読みたいのなら、Bは何らかの方法でAが作成したファイル名を取得しなければなりません。
ディレクトリ内のファイルリストを取得したり、Aが作成時にログを残しておいてBがそれを参照したりといった方法が考えられます。
質問者 ひろ  [削除]  投稿日 2/15(木) 20:58:58
「しあわせのツボ」さん、私の拙い言葉に十分な回答をありがとうございます。
おかげさまでプロセス番号について理解が出来ました。

そこでさらに質問で申し訳ないのですが。
Aが作成したファイルをBで読みたい場合、
BはAが作成したファイル名を取得しなければならないのですが。
Aがファイルを作成中、ロックファイルを用いて排他をかけています。
Aの処理終了後、3つほどのスクリプトやHTMLを経て
Bにて読み込みを行いたいのです。

AからBにたどり着く間に、新たにAにアクセスがあり
新たなファイルが作成される事が考えられる状況です。
この状況でBでファイルを特定する方法を、もう少し具体的に
教えていただけるとありがたいです。

回答者 さくら  [削除]  投稿日 2/16(金) 02:46:30
情報の牽引にはいくつかの方法が有ります。
クエリーを使う、formのhidden属性を使う、ユニークなデータファイルを使う、
データをメモリしておく為のサーバを書いてしまう。
しかし、今回の場合、どれもしっくりきません。
データファイルを違うスクリプトから読むわけですから、データファイルはだめですね、
途中でHTMLを読むようですが、動的に生成するHTMLならクエリーやhiddenを使えるでしょうが、静的なHTMLならここで牽引できなくなります。
サーバまで書くには、技術も手間も要るでしょう。
でも解決策はあります。
プロセスIDはやめて、IPアドレスにしたらどうでしょうか?
同じユーザーがAスクリプトからBスクリプトへとたどりつくのでしょう?
それなら、接続が切断されない限り、IPアドレスはユニークなものです。
回答者 谷口  [削除]  投稿日 2/16(金) 12:12:31
プロセス番号はその瞬間に実行中のプロセスについてはユニークなのですが、
無限の桁数を取れないため、ある程度時間が経つと同じ番号が現れます。
プロセス番号に時刻もつけるとさらにユニーク性が高くなると思います。
IPアドレスでもユニークなファイル名が付けられるというさくらさんのご意見、
私は無理ではないかと思いますが、いかがでしょうか?

Aが実行されるたびにユニークなファイルが作製されるわけですから、
一連の操作でAにより作製されたファイルをBで読むためには、
皆さんの仰るように、Bにファイル名を渡してあげる必要があります。
具体的な処理の流れが分かると、具体的なアドバイスが頂けるのでは
ないでしょうか?

また、この処理の流れは、「BではAでファイル作成後にファイルを読む」
「Aではユニークな名前のファイルが作成される」となっているので、
ロックファイルを用いて排他をかける必要はないと思います。
質問者 ひろ  [削除]  投稿日 2/16(金) 14:14:55
さくらさん、谷口さん、ご返答をありがとうございます。

まずさくらさんの書かれた内容についてです。
HTMLは静的なものと動的なものが混在しています。
静的なHTMLの場合は、やはり牽引は無理なのですね・・・
IPアドレスならば確かにユニークだな、と思い、クライアントのIPアドレスの
取り方を探して「環境変数」を使うのかなと思っていたところ
谷口さんのご返答を頂きました。

そこで谷口さんのおっしゃる「無理ではないか?」という理由はどういった事から
なのでしょうか。
また、谷口さんのご指摘通り具体的な処理の流れを書いてみます。
ちょっと長いですが。

現在作っているのは、ネットの通信販売においてクレジットカードを利用する場合の処理です。
一部カード会社から提供されたCGIパッケージ部分も流れの中に組み込まれています。
今は下記の状態で運用しています。

1.注文フォームへ入力→submitでCGI(A)へ
2.CGI(A)でロックファイルを生成して排他してから、フォームからのデータを
  TXTファイルへ書き出し(ファイルは単一)。さらに確認画面のHTMLを動的に生成表示。
  このHTML画面でhiddenにてパッケージ(a)に必要なデータをsubmit
3.パッケージ(a)にて初期情報のチェックを行い静的なHTMLファイルを呼び出し。
4.静的なHTMLにおいてカード番号と有効期限を入力、submitしてパッケージ(b)へ
5.パッケージ(b)でカード会社とのオーソリチェックを行いOKであればCGI(B)へ
  NGならばエラー表示をして、ロックファイル等を削除して終了。
6.CGI(B)では2で書き出したファイルを読み込み、カード会社からの承認番号等も付加して
  sendmailにてメールサーバーへ送信。
  ロックファイルを削除して処理終了。

この流れで運用していると、2で生成されたロックファイルが6になってから削除される
為に、ユーザーの動きによってはサーバー上に残ってしまい次のユーザーが
注文出来なくなってしまいます。
現状ではロックファイルの生成時間が10分以上前なら
削除するルーチンを組み込んでいますが・・・

そこでロックファイルの生成と削除を2の中で行いファイルを作成中だけ排他をかけ、
6で読み込む時は2で作成されたファイルを特定して読み込めないだろうか、と
愚考している最中です。
データファイルを単一のもので扱っている為、一連の処理が終わるまで
ロックファイルで排他をかける必要があると思うのですが、
このままでは上記の理由から現実的ではありませんよね。

良きアドバイスをいただきたいと思います。
質問者 ひろ  [削除]  投稿日 2/16(金) 18:56:11
ちょっと内容の変更・追加です。

・書出ししているデータファイル名は固定してスクリプト内にて記述されています。
 同様にCGI(B)で呼び出している際も同じファイル名を固定で読み込みしています。
 そのためにファイル内容の変更を恐れて排他処理を行っています。
・データファイルには注文フォームで入力された項目のみが上書きモードで書き込まれ、
 また2.の確認画面HTML以降の処理で渡されている項目は、「金額」という項目以外
 フォームで入力された項目はありません。オーソリでOKになるまで、ユーザーのデータを
 ファイルにセーブしておく形です。

CGI(A)にてユニークなファイルを作成し、CGI(B)にてそのファイルを
読み込む事が出来れば、排他処理を行う必要がなくなる事になりますが。
3.で呼び出している静的HTMLを動的HTMLとして生成出来れば、CGI(A)で作成した
ファイル名をCGI(B)まで持っていけるかと思いますが、
それには「パッケージ(a)」を変更しなくてはならず、パッケージ部分の理解が足らずに
変更するのが怖い状況です。

といった事から、残る問題は
(1)ユニークなファイル名の付け方
(2)それをCGI(B)まで持っていく方法
(3)「CGIパッケージ」部分を変更出来るかどうか
でしょうか。
(3)に関しては私自身の責任ですので頑張ってみます。
最後に(1)に関してご教授をいただきたいと思います。

最終的なイメージは
CGI(A)でユニークな名前の書き出し用ファイルを作成し、同時に
ファイルに書き込みも行う。
CGI(B)では、CGI(A)で作成されたファイル名を何らかの方法で取得し、
その内容を読む。このような処理になります。

質問者 ひろ  [削除]  投稿日 2/16(金) 19:53:27
すみませんが、ファイル名のつけ方は下記で間違いなくて
ユニークになっているでしょうか?

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
if ($month < 10) { $month = "0$month"; }
if ($mday < 10)  { $mday  = "0$mday";  }
if ($sec < 10)   { $sec   = "0$sec";   }
if ($min < 10)   { $min   = "0$min";   }
if ($hour < 10)  { $hour  = "0$hour";  }
$month = ($mon + 1);

$filename = $year . $month . $mday . $hour . $min . $sec . $$ . ".txt";

だんだん質問内容が変化してきていますが、
スレッドを変更して新規に書いた方がいいのでしょうか。こういう場合?

回答者 さくら  [削除]  投稿日 2/17(土) 02:09:06
一応、参考意見として私が分かる範囲で解答します。

まず、パッケージの内容が解らないので、なんとも言えませんが、
情報の牽引からお話します。
完全なる静的ページを通過させる場合は、まず、無理でしょう、
ただ、既存のhtmlファイルにssiのようなもので、コメントタグの中にコードを入れておき、
cgiでそのファイルをスキャンしながらべつのファイルに書き出し、そのコードを見つけたら、
任意の情報に置き換えるという方法が考えられます。
例えば、クエリー情報を使う場合、cgiを呼び出すリンクの部分ですが、
<A HREF="http://domain/script.cgi?<!--#filename--> >
このコメントの部分を本物のfilenameに置き換えると、そのユーザー専用のhtmlファイルができます。そして、ここへ Locationを使ってリダイレクトします。
このような方法は、ベースのhtmlはあるものの、完全な静的ページとは言えないでしょう。

上記は余談になりました。今回のご相談には使えないでしょうね。

それでは本題です。
パッケージにオプションで任意のデータを送る、取り出す事が出きれば、牽引できる事になります。
cgi(A)から動的ページを作成
ここでは問題無く牽引できます。
パッケージ(a) に情報を送信する必要がある。
パッケージ(a)から静的htmlを呼び出すようですが、これをcgiを呼ぶように変更する。
パッケージ(a)でLocation ヘッダーを使っているなら、このアドレスを変更すれば良い。
そして、情報を取り出す。
パッケージ(b)に情報を送信する必要がある。
cgi(B)で情報を取り出す。

クエリー情報で牽引するなら、全てのcgi呼び出しに、?クエリーを追加する事、
呼び出されたcgiの全てで、$ENV{'QUERY_STRING'} を使ってクエリーを取り出す事を
追加すれば、一応牽引できる事になる。
今現在のスクリプトが、クエリー情報を使っていれば、クエリーデータをパースして格納する
コードを変更する必要が有るかもしれない。
リクエストメソッドにGETを使用している場合は、入力データによってオーバーライトされてしまうので、この方法は使えない。
又、最初に書いたように、オプションのデータを使えるなら、FORM の HIDDEN を使っても良いでしょう。

谷口さんからご指摘のあったIPアドレスの件は、理由が書かれていませんが、
私の想像するところ、IPアドレスの共有の事を言われているのではないでしょうか?
(私はIPアドレスの共有について詳しくないので、詳しい方がいればフォローしていただきたい。)
確かにこのようなシステムの下位では、プライベートマシンを特定する事はできない。
(NATと言うのはこう言うシステムだろうか????)

それでもなお、私はIPアドレスを使うことをお奨めする。
当然、cgi(a)でファイルを作成する際には、現在あるファイル名をスキャンして、同名のIPアドレス(ファイル名)が有った場合は、sleepをまじえて、何度かトライして、だめなら、"しばらく経ってから。。。。"というメッセージを出して終了する。
今現在、同時に6件しか処理できないのであれば、これでも充分能率はupするはずだと思う。
10分間でタイムアウトすることを考えると、貴方のサイトの性質や、アクセス数にもよるが、一日にこのスクリプトを起動するのが、数十件から数百件であれば、例外が発生する確立は、
かなり低いと思うのですが、どうでしょうか?

この方法なら、パッケージを変更する必要は無いし、cgi(a)cgi(b)でIPアドレスを取得すれば良いので簡単だ。
IPアドレスの取得は
$ip = $ENV{'REMOTE_ADDR'};
これで、$ip にIPアドレスが入った。

-----------------
それと一応時間の取得について書いときます。
localtime は必要有りません。
$time = time ;
これで、$timeには1970年1月1日からの秒数が入った。
一秒間に同時アクセスが無ければ、これでも充分だが、
これにプロセスIDをつければ、谷口さんの言う通りユニーク度は抜群ですね。

最後に、がんばって下さい!!

回答者 谷口  [削除]  投稿日 2/18(日) 00:09:43
>谷口さんからご指摘のあったIPアドレスの件は、理由が書かれていませんが、

理由がないのは自信がない現われなのですが(笑)、借りに同時刻に同じIPアドレスから
アクセスがないとしても、別の時刻にそのIPアドレスからのアクセスがあることが考えら
れるため、ユニークにはならないと判断しました。
どのような仕様のシステムか詳細にはわかりませんが、1ファイル1データが前提となる
ような仕様の場合、書きこみの際にファイルロックを行えば書き込みが重なることによる
ファイルの破壊は防げますが、データそのものが書き換わってしまうためその方法を採用
することは出来ないと思われます。
なるべくユニーク性が守られるものと言う考えから発言させて頂きました。
回答者 さくら  [削除]  投稿日 2/18(日) 00:30:04
>理由がないのは自信がない現われなのですが(笑)、借りに同時刻に同じIPアドレスから
>アクセスがないとしても、別の時刻にそのIPアドレスからのアクセスがあることが考えら
>れるため、ユニークにはならないと判断しました。

ご解答有難う御座いました。
作成するファイルが、ログファイルかテンポラリーファイルかによって異なりますね。
ログファイルなら、確かにIPアドレスではダメですね。
テンポラリーファイルなら、たぶん、CGI(b)でこのファイルは削除されるはずなので、
IPアドレスで良いでしょう。


質問者 ひろ  [削除]  投稿日 2/19(月) 11:55:17
さくらさん、谷口さん、ご回答をありがとうございました。

さくらさん、申し訳ありません。
せっかく書いて頂いたのに私は「クエリー」が分からなくて
半分理解出来ませんでした。この部分はもう少し勉強して理解に努めます。
当方のサイトのアクセス数、スクリプト起動数ですが
残念ながらさくらさんの書かれたくらいですので問題ないのですね。
IPアドレスの取り方も教えて頂き本当にありがとうございます。

谷口さん、メールでもお世話になりました。
私の言葉がまたも足らなかったのですが、ファイルのユニーク性に
こだわっていた割にこのファイルはテンポラリファイル扱いなんです。(^^;
ファイルの内容は、メールで受け取ったあとでDBに入力されていくので
ファイル書出しと読込みの2箇所においてユニークが発揮されればいいのです。

お二方に。
パッケージに「CONFIDENTIAL」の刻印があるのでスクリプトを載せてもいいものか
判断がつかず、なんともはっきりしない部分があったと思いますが
申し訳ありませんでした。

載せるとしてもどの部分を載せればいいのかが判断出来ていないのですが、
少なくともlocationの文字は使用されていません。

皆さんのおかげで、IPアドレスとプロセスIDなど
いくつかの事を学ぶ事が出来ました。
ファイル名にどちらを用いるかは、パッケージ部分をどう変更出来るかによって
どちらも用いる事が出来ますね。
ほぼ頭の中で仕様が見えてきましたので
教えていただいた事を活かして頑張って考えてみます。

初心者の上、周りの同僚は知っている人が全くいない状況なので
これからも他の質問でお世話になると思いますが、
また見かけましたらご助力をお願い致します。
重ねてありがとうございました。

このページは終了したので返信(回答)は書きこめません

Web裏技