Как я могу отсоединить процесс от CGI, чтобы я мог хранить и читать файлы из памяти? - PullRequest
3 голосов
/ 27 января 2010

Возможно ли, что я смогу порождать отдельный демоноподобный процесс из сценария CGI который хранит прочитанные текстовые файлы в памяти, а затем повторно обращается к памяти при следующем выполнении cgi, считывая данные с помощью канала?

Будет ли большинство хостинг-провайдеров разрешать отдельные процессы? Являются ли каналы памяти быстрыми и легкими в кодировании / работе в системе Unix / Linux?

Есть ли решение, которое можно сделать без использования дополнительных модулей CPAN? Это процесс CGI, поэтому я хочу, чтобы он был минимальным.

Ответы [ 3 ]

1 голос
/ 27 января 2010

Если вы абсолютно хотите, чтобы содержимое файлов присутствовало в памяти, гораздо более простым решением было бы создать диск RAM и хранить их там. Тогда вам не нужно делать ничего особенного с cgi-скриптами.

0 голосов
/ 01 февраля 2010

Почему вы хотите это сделать? Какую проблему ты пытаешься решить? Будет ли работать что-то вроде File :: Map ? Это mmap файлы, поэтому файлы не находятся в памяти, но они действуют так, как они есть. Я написал немного об этом в файлах карты памяти, вместо того, чтобы хлестать их .

0 голосов
/ 27 января 2010

Скажем, у вас есть простое 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 вызывается как часть use Module. Если демон уже запущен, тогда делать нечего. В противном случае мы отключаем демон и записываем его идентификатор процесса в $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;

Вы заметите, что операции в демоне все еще могут быть неудачными. Для вашего здравого смысла, вам нужно как-то регистрировать события, а не задыхаться.

Относительно того, будут ли хосты разрешать долго выполняющиеся процессы, это будет зависеть от поставщика к поставщику, но даже если ваш демон время от времени отключается, приведенный выше код перезапустит его по требованию.

...