Perl守护进程不会经历整个循环

时间:2017-06-20 20:22:22

标签: linux perl daemon

我试图在Perl中创建一个非常简单的服务器程序。

该程序本身可用作图书馆目录,为用户提供按标题或作者搜索图书,借阅或归还图书的选项。书籍清单在单独的文件中提供。

基本上,它应该接受来自"请求"的请求(文件)。文件夹,处理它们,然后在"答案"中给出答案(也包括文件)。夹。该过程结束后,它会删除旧请求并重复该过程(客户端在接受答案后将删除答案)。

它意味着作为守护进程运行,但由于某种原因,只有负责删除请求文件的循环才能在后台运行 - 请求不会被处理成答案,而只是被删除。每当出现新请求时,它几乎立即被删除。

我正在学习使用守护进程并试图模仿this thread中的内容。

#!/usr/bin/perl
use warnings;
use strict;
use Proc::Daemon;

#FUNCTIONS DEFINTIONS
sub FindAuthor 
{
#try to find book by this author in the catalogue
}


sub FindTitle
{
#try to find book with this title in the catalogue
}


sub CheckIfCanBeReturned
{
#check if the book is borrowed and by whom
}

#attempt at daemonization
Proc::Daemon::Init;

my $continueWork = 1;
$SIG{TERM} = sub { $continueWork = 0 };

while ( $continueWork )
{

    sleep(2);
    my @RequestFilesArray = `ls /home/Ex5/Requests`;

    #list all requests currently in the Request folder
    for ( my $b = 0; $b < @RequestFilesArray; $b++)
    {
        my $cut = `printf "$RequestFilesArray[$b]" | wc -m`;
        $cut = $cut - 1;
        $RequestFilesArray[$b] = substr $RequestFilesArray[$b], 0, $cut;    
    }


    #the requests are formatted in such way,
    #that the first 2 letters indicate what the client wants to be done
    #and the rest is taken parameters used in the processing

    for (my $i = 0; $i < @RequestFilesArray; $i++)
    {
        my $UserRequest = `tail -1 Requests/$RequestFilesArray[$i]`;
            my $fix = `printf "$UserRequest" | wc -m`;
            $fix = $fix - 1;
            $UserRequest = substr $UserRequest, 0, $fix;

        my $RequestType = substr $UserRequest, 0, 2;
        my $RequestedValue = substr $UserRequest, 3;

        my $RequestNumber = $i;

        if ($RequestType eq "fa")
        {
            #FIND BY AUTHOR
            my @results = FindAuthor ($RequestedValue);

            my $filename = "/home/Ex5/Answers/" . $RequestFilesArray[$RequestNumber];

            open (my $answerFile, '>', $filename) or die "$!";

            for (my $a = 0; $a < @results; $a++)
            {
                print $answerFile $results[$a],"\n";
            }
            close $answerFile;

        }
        elsif ($RequestType eq "ft")
        {
            #FIND BY TITLE
            my @results = FindTitle ($RequestedValue);

            my $filename = "/home/Ex5/Answers/" . $RequestFilesArray[$RequestNumber];

            open ( my $answerFile, '>', $filename) or die "$!";

            for (my $a = 0; $a < @results; $a++)
            {
                print $answerFile $results[$a],"\n";
            }
            close $answerFile;

        }
        elsif ($RequestType eq "br")
        {
            #BOOK RETURN
            my $result = CheckIfCanBeReturned ($RequestedValue, $RequestFilesArray[$RequestNumber]);

            my $filename = "/home/Ex5/Answers/" . $RequestFilesArray[$RequestNumber];

            open ( my $answerFile, '>', $filename) or die "$!";
            print $answerFile $result;
            close $answerFile;
        }
        elsif ($RequestType eq "bb")
        {
            #BOOK BORROW
            my $result = CheckIfCanBeBorrowed ($RequestedValue, $RequestFilesArray[$RequestNumber]);

            my $filename = "/home/Ex5/Answers/" . $RequestFilesArray[$RequestNumber];

            open ( my $answerFile, '>', $filename) or die "$!";
            print $answerFile $result;
            close $answerFile;
        }
        else
        {
            print "something went wrong with this request";
        }
    }

    #deleting processed requests
    for ( my $e = 0; $e < @RequestFilesArray; $e++)
    {   
        my $removeReq = "/home/Ex5/Requests/" . $RequestFilesArray[$e];
        unlink $removeReq;
    }

#$continueWork =0;
}

2 个答案:

答案 0 :(得分:4)

在尝试测试之前,您已经编写了太多代码。您还在每个机会都启动了shell进程,而不是学习在Perl中实现事物的正确方法

