在perl中运行后台进程,不要等待它完成

时间:2015-02-03 21:05:19

标签: perl parent-child wait

编辑:在这里找到了解决方案: http://www.webmasterworld.com/forum13/4416.htm

显然,在Linux服务器上做的比在Windows上更容易,谷歌也来了。

#Print out whatever you're going to print 
print "Stuff in progress. Thanks."

# Close the I/O handles 
close(STDIN); 
close(STDOUT); 
close(STDERR); 
# run your other code here

我根本不在perl工作,所以最简单的解决方案对我来说是最好的。我只想弄清楚如何修改这个程序,让它做我想做的事。

基本上这个程序是UI的代理。它的作用是获取程序名称,将命令打印到SAS程序文件,包括运行哪个SAS程序来创建输出,然后运行SAS程序,然后在最后输出$ pname.out文件,这就是最终打印到UI界面。

最新创建的SAS程序可能需要很长时间,所以我打算在孩提时代后台运行SAS程序,让SAS在完成后发送电子邮件。

在前台即父级,我想让perl程序返回一个带有一些基本信息的屏幕。

所以我的问题基本上是,如何告诉perl在后台运行子进程而不是等待它完成?

我试过“&”在系统的末尾(“$ SASROOT $ saschild”)命令,但它只是阻止程序运行。如果我使用没有“&”的命令,程序在孩子完成运行之前不会向浏览器屏幕返回任何内容。

任何帮助将不胜感激!

#!perl


use CGI ;



# YOUR MODIFICATIONS START HERE 

$TEMPFILES = "c:\\temp"; # This is the directory SAS will write its temporary files
$PROGROOT = "c:\\Inetpub\\wwwroot\\Effectiveness"; # This is the directory that contains the SAS programs to run
$DATAROOT = "c:\\Inetpub\\wwwroot\\Effectiveness" ; # This is the directory that contains the SAS data sets to be analysed

$SASROOT = "D:\\SAS\\SASFoundation\\9.2\\sas.exe"; # This is the full path name of the SAS System
$CGIBIN = "\\" ; # This is the alias of cgi-bin directory

$HTTPURL ="http://10.240.7.172" ;

$WEBROOT = "c:\\Inetpub\\wwwroot\\Effectiveness" ; # This is the root directory of webserver
$SASCFG = "d:\\SAS\\SASFoundation\\9.2\\SASV9.CFG" ; # This is the path to SAS config file

# YOUR MODIFICATIONS END HERE 

&get_request;

$PROGFILE = $rqpairs{'_program'};

if (!($PROGFILE =~ /^(\w[\w\.\-]+)$/))
{
    &error("The hidden field <CODE>_program</CODE> (= \"$PROGFILE\") is invalid or missing.");
}

$SASPROG="$PROGROOT\\$PROGFILE.sas";

if (!-f $SASPROG)
{
    &error("The program file \"$SASPROG\" does not exist.");
}


$pname = "p$$"; 
$cname = "c$$" ;
$repname = "r$$" ;

$random = int(rand("$$")); 
$pname = "$pname$random" ;
$cname = "$cname$random" ;
$repname = "$repname$random" ;


open(OUTCON, "+>>$TEMPFILES\\$cname.sas") ;
   print OUTCON "-set outfl \"$TEMPFILES\\$pname.out\" \n" ;
#print OUTCON "%include \"$TEMPFILES\\config.tpl\" \n";
   print OUTCON "%include \"$SASCFG\" \n";
close(OUTCON) ;


open(OUTFI,"+>>$TEMPFILES\\$pname.sas");


print OUTFI "options set=cgibin \"$CGIBIN/broker.pl\" ; \n" ;
print OUTFI "options set=location \"$DATAROOT\" ; \n" ;
print OUTFI "options set=webroot \"$WEBROOT\" ; \n" ;
print OUTFI "options set=outfl \"$TEMPFILES\\$pname.out\" ; \n" ;

print OUTFI "options set=outrep \"$WEBROOT\\$repname.xls\" ; \n" ;
print OUTFI "options set=repline \"$HTTPURL\\broker.pl?_program=_result\" ; \n" ;
print OUTFI "options set=excel_file=\"$repname.xls\" ; \n" ;

print OUTFI "options mprint ; \n" ;



