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

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

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

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


person Jeremy Gwa    schedule 27.01.2010    source источник


Ответы (3)


Скажем, у вас есть простой 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;

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

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

person Greg Bacon    schedule 27.01.2010

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

person hlovdal    schedule 27.01.2010
comment
Я ищу портативное решение... у него есть две работы на средних общих серверах веб-хостинга. - person Jeremy Gwa; 27.01.2010
comment
@Jera Jera - я сомневаюсь, что решение с оперативным диском будет менее переносимым, чем spawning deamons and communicating with pipes. - person Nifle; 27.01.2010
comment
как же так? Я не эксперт по RAM-диску, как мне легко настроить это на моем хосте? все хосты разрешат это? - person Jeremy Gwa; 27.01.2010

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

person brian d foy    schedule 01.02.2010