第一个错误是使用ls来发现正在等待的工作。 ls每行打印多个文件,并使用奇怪的printf "$RequestFilesArray[$b]" | wc -m代替length $RequestFilesArray[$b]

将每行的整个行视为文件名

之后事情变得更糟

我建议如下

  • 从头开始

  • 在Perl中编写程序。 Perl不是一种shell语言

  • 非常小的增量进展,确保您的代码编译并完成每三或四行所需的内容。知道你是否正在增强工作代码而不是创建一个神奇的随机字符序列,这确实让你有信心

  • 了解如何调试。你似乎正盯着自己的代码,希望灵感以某人盯着他们的汽车引擎的方式罢工,希望看到为什么它不会开始

  • 删除请求文件作为处理请求的一部分,只有在处理完请求并成功写入答案文件后才能删除。它不应该在一个单独的循环中完成

答案 1 :(得分:0)

根据您提供的内容,我已经为您设计了一些伪代码,您可以将其用作某种模板。这是NO MEANS详尽无遗的。我认为@Borodin给出的建议是合理而谨慎的。

这都是未经测试的,很多新东西都是伪代码。但是,希望有一些面包屑可供学习。此外,正如我上面所述,您对Proc::Daemon::Init的使用是可疑的。至少,它是如此微不足道,它吞噬了正在发生的任何错误,你不知道脚本有什么问题。

#!/usr/bin/perl -wl

use strict;
use File::Basename;
use File::Spec;
use Proc::Daemon;
use Data::Dumper;

# turn off buffering
$|++;

#FUNCTIONS DEFINTIONS
sub FindAuthor
{
#try to find book by this author in the catalogue
}


sub FindTitle
{
#try to find book with this title in the catalogue
}


sub CheckIfCanBeReturned
{
#check if the book is borrowed and by whom
}

sub tail
{
  my $file = shift;

# do work
}

sub find_by
{
  my $file = shift;
  my $val  = shift;
  my $by   = shift;
  my @results;
  my $xt   = 0;

# sanity check args
# do work

  if ( $by eq 'author' )
  {
    my @results = FindByAuthor(blah);
  }
  elsif ( $by eq 'blah' )
  {
    @results = blah();
  }
  #...etc 

  # really should use File::Spec IE
  my $filename = File::Spec->catfile('home', 'Ex5', 'Answers', $file);

  # might be a good idea to either append or validate you're not clobbering
  # an existent file here because this is currently clobbering.
  open (my $answerFile, '>', $filename) or die "$!";

  for ( @results )
  {
    print $answerFile $_,"\n";
  }
  close $answerFile;

  # have some error checking in place and set $xt to 1 if an error occurs
  return $xt;
}

#attempt at daemonization
# whatever this is is completely broken methinks.
#Proc::Daemon::Init;

my $continueWork++;
my $r_dir = '/home/user/Requests';

$SIG{TERM} = sub { $continueWork = 0 };

# going with pseudocode
while ( $continueWork )
{
  #list all requests currently in the Request folder
  my @RequestFilesArray = grep(/[^\.]/, <$r_dir/*>);

  #the requests are formatted in such way,
  #that the first 2 letters indicate what the client wants to be done
  #and the rest is taken parameters used in the processing

  for my $request_file ( @RequestFilesArray )
  {
    my $result    = 0;

    $request_file = basename($request_file);
    my $cut       = length($request_file) - 1;
    my $work_on   = substr $request_file, 0, $cut;

    my $UserRequest = tail($request_file);
    my $fix       = length($UserRequest) - 1;
     $UserRequest = substr $UserRequest, 0, $fix;

    my $RequestType = substr $UserRequest, 0, 2;
    my $RequestedValue = substr $UserRequest, 3;

    if ($RequestType eq "fa")
    {
      #FIND BY AUTHOR
      $result = find_by($request_file, $RequestedValue, 'author');
    }
    elsif ($RequestType eq "ft")
    {
      #FIND BY TITLE
      $result = find_by($request_file, $RequestedValue, 'title');
    }
    elsif ($RequestType eq "br")
    {
      #BOOK RETURN
      $result = CheckIfCanBeReturned ($RequestedValue, $request_file) or handle();
    }
    elsif ($RequestType eq "bb")
    {
      #BOOK BORROW
      $result = CheckIfCanBeBorrowed ($RequestedValue, $request_file) or handle();
    }
    else
    {
      print STDERR "something went wrong with this request";
    }
  }

  #deleting processed requests
  if ( $result == 1 )
  {
      unlink $work_on;
  }

  sleep(2);
}

特别注意我的温和&#34;尝试使用find_by子例程干掉代码。您的原始脚本中有很多重复的代码,我将其移动到一个子例程中。 DRY eq不要重复自己&#39;。