Charlie has asked for the wisdom of the Perl Monks concerning the following question:

I want to execute a shell script from a Perl script; but without waiting on the shell script to complete before continuing to the next step the Perl script. I am looking for the syntax for
$ some_script &
A snippet of my code to illustrate is
qw/mhmail someone@somewhere.com -body $meg/ qw/get_mail/
Where the get_mail script accomplishes a list of things, like dial the ISP; establish a ppp connection and logon; run sendmail -q, run fetchmail, etc. Thankyou for your assistance.

Replies are listed 'Best First'.
Re: Don't want to wait
by lhoward (Vicar) on Jul 16, 2000 at 16:50 UTC
    t0mas gave you %95 of what you need. Use system to do the calls you need, just add the & at the end of the system call and your perl program won't wait for them to complete before proceeding. If you use exec control will never return to your perl program. Alternatively, you could do something with fork in your perl program, but that would be uglier and not really add any benefit.
    system "mhmail someone@somewhere.com -body $meg &"; system "get_mail &";
Re: Don't want to wait
by maverick (Curate) on Jul 16, 2000 at 20:34 UTC
    I would be tempted to handle it this way:
    my $pid = fork(); if ($pid == 0) { # child process my $exit = system("whatever command you want"); if ($exit != 0) { # handle error } exit; } # rest of the program that isn't waiting on the 'system' . . .

    This way you can handle any errors that might result from the system command, and not have to wait for it to finish.

    If later in your code you need to make sure that the system has finished before you go on, you can use waitpid($pid,0) to have this process pause until the other has exited.

    /\/\averick

Re: Don't want to wait
by t0mas (Priest) on Jul 16, 2000 at 16:12 UTC
    From perldoc perlfunc:
    The exec function executes a system command and never returns-- use system instead of exec if you want it to return. It fails and returns false only if the command does not exist and it is executed directly instead of via your system's command shell.

    Is exec get_mail what you want?

    /brother t0mas
      The exec function executes a system command and never returns
      I really think this part of the documentation should be modified a bit. (Anyone know who to contact?)

      When I first read that when I had a similar problem, I thought it meant did not return a value, and the "returns false only.." bit was put it as it is to emphasise that the function returning a value is a rare event.

      I would like it be changed to:
      "The exec function replaces the currently running process with the command or program called, unless the command or program does not exist. If the command or program does not exist, the call will fail and exec will return false."

Re: Don't want to wait
by ZZamboni (Curate) on Jul 17, 2000 at 04:10 UTC
    There are two ways of doing this that I can think of:
    1. Use system, and add an ampersand at the end, like this:
      system("command &");
      system uses a shell to execute the command, so it will correctly recognize the ampersand and put the code in the background. The disadvantages of this approach are that an extra process (the shell) gets executed, and that shell meta-character interpretation is done (this could also be considered an advantage, but it opens potential security concerns). The advantage is that it's easy to do.
    2. Use fork and exec, something like this:
      my $pid; if (defined ($pid=fork)) { if (!$pid) { # Execute command in the child exec ("command"); # If it returns, there was an error die "Error executing command: $!\n"; } # The parent continues unaffected, falls of the if stmt } else { die "Error in fork: $!\n"; }
      This has the advantages that it is more efficient (just your two processes are started) and that no shell metacharacters are interpreted (again, this could be a disadvantage depending on what you need). The slight disadvantage is that it's more complex to code.

      --ZZamboni