while ( ($name,$value) = each %rqpairs )
{

 $value =~ s/([%()])/%$1/g ;


# $value =~ tr/ /\n/s ;
# $value =~ tr/,/,\n/s ;

# $in_string =~ tr/\+/ /s; # translate and squeeze multiple spaces


     if ($name ne "var")
   {
       print OUTFI "%let $name = %nrstr($value);\n";
   } 
}



print OUTFI "%include \"$SASPROG\";\n";
close(OUTFI) ;

$sasoptions = " -nodms -sysin $TEMPFILES\\$pname.sas -log $TEMPFILES\\$pname.log -work $TEMPFILES -sasuser $TEMPFILES" ;




#THIS IS THE FORKING OF THE PROCESS - only fork for rfcost application
my $pid = fork();
if (defined $pid && $pid == 0){

    #child
    close STDIN; #close connections to webpage
    close STDOUT; #close connections to webpage
    $saschild = " -nodms -sysin $TEMPFILES\\TestOutput.sas -log $TEMPFILES\\TestOutput.log -work $TEMPFILES -sasuser $TEMPFILES" ;


    system ("$SASROOT $saschild");
    exit(0);

}

#   sleep(120);
system ("$SASROOT $sasoptions");



#system ("$SASROOT -rsasuser -noterminal -sysparm -sysin $TEMPFILES\\$pname.sas -log $TEMPFILES\\$pname.log -config $TEMPFILES\\$cname.sas");


    print "HTTP/1.0 200 OK\n";
    print "Content-type: text/html\n\n";

    &html_trailer;

#print "$sasoptions" ;

   open (FILE, "$TEMPFILES\\$pname.out");
    while (<FILE>){ print; }
    close (FILE);

    &html_trailer;

#unlink("$TEMPFILES/$pname.sas");
#unlink("$TEMPFILES/$pname.log");
#unlink("$TEMPFILES/$pname.lst");
#unlink("$TEMPFILES/$pname.out");
#unlink("$TEMPFILES/$cname.sas");

sub get_request 
{

    if ($ENV{'REQUEST_METHOD'} eq "POST") {
        read(STDIN, $request, $ENV{'CONTENT_LENGTH'});
    } elsif ($ENV{'REQUEST_METHOD'} eq "GET" ) {
        $request = $ENV{'QUERY_STRING'};
    }

    %rqpairs = ();
    @rqarray = &url_decode(split(/[&=]/, $request));

    while ( $key = shift(@rqarray) )
       {
       $value = shift(@rqarray);

       if ( $rqpairs{$key} ne "" )
          {
          $rqpairs{$key} .= "," . $value;
          }
       else
          {
          $rqpairs{$key} = $value;
          }
       }
}

sub url_decode 
{


    foreach (@_) 
    {
        tr/+/ /;
        s/%(..)/pack("c",hex($1))/ge;
    }
    @_;
}

sub html_header 
{

    local($title) = @_;

    print "HTTP/1.0 200 OK\n";
    print "Content-type: text/html\n\n";
    print "<html><head>\n";
    print "<title>$title</title>\n";
    print "</head>\n<body>\n";
}

sub html_trailer 
{


    local($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
        = gmtime;

    local($mname) = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
                     "Aug", "Sep", "Oct", "Nov", "Dec")[$mon];
    local($dname) = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
                    "Sat")[$wday];
#    print "<br><p>Date: $hour:$min:$sec on $dname $mday $mname $year</p> \n" ;
    print "</body></html>\n";
}


sub error 
{

    local($msg) = @_;
    &html_header("SAS CGI Process Error");
    print "<H1>SAS CGI Process Error</H1>\n$msg\n";
    &html_trailer;
    exit 1;
}

2 个答案:

答案 0 :(得分:1)

使用exec(建议使用quicoju)在后台执行命令

请点击此处了解详情:http://perldoc.perl.org/functions/exec.html

  

exec PROGRAM LIST

     

exec函数执行系统命令,永不返回;如果你想让它返回,请使用system而不是exec。它失败并仅在命令不存在时返回false并且直接执行而不是通过系统的命令shell(见下文)。

您将在此主题中找到一个非常好的答案:What's the difference between Perl's backticks, system, and exec?

答案 1 :(得分:1)

有各种CPAN模块可以使任务更容易,例如http://search.cpan.org/~bzajac/Proc-Background-1.10/lib/Proc/Background.pm

话虽如此,我考虑引入一些作业队列,因此您的流程会将任务放入队列,并且单独的流程会将其选中以便处理,更易于管理...