2017-06-20 36 views
-1

我正在试图制作一个程序,它的工作方式类似于一个非常简单的Perl服务器。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; 
} 
+1

请提供一个最小的,可运行的问题演示。 – ikegami

+0

将错误发送到'/ dev/null'使得它很难调试。你应该开始解决这个问题! – ikegami

+0

尝试添加调试'print'语句,以便您可以查看变量的值。 – Barmar

回答

4

你已经写太多代码尝试测试它。您还可以在每个机会上启动shell进程,而不是学习在Perl中实现事物的正确方式。

第一个错误是使用ls来发现哪些作业正在等待。 ls每行打印多个文件,而且你把整个的每一行作为文件名,而是使用的离奇printf "$RequestFilesArray[$b]" | wc -mlength $RequestFilesArray[$b]

事情只会变得更糟后

我建议以下

  • 从头开始

  • 用Perl写你的程序。 Perl不是shell语言

  • 前进很小的增量,确保你的代码编译并做它应该每三四行。它奇迹的信心,知道你提高工作代码,而不是创造的随机字符一个神奇的序列

  • 了解如何调试。你似乎盯着你的代码,希望灵感能够以某人盯着他们的汽车发动机的方式发动,希望看到为什么它不会启动

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

0

以你提供了什么来完成,这里的一些伪代码,我发明了你,你可以作为有些模板使用。这是没有意义的。我认为@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); 
} 

请特别注意我的“温和”的尝试,通过使用find_by子程序枯竭你的代码。您的原始脚本中有很多重复的代码,我将其移入单个子例程中。 DRY eq'不要重复自己'。

+2

“*你使用Proc :: Daemon :: Init是可疑的。*”,这是一个正确和文件化的用法。也就是说,指示它将STDERR重定向到一个实际的文件而不是默认的'/ dev/null'会更有用。 – ikegami