是否有可能,我將能夠產生一個分離的守護進程的過程中,從一個CGI腳本 ,存儲在內存中讀取文本文件,然後重新訪問內存中的下一個CGI的執行,使用管道讀取數據?如何從CGI中分離進程,以便能夠從內存中存儲和讀取文件?
最會主辦的ISP,讓超脫流程?內存管道是否快速,並且易於在unix/linux系統上進行編碼/工作?
是否有解決方案,可以在不使用任何額外的CPAN模塊來完成?這是一個CGI過程,所以我想把它保持在最低限度。
是否有可能,我將能夠產生一個分離的守護進程的過程中,從一個CGI腳本 ,存儲在內存中讀取文本文件,然後重新訪問內存中的下一個CGI的執行,使用管道讀取數據?如何從CGI中分離進程,以便能夠從內存中存儲和讀取文件?
最會主辦的ISP,讓超脫流程?內存管道是否快速,並且易於在unix/linux系統上進行編碼/工作?
是否有解決方案,可以在不使用任何額外的CPAN模塊來完成?這是一個CGI過程,所以我想把它保持在最低限度。
假設你有一個簡單的resource.cgi
:
#! /usr/bin/perl
use warnings;
use strict;
use Reader;
use CGI qw/ :standard /;
print header("text/plain"),
"Contents:\n",
Reader::data,
"-" x 40, "\n";
它的輸出是
Content-Type: text/plain; charset=ISO-8859-1 Contents: This is a data file with some very interesting bits. ----------------------------------------
有趣的部分是在Reader.pm
,與熟悉的前瞻性樣板開始:
package Reader;
use warnings;
use strict;
use Fcntl qw/ :DEFAULT :flock :seek /;
use POSIX qw/ setsid /;
接下來它定義了集合點:
my $PIDFILE = "/tmp/reader.pid";
my $DATA = "/tmp/file.dat";
my $PIPE = "/tmp/reader.pipe";
該子import
is called as part of use Module
。如果守護進程已經在運行,那麼就沒有什麼可做的了。否則,我們分離守護進程並將其進程ID寫入$PIDFILE
。
sub import {
return unless my $fh = take_lock();
my $child = fork;
die "$0: fork: $!" unless defined $child;
if ($child) {
print $fh "$child\n" or die "$0: write $PIDFILE: $!";
close $fh or die "$0: close $PIDFILE: $!";
return;
}
# daemonize
close $fh;
chdir "/";
open STDIN, "<", "/dev/null";
open STDOUT, ">", "/dev/null";
open STDERR, ">", "/dev/null";
setsid;
open $fh, "<", $DATA or die;
undef $/;
my $data = <$fh>;
close $fh;
while (1) {
open my $fh, ">", $PIPE or die;
print $fh $data or die;
close $fh;
}
}
每個客戶端都需要等到輪到它鎖定$PIDFILE
。一旦我們有了鎖定,我們就會檢查確定的進程是否仍在運行,並在必要時創建命名管道。
sub take_lock {
sysopen my $fh, $PIDFILE, O_RDWR | O_CREAT or die "$0: open $PIDFILE: $!";
flock $fh => LOCK_EX or die "$0: flock $PIDFILE: $!";
my $pid = <$fh>;
if (defined $pid) {
chomp $pid;
if (kill 0 => $pid) {
close $fh;
return;
}
}
else {
die "$0: readline $PIDFILE: $!" if $!;
}
sysseek $fh, 0, SEEK_SET or die "$0: sysseek $PIDFILE: $!";
truncate $fh, 0 or die "$0: truncate $PIDFILE: $!";
unless (-p $PIPE) {
system("mknod", $PIPE, "p") == 0
or die "$0: mknod exited " . ($? >> 8);
}
$fh;
}
最後,閱讀管道很簡單:
sub data {
open my $fh, "<", $DATA or die "$0: open $DATA: $!";
local $/;
scalar <$fh>;
}
不要忘了從模塊返回真值:
1;
你會注意到,操作仍然在守護進程中失敗。爲了您的理智,您需要以某種方式記錄事件,而不是默默地窒息。
至於主機是否將允許長時間運行的進程,這將改變從供應商提供的,但即使你的守護進程是從時間殺死時間,上面的代碼將重新啓動它的需求。
如果你絕對需要的文件的內容存在於內存中,更簡單的解決辦法是建立一個RAM磁盤,並將它們存儲在那裏。那麼你不必對cgi-scripts做任何特殊的事情。
我要尋找一個便攜式解決方案...這在平均共享網絡託管服務器上有兩項工作: – 2010-01-27 15:56:03
@Jera - 我懷疑內存磁盤解決方案的可移植性不及「產生deamons和與管道通信」。 – Nifle 2010-01-27 16:26:40
怎麼這樣?我不是RAM磁盤專家,我如何輕鬆地在主機上設置它?所有主機都會允許嗎? – 2010-01-27 17:01:03
你爲什麼想這樣做?你想解決什麼問題?會像File::Map工作?它mmap文件,所以文件不在內存中,但他們的行爲就像他們。我在Memory-map files instead of slurping them中寫了一些關於這個的內容。
+1有趣的問題 – Nifle 2010-01-27 16:27:53